[READ-ONLY] Mirror of https://github.com/improsocial/impro An extensible Bluesky client for web impro.social
6

Configure Feed

Select the types of activity you want to include in your feed.

Use icon for close buttons

Grace Kind (Jul 9, 2026, 3:07 PM -0500) bf71dec7 2ab1aa56

+86 -74
+1 -1
package.json
··· 1 1 { 2 2 "name": "impro", 3 - "version": "0.17.120", 3 + "version": "0.17.121", 4 4 "type": "module", 5 5 "scripts": { 6 6 "start": "rm -rf \"${BUILD_DIR:-build}\" && NODE_ENV=development eleventy --serve",
+38 -55
src/css/style.css
··· 2085 2085 position: relative; 2086 2086 } 2087 2087 2088 + .close-icon { 2089 + width: 24px; 2090 + height: 24px; 2091 + } 2092 + 2088 2093 .account-switcher-add-icon .icon { 2089 2094 width: 24px; 2090 2095 height: 24px; ··· 2376 2381 top: 20px; 2377 2382 right: 20px; 2378 2383 color: var(--overlay-text-color); 2379 - font-size: 24px; 2380 2384 cursor: pointer; 2381 2385 background: var(--overlay-color); 2382 2386 width: 40px; ··· 2747 2751 color: var(--text-color); 2748 2752 border: var(--hair) solid var(--post-border-color); 2749 2753 background: light-dark(var(--lightest-gray), var(--dark-gray)); 2750 - width: 35px; 2751 - height: 35px; 2754 + width: 33px; 2755 + height: 33px; 2752 2756 cursor: pointer; 2757 + display: flex; 2758 + align-items: center; 2759 + justify-content: center; 2753 2760 } 2754 2761 2755 - .embed-preview-close-button span { 2756 - position: relative; 2757 - top: -1px; 2758 - font-size: 20px; 2762 + .embed-preview-close-button .close-icon { 2763 + width: 18px; 2764 + height: 18px; 2759 2765 } 2760 2766 2761 2767 .post-composer-image-preview { ··· 4273 4279 .message-reply-preview-clear { 4274 4280 background: none; 4275 4281 border: none; 4276 - font-size: 24px; 4277 - line-height: 1; 4278 4282 color: var(--text-color-muted); 4279 4283 cursor: pointer; 4280 4284 padding: 4px 8px; 4285 + display: flex; 4286 + align-items: center; 4281 4287 } 4282 4288 4283 4289 .message-embed-preview { ··· 4703 4709 display: none; 4704 4710 background: none; 4705 4711 border: none; 4706 - font-size: 24px; 4707 - line-height: 1; 4708 4712 cursor: pointer; 4709 4713 color: var(--text-color); 4710 4714 padding: 0 8px; ··· 4712 4716 4713 4717 @media (min-width: 800px) { 4714 4718 .reactions-dialog-close { 4715 - display: inline-block; 4719 + display: inline-flex; 4720 + align-items: center; 4716 4721 } 4717 4722 } 4718 4723 ··· 5324 5329 justify-content: center; 5325 5330 } 5326 5331 5327 - .search-clear-button span { 5328 - margin-top: -2px; 5332 + .search-clear-button .close-icon { 5333 + width: 16px; 5334 + height: 16px; 5329 5335 } 5330 5336 5331 5337 .search-results-container { ··· 6557 6563 font-weight: 600; 6558 6564 } 6559 6565 6560 - .image-alt-text-dialog-close-button { 6561 - background: none; 6562 - border: none; 6563 - font-size: 32px; 6564 - line-height: 1; 6565 - cursor: pointer; 6566 - padding: 0; 6567 - width: 32px; 6568 - height: 32px; 6569 - display: flex; 6570 - align-items: center; 6571 - justify-content: center; 6572 - border-radius: var(--icon-button-border-radius); 6573 - transition: background-color 0.2s; 6574 - } 6575 - 6576 - @media (min-width: 800px) { 6577 - .image-alt-text-dialog-close-button:hover { 6578 - background-color: light-dark(var(--light-gray), var(--dark-gray)); 6579 - } 6580 - } 6581 - 6582 6566 .image-alt-text-dialog-body { 6583 6567 display: flex; 6584 6568 flex-direction: column; ··· 6807 6791 top: 20px; 6808 6792 right: 20px; 6809 6793 color: var(--overlay-text-color); 6810 - font-size: 24px; 6811 6794 cursor: pointer; 6812 6795 background: var(--overlay-color); 6813 6796 width: 40px; ··· 7151 7134 display: flex; 7152 7135 align-items: center; 7153 7136 justify-content: center; 7154 - font-size: 16px; 7155 - line-height: 1; 7137 + } 7138 + 7139 + .muted-word-delete-button .close-icon { 7140 + width: 16px; 7141 + height: 16px; 7156 7142 } 7157 7143 7158 7144 .muted-word-delete-button span { ··· 7381 7367 background: none; 7382 7368 border: none; 7383 7369 padding: 0; 7384 - font-size: 24px; 7385 - line-height: 1; 7386 7370 color: var(--text-color-muted); 7387 7371 cursor: pointer; 7388 7372 } 7389 7373 7390 7374 @media (min-width: 800px) { 7391 7375 .account-switcher-close { 7392 - display: block; 7376 + display: flex; 7377 + align-items: center; 7393 7378 } 7394 7379 } 7395 7380 ··· 8096 8081 display: none; 8097 8082 background: none; 8098 8083 border: none; 8099 - font-size: 28px; 8100 - line-height: 1; 8101 8084 cursor: pointer; 8102 8085 color: var(--text-color); 8103 8086 padding: 0; ··· 8268 8251 .report-selected-clear { 8269 8252 background: none; 8270 8253 border: none; 8271 - font-size: 20px; 8272 - line-height: 1; 8273 8254 cursor: pointer; 8274 8255 color: var(--text-color-secondary); 8275 8256 padding: 0; ··· 8281 8262 border-radius: var(--icon-button-border-radius); 8282 8263 } 8283 8264 8265 + .report-selected-clear .close-icon { 8266 + width: 16px; 8267 + height: 16px; 8268 + } 8269 + 8284 8270 .report-submit-section { 8285 8271 display: flex; 8286 8272 flex-direction: column; ··· 8435 8421 right: 12px; 8436 8422 background: none; 8437 8423 border: none; 8438 - font-size: 24px; 8439 8424 cursor: pointer; 8440 8425 color: var(--text-color); 8441 8426 padding: 4px 8px; 8442 - line-height: 1; 8443 8427 opacity: 0.6; 8444 8428 } 8445 8429 8446 8430 @media (min-width: 800px) { 8447 8431 .post-notifications-dialog-close { 8448 - display: block; 8432 + display: flex; 8433 + align-items: center; 8449 8434 } 8450 8435 } 8451 8436 ··· 8542 8527 right: 12px; 8543 8528 background: none; 8544 8529 border: none; 8545 - font-size: 24px; 8546 8530 cursor: pointer; 8547 8531 color: var(--text-color); 8548 8532 padding: 4px 8px; 8549 - line-height: 1; 8550 8533 opacity: 0.6; 8551 8534 } 8552 8535 8553 8536 @media (min-width: 800px) { 8554 8537 .add-to-lists-dialog-close { 8555 - display: block; 8538 + display: flex; 8539 + align-items: center; 8556 8540 } 8557 8541 } 8558 8542 ··· 8772 8756 display: none; 8773 8757 background: none; 8774 8758 border: none; 8775 - font-size: 24px; 8776 8759 cursor: pointer; 8777 8760 color: var(--text-color); 8778 8761 padding: 4px 8px; 8779 - line-height: 1; 8780 8762 opacity: 0.6; 8781 8763 } 8782 8764 8783 8765 @media (min-width: 800px) { 8784 8766 .new-chat-dialog-close { 8785 - display: block; 8767 + display: flex; 8768 + align-items: center; 8786 8769 } 8787 8770 8788 8771 .new-chat-dialog-close:hover {
+2 -1
src/js/components/account-switcher-dialog.js
··· 11 11 import { circleCheckIconTemplate } from "/js/templates/icons/circleCheckIcon.template.js"; 12 12 import { chevronRightIconTemplate } from "/js/templates/icons/chevronRight.template.js"; 13 13 import { userPlusIconTemplate } from "/js/templates/icons/userPlusIcon.template.js"; 14 + import { closeIconTemplate } from "/js/templates/icons/closeIcon.template.js"; 14 15 15 16 class AccountSwitcherDialog extends Component { 16 17 connectedCallback() { ··· 113 114 ?disabled=${pendingAction !== null} 114 115 @click=${() => this.close()} 115 116 > 116 - &times; 117 + ${closeIconTemplate()} 117 118 </button> 118 119 </div> 119 120 <div
+2 -1
src/js/components/add-to-lists-dialog.js
··· 4 4 import { enableDragToDismiss } from "/js/utils.js"; 5 5 import { Signal, SignalSet, ReactiveStore, effect } from "/js/signals.js"; 6 6 import { isModerationList } from "/js/dataHelpers.js"; 7 + import { closeIconTemplate } from "/js/templates/icons/closeIcon.template.js"; 7 8 import "/js/components/infinite-scroll-container.js"; 8 9 9 10 class AddToListsDialog extends Component { ··· 114 115 aria-label="Close" 115 116 @click=${() => this.close()} 116 117 > 117 - &times; 118 + ${closeIconTemplate()} 118 119 </button> 119 120 <div class="add-to-lists-dialog-body"> 120 121 <div class="add-to-lists-dialog-header">
+2 -1
src/js/components/lightbox-image-group.js
··· 3 3 import { ImageLoader } from "/js/utils.js"; 4 4 import { chevronLeftIconTemplate } from "/js/templates/icons/chevronLeft.template.js"; 5 5 import { chevronRightIconTemplate } from "/js/templates/icons/chevronRight.template.js"; 6 + import { closeIconTemplate } from "/js/templates/icons/closeIcon.template.js"; 6 7 7 8 class LightboxDialog extends Component { 8 9 connectedCallback() { ··· 70 71 this.close(); 71 72 }} 72 73 > 73 - × 74 + ${closeIconTemplate()} 74 75 </div> 75 76 ${hasMultiple 76 77 ? html`
+3 -2
src/js/components/new-chat-dialog.js
··· 6 6 import { getDisplayName, MISSING_HANDLE } from "/js/dataHelpers.js"; 7 7 import { avatarTemplate } from "/js/templates/avatar.template.js"; 8 8 import { searchIconTemplate } from "/js/templates/icons/searchIcon.template.js"; 9 + import { closeIconTemplate } from "/js/templates/icons/closeIcon.template.js"; 9 10 import { showToast } from "/js/toasts.js"; 10 11 11 12 const CREATE_CHAT_ERROR_TOASTS = { ··· 239 240 data-testid="new-chat-dialog-close" 240 241 @click=${() => this.close()} 241 242 > 242 - &times; 243 + ${closeIconTemplate()} 243 244 </button> 244 245 </div> 245 246 <div class="new-chat-search-container"> ··· 265 266 aria-label="Clear search" 266 267 @click=${() => this._onClearSearch()} 267 268 > 268 - <span>×</span> 269 + ${closeIconTemplate()} 269 270 </button> 270 271 ` 271 272 : ""}
+5 -4
src/js/components/post-composer.js
··· 16 16 import { ScrollLock } from "/js/scrollLock.js"; 17 17 import { imageIconTemplate } from "/js/templates/icons/imageIcon.template.js"; 18 18 import { emojiIconTemplate } from "/js/templates/icons/emojiIcon.template.js"; 19 + import { closeIconTemplate } from "/js/templates/icons/closeIcon.template.js"; 19 20 import { showToast } from "/js/toasts.js"; 20 21 import { 21 22 validateVideoFile, ··· 75 76 onClose(); 76 77 }} 77 78 > 78 - <span>×</span> 79 + ${closeIconTemplate()} 79 80 </button> 80 81 ${externalLinkTemplate({ 81 82 url: data.url, ··· 114 115 onRemove(); 115 116 }} 116 117 > 117 - <span>×</span> 118 + ${closeIconTemplate()} 118 119 </button> 119 120 ${!isReady 120 121 ? html`<div class="video-preview-overlay"> ··· 157 158 onRemove(index); 158 159 }} 159 160 > 160 - <span>×</span> 161 + ${closeIconTemplate()} 161 162 </button> 162 163 <div class="alt-indicator ${img.alt ? "has-alt" : "no-alt"}"> 163 164 ${img.alt ? "✓ ALT" : "+ ALT"} ··· 342 343 this.handleQuotedEmbedPreviewClose(); 343 344 }} 344 345 > 345 - <span>×</span> 346 + ${closeIconTemplate()} 346 347 </button> 347 348 <div inert> 348 349 ${recordEmbedTemplate({
+2 -1
src/js/components/post-notifications-dialog.js
··· 3 3 import { ScrollLock } from "/js/scrollLock.js"; 4 4 import { enableDragToDismiss } from "/js/utils.js"; 5 5 import "/js/components/toggle-switch.js"; 6 + import { closeIconTemplate } from "/js/templates/icons/closeIcon.template.js"; 6 7 7 8 class PostNotificationsDialog extends Component { 8 9 connectedCallback() { ··· 47 48 class="post-notifications-dialog-close" 48 49 @click=${() => this.close()} 49 50 > 50 - &times; 51 + ${closeIconTemplate()} 51 52 </button> 52 53 <div class="post-notifications-dialog-body"> 53 54 <div class="post-notifications-dialog-header">
+2 -1
src/js/components/reactions-dialog.js
··· 5 5 import { enableDragToDismiss } from "/js/utils.js"; 6 6 import { avatarTemplate } from "/js/templates/avatar.template.js"; 7 7 import { getDisplayName, groupReactions } from "/js/dataHelpers.js"; 8 + import { closeIconTemplate } from "/js/templates/icons/closeIcon.template.js"; 8 9 9 10 class ReactionsDialog extends Component { 10 11 connectedCallback() { ··· 137 138 aria-label="Close reactions" 138 139 @click=${() => this._close()} 139 140 > 140 - &times; 141 + ${closeIconTemplate()} 141 142 </button> 142 143 </div> 143 144 <div
+5 -2
src/js/components/report-dialog.js
··· 4 4 import { enableDragToDismiss, resetScrollOnBlur } from "/js/utils.js"; 5 5 import { avatarTemplate } from "/js/templates/avatar.template.js"; 6 6 import { checkIconTemplate } from "/js/templates/icons/checkIcon.template.js"; 7 + import { closeIconTemplate } from "/js/templates/icons/closeIcon.template.js"; 7 8 import { BSKY_LABELER_DID } from "/js/config.js"; 8 9 9 10 const BSKY_ONLY_CATEGORIES = ["childSafety"]; ··· 346 347 return html` 347 348 <div class="report-selected-item"> 348 349 <span class="report-selected-title">${title}</span> 349 - <button class="report-selected-clear" @click=${onClear}>&times;</button> 350 + <button class="report-selected-clear" @click=${onClear}> 351 + ${closeIconTemplate()} 352 + </button> 350 353 </div> 351 354 `; 352 355 } ··· 647 650 > 648 651 <div class="report-dialog-content"> 649 652 <button class="report-dialog-close" @click=${() => this.close()}> 650 - &times; 653 + ${closeIconTemplate()} 651 654 </button> 652 655 <div class="report-dialog-body"> 653 656 ${stepTemplate({
+15
src/js/templates/icons/closeIcon.template.js
··· 1 + import { html } from "/js/lib/lit-html.js"; 2 + 3 + export function closeIconTemplate() { 4 + return html`<div class="icon close-icon"> 5 + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"> 6 + <path 7 + stroke="currentColor" 8 + stroke-linecap="round" 9 + stroke-linejoin="round" 10 + stroke-width="2" 11 + d="M12 12 7 7m5 5 5 5m-5-5 5-5m-5 5-5 5" 12 + /> 13 + </svg> 14 + </div>`; 15 + }
+2 -1
src/js/templates/postEmbed.template.js
··· 8 8 import { externalLinkTemplate } from "/js/templates/externalLink.template.js"; 9 9 import { avatarTemplate } from "/js/templates/avatar.template.js"; 10 10 import { infoIconTemplate } from "/js/templates/icons/infoIcon.template.js"; 11 + import { closeIconTemplate } from "/js/templates/icons/closeIcon.template.js"; 11 12 import { richTextTemplate } from "/js/templates/richText.template.js"; 12 13 import { postHeaderTextTemplate } from "/js/templates/postHeaderText.template.js"; 13 14 import { postLabelsTemplate } from "/js/templates/postLabels.template.js"; ··· 368 369 @click=${() => dialog.close()} 369 370 aria-label="Close" 370 371 > 371 - × 372 + ${closeIconTemplate()} 372 373 </button> 373 374 <p class="alt-text-dialog-text">${altText}</p>`, 374 375 dialog,
+3 -2
src/js/views/chatDetail.view.js
··· 35 35 import { Signal, ReactiveStore } from "/js/signals.js"; 36 36 import { getPermalinkForConvo } from "/js/navigation.js"; 37 37 import { emojiIconTemplate } from "/js/templates/icons/emojiIcon.template.js"; 38 + import { closeIconTemplate } from "/js/templates/icons/closeIcon.template.js"; 38 39 import "/js/components/infinite-scroll-container.js"; 39 40 import "/js/components/chat-input.js"; 40 41 import "/js/components/emoji-picker-dialog.js"; ··· 154 155 data-testid="message-embed-preview-remove" 155 156 @click=${() => clearStagedRecordEmbed()} 156 157 > 157 - <span>×</span> 158 + ${closeIconTemplate()} 158 159 </button> 159 160 ${body} 160 161 </div>`; ··· 193 194 data-testid="reply-preview-clear" 194 195 @click=${() => clearReply()} 195 196 > 196 - × 197 + ${closeIconTemplate()} 197 198 </button> 198 199 </div>`; 199 200 }
+2 -1
src/js/views/search.view.js
··· 1 1 import { html, render } from "/js/lib/lit-html.js"; 2 2 import { View } from "/js/views/view.js"; 3 3 import { searchIconTemplate } from "/js/templates/icons/searchIcon.template.js"; 4 + import { closeIconTemplate } from "/js/templates/icons/closeIcon.template.js"; 4 5 import { headerTemplate } from "/js/templates/header.template.js"; 5 6 import { classnames, debounce } from "/js/utils.js"; 6 7 import { Signal, ReactiveStore } from "/js/signals.js"; ··· 371 372 class="search-clear-button" 372 373 @click=${() => handleClearSearch()} 373 374 > 374 - <span>×</span> 375 + ${closeIconTemplate()} 375 376 </button> 376 377 ` 377 378 : ""}
+2 -1
src/js/views/settings/mutedWords.view.js
··· 2 2 import { html, render } from "/js/lib/lit-html.js"; 3 3 import { pageEffect } from "/js/router.js"; 4 4 import { headerTemplate } from "/js/templates/header.template.js"; 5 + import { closeIconTemplate } from "/js/templates/icons/closeIcon.template.js"; 5 6 import { auth } from "/js/auth.js"; 6 7 import { confirmModal } from "/js/modals/confirm.modal.js"; 7 8 import { differenceInHours, differenceInDays } from "/js/utils.js"; ··· 215 216 > 216 217 ${isRemoving 217 218 ? html`<div class="loading-spinner"></div>` 218 - : html`<span>×</span>`} 219 + : closeIconTemplate()} 219 220 </button> 220 221 </div> 221 222 </div>