[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.

Restructure button styles

Grace Kind (Jul 19, 2026, 11:30 PM -0500) b9c33b18 31707638

+206 -329
+2 -1
.gitignore
··· 3 3 .env 4 4 .context 5 5 tests/e2e/.results 6 + tests/.artifacts/visual 6 7 CLAUDE.md 7 8 .claude 8 9 plugins-local/* 9 - !plugins-local/.gitkeep 10 + !plugins-local/.gitkeep
+2 -1
package.json
··· 1 1 { 2 2 "name": "impro", 3 - "version": "0.18.25", 3 + "version": "0.18.26", 4 4 "type": "module", 5 5 "scripts": { 6 6 "start": "rm -rf \"${BUILD_DIR:-build}\" && NODE_ENV=development eleventy --serve", ··· 14 14 "test:unit": "node --import ./tests/unit/env.js --test-isolation=none --test-force-exit --test 'tests/unit/specs/**/*.test.js'", 15 15 "test:unit:coverage": "node --import ./tests/unit/env.js --test-isolation=none --test-force-exit --experimental-test-coverage --test-coverage-include='src/js/**' --test 'tests/unit/specs/**/*.test.js'", 16 16 "test:e2e": "npx playwright test", 17 + "test:visual": "VISUAL_CAPTURE_DIR=tests/.artifacts/visual npx playwright test tests/e2e/specs/views", 17 18 "serve:static": "node scripts/serve-static.js", 18 19 "prepare": "husky" 19 20 },
+73 -285
src/css/style.css
··· 11 11 12 12 button { 13 13 color: inherit; 14 + font-family: inherit; 14 15 } 15 16 16 17 html, ··· 187 188 --message-input-z-index: 4; 188 189 --reaction-palette-z-index: 5; 189 190 --toast-z-index: 5; 190 - --floating-compose-button-z-index: 6; 191 + --fab-z-index: 6; 191 192 --sidebar-z-index: 8; 192 193 --lightbox-container-z-index: 9; 193 194 --lightbox-z-index: 10; ··· 493 494 font-size: 15px; 494 495 } 495 496 496 - .back-button { 497 - display: flex; 497 + .text-pill-button { 498 + background: none; 499 + border: none; 500 + font-size: 15px; 501 + cursor: pointer; 502 + padding: 8px 12px; 503 + transition: color 0.2s; 504 + border-radius: var(--pill-button-border-radius); 505 + color: var(--highlight-color); 506 + } 507 + 508 + .text-pill-button:disabled { 509 + opacity: 0.5; 510 + cursor: default; 511 + } 512 + 513 + .icon-button { 514 + display: inline-flex; 498 515 align-items: center; 499 516 justify-content: center; 500 - text-decoration: none; 501 - border: none; 517 + padding: 0; 502 518 background: none; 503 - cursor: pointer; 519 + border: none; 504 520 color: var(--icon-button-color); 521 + cursor: pointer; 522 + text-decoration: none; 505 523 border-radius: var(--icon-button-border-radius); 524 + transition: background-color 0.2s; 525 + } 526 + 527 + .icon-button:disabled { 528 + opacity: 0.5; 529 + cursor: default; 530 + } 531 + 532 + .icon-button .icon { 533 + width: 24px; 534 + height: 24px; 535 + } 536 + 537 + @media (hover: hover) { 538 + .icon-button:not(:disabled):hover { 539 + background-color: var(--back-button-hover-color); 540 + } 541 + } 542 + 543 + .back-button { 506 544 height: 30px; 507 545 width: 30px; 508 - transition: background-color 0.2s; 509 546 } 510 547 511 548 .floating-back-button { ··· 531 568 height: 20px; 532 569 } 533 570 534 - @media (hover: hover) { 535 - .back-button:hover { 536 - background-color: var(--back-button-hover-color); 537 - } 538 - } 539 - 540 571 .menu-button { 541 - display: flex; 542 - align-items: center; 543 - justify-content: center; 544 - border: none; 545 - background: none; 546 - cursor: pointer; 547 - color: var(--text-color-muted); 548 572 font-size: 24px; 549 573 height: 30px; 550 574 width: 30px; 551 - border-radius: var(--icon-button-border-radius); 552 - transition: background-color 0.2s; 553 - } 554 - 555 - @media (hover: hover) { 556 - .menu-button:hover { 557 - background-color: var(--back-button-hover-color); 558 - } 559 575 } 560 576 561 577 @media (min-width: 800px) { 562 578 .menu-button { 563 579 display: none; 564 580 } 565 - } 566 - 567 - .header-icon-button { 568 - display: flex; 569 - align-items: center; 570 - justify-content: center; 571 - background: transparent; 572 - border: none; 573 - padding: 0; 574 - cursor: pointer; 575 - color: var(--text-color-muted); 576 - border-radius: var(--icon-button-border-radius); 577 - transition: background-color 0.2s; 578 - } 579 - 580 - @media (hover: hover) { 581 - .header-icon-button:not(:disabled):hover { 582 - background-color: var(--back-button-hover-color); 583 - } 584 - } 585 - 586 - .header-icon-button:disabled { 587 - opacity: 0.5; 588 - cursor: default; 589 581 } 590 582 591 583 .inbox-button { ··· 661 653 color: var(--text-color-muted); 662 654 } 663 655 664 - form button { 665 - width: 100%; 666 - display: flex; 667 - align-items: center; 668 - justify-content: center; 669 - gap: 8px; 670 - padding: 10px 20px; 671 - font-size: 15px; 672 - border-radius: var(--pill-button-border-radius); 673 - border: var(--hair) solid var(--post-border-color); 674 - background: var(--background-color); 675 - cursor: pointer; 676 - } 677 - 678 - form button.rounded-button { 656 + #login-form .rounded-button { 679 657 padding: 10px 20px; 680 658 } 681 659 682 - form button[type="submit"] { 683 - font-weight: normal; 684 - background: var(--primary-button-color); 685 - color: var(--primary-button-text-color); 686 - } 687 - 688 - form button[type="submit"] .loading-spinner { 660 + #login-form .rounded-button-primary .loading-spinner { 689 661 border-top-color: var(--primary-button-text-color); 690 662 border-left-color: transparent; 691 663 border-right-color: transparent; 692 664 border-bottom-color: transparent; 693 - } 694 - 695 - @media (hover: hover) { 696 - form button[type="submit"]:hover { 697 - background: var(--primary-button-hover-color); 698 - } 699 - } 700 - 701 - form button:disabled { 702 - opacity: 0.5; 703 - } 704 - 705 - @media (hover: hover) { 706 - form button:hover { 707 - background: var(--post-hover-color); 708 - } 709 665 } 710 666 711 667 input, ··· 1361 1317 margin-left: 10px; 1362 1318 width: fit-content; 1363 1319 padding: 12px 20px; 1364 - background-color: var(--primary-button-color); 1365 - color: var(--off-white); 1366 - border: none; 1367 - border-radius: var(--pill-button-border-radius); 1368 1320 font-size: 16px; 1369 1321 font-weight: 600; 1370 - cursor: pointer; 1371 - align-items: center; 1372 - justify-content: center; 1373 - gap: 8px; 1374 - transition: background-color 0.2s; 1375 - } 1376 - 1377 - @media (hover: hover) { 1378 - .sidebar-compose-button:hover { 1379 - background-color: var(--primary-button-hover-color); 1380 - } 1381 1322 } 1382 1323 1383 1324 .sidebar-compose-button .icon { ··· 1812 1753 color: var(--text-color-muted); 1813 1754 font-size: 13px; 1814 1755 cursor: pointer; 1815 - font-family: inherit; 1816 1756 margin-left: 2px; 1817 1757 } 1818 1758 .who-can-reply-badge .icon { ··· 3459 3399 width: 32px; 3460 3400 height: 32px; 3461 3401 background-color: var(--overlay-color-medium); 3462 - border-radius: 50%; 3402 + border-radius: var(--circular-button-border-radius); 3463 3403 } 3464 3404 3465 3405 .video-preview-play-button::after { ··· 4321 4261 } 4322 4262 4323 4263 .chat-join-link-action { 4324 - display: flex; 4325 - align-items: center; 4326 - justify-content: center; 4327 4264 gap: 6px; 4328 4265 padding: 8px 14px; 4329 - border-radius: var(--pill-button-border-radius); 4330 - border: none; 4331 - cursor: pointer; 4332 - font-size: 14px; 4333 4266 font-weight: 600; 4334 - background: var(--primary-button-color); 4335 - color: var(--primary-button-text-color); 4336 4267 width: 100%; 4337 4268 } 4338 4269 4339 4270 .chat-join-link-action[disabled] { 4340 - opacity: 0.6; 4341 - cursor: default; 4342 4271 background: var(--secondary-button-color); 4343 4272 color: var(--text-color); 4344 4273 } ··· 4594 4523 flex-shrink: 0; 4595 4524 width: 32px; 4596 4525 height: 32px; 4597 - border-radius: 50%; 4526 + border-radius: var(--circular-button-border-radius); 4598 4527 background: transparent; 4599 4528 border: none; 4600 4529 display: flex; ··· 4631 4560 height: 40px; 4632 4561 border-radius: var(--circular-button-border-radius); 4633 4562 color: var(--primary-button-text-color); 4634 - background-color: var(--highlight-color); 4563 + background-color: var(--primary-button-color); 4635 4564 border: none; 4636 4565 display: flex; 4637 4566 align-items: center; ··· 6165 6094 } 6166 6095 } 6167 6096 6168 - .post-composer-cancel-button { 6169 - background: none; 6170 - border: none; 6171 - font-size: 15px; 6172 - cursor: pointer; 6173 - padding: 8px 12px; 6174 - transition: color 0.2s; 6175 - border-radius: var(--pill-button-border-radius); 6176 - color: var(--highlight-color); 6177 - } 6178 - 6179 6097 .post-composer-drafts-button { 6180 - background: none; 6181 - border: none; 6182 - font-size: 15px; 6183 - cursor: pointer; 6184 - padding: 8px 12px; 6185 - transition: color 0.2s; 6186 - border-radius: var(--pill-button-border-radius); 6187 - color: var(--highlight-color); 6188 6098 margin-left: auto; 6189 6099 margin-right: 8px; 6190 - } 6191 - 6192 - .post-composer-drafts-button:disabled { 6193 - opacity: 0.5; 6194 - cursor: default; 6195 6100 } 6196 6101 6197 6102 .post-composer-body { ··· 6295 6200 } 6296 6201 6297 6202 .post-composer-add-post-button { 6298 - background: none; 6299 - border: none; 6300 6203 padding: 6px; 6301 - cursor: pointer; 6302 - display: flex; 6303 - align-items: center; 6304 - justify-content: center; 6305 - border-radius: var(--icon-button-border-radius); 6306 - transition: background-color 0.2s; 6307 6204 } 6308 6205 6309 6206 @media (hover: hover) { 6310 - .post-composer-add-post-button:hover { 6207 + .post-composer-add-post-button:not(:disabled):hover { 6311 6208 background-color: var(--background-color-secondary); 6312 6209 } 6313 6210 } ··· 6363 6260 } 6364 6261 6365 6262 .image-picker-button { 6366 - background: none; 6367 - border: none; 6368 6263 padding: 6px; 6369 - cursor: pointer; 6370 - display: flex; 6371 - align-items: center; 6372 - justify-content: center; 6373 - border-radius: var(--icon-button-border-radius); 6374 - transition: background-color 0.2s; 6375 6264 } 6376 6265 6377 6266 @media (hover: hover) { 6378 - .image-picker-button:hover { 6267 + .image-picker-button:not(:disabled):hover { 6379 6268 background-color: var(--background-color-secondary); 6380 - } 6381 - } 6382 - 6383 - .image-picker-button:disabled { 6384 - opacity: 0.4; 6385 - cursor: default; 6386 - } 6387 - 6388 - @media (hover: hover) { 6389 - .image-picker-button:disabled:hover { 6390 - background-color: transparent; 6391 6269 } 6392 6270 } 6393 6271 ··· 6403 6281 } 6404 6282 6405 6283 .post-composer-emoji-button { 6406 - background: none; 6407 - border: none; 6408 6284 padding: 6px; 6409 - cursor: pointer; 6410 - display: flex; 6411 - align-items: center; 6412 - justify-content: center; 6413 - border-radius: var(--icon-button-border-radius); 6414 6285 color: var(--highlight-color); 6415 - transition: background-color 0.2s; 6416 6286 } 6417 6287 6418 6288 @media (hover: hover) { 6419 - .post-composer-emoji-button:hover { 6289 + .post-composer-emoji-button:not(:disabled):hover { 6420 6290 background-color: var(--background-color-secondary); 6421 6291 } 6422 6292 } ··· 6474 6344 color: var(--error-color); 6475 6345 } 6476 6346 6477 - .floating-compose-button { 6347 + .fab { 6478 6348 display: flex; 6479 6349 position: fixed; 6480 6350 bottom: calc(70px + var(--safe-area-inset-bottom)); ··· 6483 6353 height: 60px; 6484 6354 border-radius: var(--circular-button-border-radius); 6485 6355 background-color: var(--primary-button-color); 6486 - color: var(--off-white); 6356 + color: var(--primary-button-text-color); 6487 6357 border: none; 6488 6358 cursor: pointer; 6489 6359 box-shadow: var(--shadow-color-light); 6490 - z-index: var(--floating-compose-button-z-index); 6360 + z-index: var(--fab-z-index); 6491 6361 align-items: center; 6492 6362 justify-content: center; 6493 6363 transition: ··· 6496 6366 } 6497 6367 6498 6368 @media (hover: hover) { 6499 - .floating-compose-button:hover { 6369 + .fab:hover { 6500 6370 transform: scale(1.05); 6501 6371 box-shadow: var(--shadow-color-hover); 6502 6372 } 6503 6373 } 6504 6374 6505 - .floating-compose-button:active { 6375 + .fab:active { 6506 6376 transform: scale(0.95); 6507 6377 } 6508 6378 ··· 6886 6756 } 6887 6757 6888 6758 .modal-dialog-button.cancel-button { 6889 - background-color: light-dark(var(--lightest-gray), var(--light-gray)); 6759 + background-color: var(--secondary-button-color); 6890 6760 } 6891 6761 6892 6762 @media (hover: hover) { 6893 6763 .modal-dialog-button.cancel-button:hover { 6894 - background-color: light-dark(var(--lighter-gray), var(--light-gray)); 6764 + background-color: var(--secondary-button-hover-color); 6895 6765 } 6896 6766 } 6897 6767 6898 6768 .modal-dialog-button.primary-button { 6899 6769 background-color: var(--primary-button-color); 6900 - color: var(--off-white); 6770 + color: var(--primary-button-text-color); 6901 6771 } 6902 6772 6903 6773 .modal-dialog-button.danger-button { 6904 6774 background-color: var(--error-color); 6905 - color: var(--off-white); 6775 + color: var(--primary-button-text-color); 6906 6776 } 6907 6777 6908 6778 .modal-dialog-button.danger-subtle-button { ··· 7431 7301 } 7432 7302 7433 7303 .settings-button { 7434 - display: flex; 7435 - align-items: center; 7436 - justify-content: center; 7437 7304 gap: 6px; 7438 7305 width: 100%; 7439 7306 padding: 10px; 7440 - border-radius: var(--pill-button-border-radius); 7441 - border: none; 7442 - background: var(--highlight-color); 7443 - color: white; 7444 7307 font-size: 15px; 7445 - font-weight: 600; 7446 - cursor: pointer; 7447 - } 7448 - 7449 - .settings-button:disabled { 7450 - opacity: 0.5; 7451 - cursor: default; 7452 7308 } 7453 7309 7454 7310 .settings-button .plus-icon { ··· 7457 7313 } 7458 7314 7459 7315 .settings-button .loading-spinner { 7460 - border-color: rgba(255, 255, 255, 0.3); 7461 - border-top-color: white; 7316 + border-color: color-mix( 7317 + in srgb, 7318 + var(--primary-button-text-color) 30%, 7319 + transparent 7320 + ); 7321 + border-top-color: var(--primary-button-text-color); 7462 7322 } 7463 7323 7464 7324 .muted-word-delete-button .loading-spinner { ··· 7539 7399 border-radius: var(--pill-button-border-radius); 7540 7400 border: var(--hair) solid var(--post-border-color); 7541 7401 background: none; 7542 - color: var(--link-color); 7402 + color: var(--text-link-color); 7543 7403 cursor: pointer; 7544 7404 font-size: 12px; 7545 7405 font-weight: 600; ··· 7555 7415 flex-shrink: 0; 7556 7416 width: 28px; 7557 7417 height: 28px; 7558 - border-radius: 50%; 7418 + border-radius: var(--circular-button-border-radius); 7559 7419 border: var(--hair) solid var(--post-border-color); 7560 7420 background: none; 7561 7421 color: var(--text-color-muted); ··· 7791 7651 .drafts-dialog-back { 7792 7652 position: absolute; 7793 7653 left: 0; 7794 - background: none; 7795 - border: none; 7796 - font-size: 15px; 7797 - cursor: pointer; 7798 - padding: 8px 12px; 7799 - transition: color 0.2s; 7800 - border-radius: var(--pill-button-border-radius); 7801 - color: var(--highlight-color); 7802 7654 } 7803 7655 7804 7656 .drafts-dialog-list { ··· 7909 7761 margin-bottom: 4px; 7910 7762 } 7911 7763 7912 - .draft-item-delete { 7913 - background: none; 7914 - border: none; 7915 - color: var(--text-color-muted); 7916 - cursor: pointer; 7917 - border-radius: var(--icon-button-border-radius); 7918 - transition: background-color 0.2s; 7919 - } 7920 - 7921 7764 .draft-item-delete .icon { 7922 7765 width: 18px; 7923 7766 height: 18px; 7924 - } 7925 - 7926 - @media (hover: hover) { 7927 - .draft-item-delete:hover { 7928 - background-color: var(--back-button-hover-color); 7929 - } 7930 7767 } 7931 7768 7932 7769 .account-switcher-content { ··· 8427 8264 } 8428 8265 8429 8266 .error-state button { 8430 - border: none; 8431 - border-radius: var(--pill-button-border-radius); 8432 - cursor: pointer; 8433 - padding: 8px 16px; 8434 8267 margin-top: 16px; 8435 8268 } 8436 8269 ··· 9178 9011 color: var(--primary-button-text-color); 9179 9012 height: 33px; 9180 9013 width: 33px; 9181 - border-radius: 50%; 9014 + border-radius: var(--circular-button-border-radius); 9182 9015 transition: background-color 0.2s; 9183 9016 } 9184 9017 ··· 9197 9030 .new-chat-button .icon { 9198 9031 width: 16px; 9199 9032 height: 16px; 9200 - } 9201 - 9202 - .new-chat-fab { 9203 - display: flex; 9204 - position: fixed; 9205 - bottom: calc(70px + var(--safe-area-inset-bottom)); 9206 - right: 20px; 9207 - width: 60px; 9208 - height: 60px; 9209 - border-radius: var(--circular-button-border-radius); 9210 - background-color: var(--primary-button-color); 9211 - color: var(--off-white); 9212 - border: none; 9213 - cursor: pointer; 9214 - box-shadow: var(--shadow-color-light); 9215 - z-index: var(--floating-compose-button-z-index); 9216 - align-items: center; 9217 - justify-content: center; 9218 - transition: transform 0.2s; 9219 - } 9220 - 9221 - .new-chat-fab:active { 9222 - transform: scale(0.95); 9223 9033 } 9224 9034 9225 9035 .new-chat-fab .icon { ··· 9487 9297 border: none; 9488 9298 font-size: 16px; 9489 9299 cursor: pointer; 9490 - color: var(--link-color); 9300 + color: var(--text-link-color); 9491 9301 padding: 4px 0; 9492 9302 } 9493 9303 ··· 9572 9382 position: absolute; 9573 9383 width: 24px; 9574 9384 height: 24px; 9575 - border-radius: 50%; 9385 + border-radius: var(--circular-button-border-radius); 9576 9386 background-color: light-dark(var(--lightest-gray), var(--dark-gray)); 9577 9387 border: 1px solid light-dark(var(--lighter-gray), var(--light-gray)); 9578 9388 display: flex; ··· 9905 9715 display: flex; 9906 9716 align-items: center; 9907 9717 gap: 12px; 9908 - } 9909 - 9910 - .icon-button { 9911 - display: inline-flex; 9912 - align-items: center; 9913 - justify-content: center; 9914 - padding: 0; 9915 - background: none; 9916 - border: none; 9917 - color: inherit; 9918 - cursor: pointer; 9919 - text-decoration: none; 9920 - } 9921 - 9922 - .icon-button:disabled { 9923 - opacity: 0.5; 9924 - cursor: default; 9925 - } 9926 - 9927 - .icon-button .icon { 9928 - width: 24px; 9929 - height: 24px; 9930 9718 } 9931 9719 9932 9720 .plugin-list-item.uninstalling { ··· 10458 10246 flex: 0 0 auto; 10459 10247 padding: 8px 14px; 10460 10248 border: 1px solid color-mix(in srgb, var(--highlight-color) 35%, transparent); 10461 - border-radius: 999px; 10249 + border-radius: var(--pill-button-border-radius); 10462 10250 background: transparent; 10463 10251 color: var(--highlight-color); 10464 10252 font-size: 13px;
+25
tests/e2e/base.js
··· 3 3 import path from "node:path"; 4 4 5 5 const cssCoverageDir = process.env.CSS_COVERAGE_DIR; 6 + const visualCaptureDir = process.env.VISUAL_CAPTURE_DIR; 7 + 8 + function visualCapturePath(testInfo) { 9 + const fileName = path.basename(testInfo.file, ".test.js"); 10 + const title = testInfo.title 11 + .replace(/[^a-z0-9]+/gi, "-") 12 + .replace(/^-|-$/g, "") 13 + .slice(0, 120); 14 + return path.join( 15 + visualCaptureDir, 16 + testInfo.project.name, 17 + fileName, 18 + `${title || testInfo.testId}.png`, 19 + ); 20 + } 6 21 7 22 export const test = baseTest.extend({ 8 23 page: async ({ page, browserName }, use, testInfo) => { ··· 22 37 }); 23 38 24 39 await use(page); 40 + 41 + if (visualCaptureDir) { 42 + const screenshotPath = visualCapturePath(testInfo); 43 + fs.mkdirSync(path.dirname(screenshotPath), { recursive: true }); 44 + await page.screenshot({ 45 + path: screenshotPath, 46 + fullPage: true, 47 + animations: "disabled", 48 + }); 49 + } 25 50 26 51 if (collectCssCoverage) { 27 52 const entries = await page.coverage.stopCSSCoverage();
+2 -2
src/js/components/drafts-dialog.js
··· 144 144 </div> 145 145 <div class="draft-item-side"> 146 146 <button 147 - class="draft-item-delete" 147 + class="icon-button draft-item-delete" 148 148 data-testid="draft-item-delete" 149 149 aria-label="Delete draft" 150 150 @click=${(e) => { ··· 268 268 <div class="drafts-dialog-content"> 269 269 <div class="drafts-dialog-header"> 270 270 <button 271 - class="drafts-dialog-back" 271 + class="text-pill-button drafts-dialog-back" 272 272 data-testid="drafts-dialog-back" 273 273 @click=${() => this.close()} 274 274 >
+5 -5
src/js/components/post-composer.js
··· 558 558 <div class="post-composer-content"> 559 559 <div class="post-composer-top-bar"> 560 560 <button 561 - class="post-composer-cancel-button" 561 + class="text-pill-button post-composer-cancel-button" 562 562 @click=${async () => { 563 563 if (await this.confirmClose()) { 564 564 this.close(); ··· 569 569 </button> 570 570 ${!this.replyTo && draftsEnabled 571 571 ? html`<button 572 - class="post-composer-drafts-button" 572 + class="text-pill-button post-composer-drafts-button" 573 573 data-testid="composer-drafts-button" 574 574 .disabled=${isSavingDraft} 575 575 @click=${() => this.handleDraftsButtonClick()} ··· 644 644 }} 645 645 /> 646 646 <button 647 - class="image-picker-button" 647 + class="icon-button image-picker-button" 648 648 @click=${() => this.handleMediaButtonClick()} 649 649 .disabled=${hasVideo || activePost.images.length >= 4} 650 650 > ··· 653 653 <div class="post-composer-emoji-wrapper"> 654 654 <button 655 655 type="button" 656 - class="post-composer-emoji-button" 656 + class="icon-button post-composer-emoji-button" 657 657 aria-label="Open emoji picker" 658 658 @click=${(e) => this.handleEmojiButtonClick(e)} 659 659 > ··· 670 670 <div class="post-composer-bottom-bar-right"> 671 671 ${canAddPost 672 672 ? html`<button 673 - class="post-composer-add-post-button" 673 + class="icon-button post-composer-add-post-button" 674 674 data-testid="composer-add-post-button" 675 675 aria-label="Add another post" 676 676 @click=${() => this.handleAddPost()}
+1 -1
src/js/templates/chatJoinLinkEmbed.template.js
··· 110 110 const iconFn = ACTION_ICONS[action.icon]; 111 111 const icon = iconFn ? iconFn() : null; 112 112 return html`<button 113 - class="chat-join-link-action chat-join-link-action-${action.type}" 113 + class="rounded-button rounded-button-primary chat-join-link-action chat-join-link-action-${action.type}" 114 114 data-testid="join-link-embed-action" 115 115 data-teststate=${action.type} 116 116 ?disabled=${action.disabled}
+1 -1
src/js/templates/floatingComposeButton.template.js
··· 3 3 4 4 export function floatingComposeButtonTemplate({ onClick }) { 5 5 return html`<button 6 - class="floating-compose-button" 6 + class="fab floating-compose-button" 7 7 data-testid="floating-compose-button" 8 8 @click=${() => onClick()} 9 9 >
+2 -2
src/js/templates/header.template.js
··· 44 44 > 45 45 ${leftButton === "menu" 46 46 ? html`<button 47 - class="menu-button" 47 + class="icon-button menu-button" 48 48 data-testid="menu-button" 49 49 @click=${onClickMenuButton} 50 50 > 51 51 ${menuIconTemplate()} 52 52 </button>` 53 53 : html`<button 54 - class="back-button" 54 + class="icon-button back-button" 55 55 data-testid="back-button" 56 56 @click=${onClickBackButton 57 57 ? () => onClickBackButton()
+3 -1
src/js/templates/postFeed.template.js
··· 270 270 console.error(error); 271 271 return html`<div class="error-state"> 272 272 <div>Error loading posts</div> 273 - <button @click=${() => window.location.reload()}>Try again</button> 273 + <button class="rounded-button" @click=${() => window.location.reload()}> 274 + Try again 275 + </button> 274 276 </div>`; 275 277 } 276 278 }
+1 -1
src/js/templates/sidebar.template.js
··· 302 302 })} 303 303 ${onClickComposeButton 304 304 ? html`<button 305 - class="sidebar-compose-button" 305 + class="rounded-button rounded-button-primary sidebar-compose-button" 306 306 data-testid="sidebar-compose-button" 307 307 @click=${() => onClickComposeButton()} 308 308 >
+5 -3
src/js/views/chat.view.js
··· 136 136 function inboxButtonTemplate({ hasUnreadRequests }) { 137 137 return html` 138 138 <a 139 - class="header-icon-button inbox-button" 139 + class="icon-button inbox-button" 140 140 href="/messages/inbox" 141 141 aria-label=${hasUnreadRequests ? "Requests (unread)" : "Requests"} 142 142 data-testid="inbox-button" ··· 183 183 console.error(error); 184 184 return html`<div class="error-state"> 185 185 <div>There was an error loading conversations.</div> 186 - <button @click=${() => window.location.reload()}>Try again</button> 186 + <button class="rounded-button" @click=${() => window.location.reload()}> 187 + Try again 188 + </button> 187 189 </div>`; 188 190 } 189 191 ··· 244 246 })()} 245 247 </main> 246 248 <button 247 - class="new-chat-fab" 249 + class="fab new-chat-fab" 248 250 aria-label="New chat" 249 251 data-testid="new-chat-fab" 250 252 @click=${() => handleNewChatClick()}
+9 -2
src/js/views/chatDetail.view.js
··· 1306 1306 return html`<div class="error-state" data-testid="convo-not-found"> 1307 1307 <h3>Not Found</h3> 1308 1308 <div>Conversation not found</div> 1309 - <button @click=${() => window.location.reload()}>Try again</button> 1309 + <button 1310 + class="rounded-button" 1311 + @click=${() => window.location.reload()} 1312 + > 1313 + Try again 1314 + </button> 1310 1315 </div>`; 1311 1316 } 1312 1317 console.error(error); 1313 1318 return html`<div class="error-state" data-testid="messages-error"> 1314 1319 <div>There was an error loading messages.</div> 1315 - <button @click=${() => window.location.reload()}>Try again</button> 1320 + <button class="rounded-button" @click=${() => window.location.reload()}> 1321 + Try again 1322 + </button> 1316 1323 </div>`; 1317 1324 } 1318 1325
+3 -1
src/js/views/chatRequests.view.js
··· 207 207 console.error(error); 208 208 return html`<div class="error-state"> 209 209 <div>There was an error loading chat requests.</div> 210 - <button @click=${() => window.location.reload()}>Try again</button> 210 + <button class="rounded-button" @click=${() => window.location.reload()}> 211 + Try again 212 + </button> 211 213 </div>`; 212 214 } 213 215
+4 -1
src/js/views/communityPluginListing.view.js
··· 171 171 if (loadError) { 172 172 return html`<div class="error-state"> 173 173 <div>Failed to load plugin</div> 174 - <button @click=${() => window.location.reload()}> 174 + <button 175 + class="rounded-button" 176 + @click=${() => window.location.reload()} 177 + > 175 178 Try again 176 179 </button> 177 180 </div>`;
+3 -1
src/js/views/communityPlugins.view.js
··· 33 33 ${error 34 34 ? html`<div class="error-state"> 35 35 <div>Failed to load plugins</div> 36 - <button @click=${() => loadListings()}>Try again</button> 36 + <button class="rounded-button" @click=${() => loadListings()}> 37 + Try again 38 + </button> 37 39 </div>` 38 40 : !listings 39 41 ? html`<div
+1 -1
src/js/views/feeds.view.js
··· 240 240 </div>`; 241 241 } 242 242 return html`<button 243 - class="header-icon-button header-edit-button" 243 + class="icon-button header-edit-button" 244 244 data-testid="feeds-edit-button" 245 245 aria-label="Edit feeds" 246 246 @click=${() => state.$isEditing.set(true)}
+6 -2
src/js/views/groupChatDetails.view.js
··· 112 112 return html`<div class="error-state" data-testid="convo-not-found"> 113 113 <h3>Not Found</h3> 114 114 <div>Conversation not found</div> 115 - <button @click=${() => window.location.reload()}>Try again</button> 115 + <button class="rounded-button" @click=${() => window.location.reload()}> 116 + Try again 117 + </button> 116 118 </div>`; 117 119 } 118 120 console.error(error); 119 121 return html`<div class="error-state" data-testid="group-details-error"> 120 122 <div>There was an error loading the group chat.</div> 121 - <button @click=${() => window.location.reload()}>Try again</button> 123 + <button class="rounded-button" @click=${() => window.location.reload()}> 124 + Try again 125 + </button> 122 126 </div>`; 123 127 } 124 128
+7 -2
src/js/views/home.view.js
··· 194 194 >View profile</a 195 195 ><br />` 196 196 : ""} 197 - <button @click=${() => window.location.reload()}>Try again</button> 197 + <button 198 + class="rounded-button" 199 + @click=${() => window.location.reload()} 200 + > 201 + Try again 202 + </button> 198 203 </div> 199 204 </div>`; 200 205 } ··· 229 234 onClickMenuButton: () => handleMenuClick(), 230 235 rightItemTemplate: () => html` 231 236 <a 232 - class="header-icon-button feeds-button" 237 + class="icon-button feeds-button" 233 238 href="/feeds" 234 239 aria-label="Feeds" 235 240 data-testid="feeds-button"
+3 -1
src/js/views/notifications.view.js
··· 596 596 console.error(error); 597 597 return html`<div class="error-state"> 598 598 <div>There was an error loading notifications.</div> 599 - <button @click=${() => window.location.reload()}>Try again</button> 599 + <button class="rounded-button" @click=${() => window.location.reload()}> 600 + Try again 601 + </button> 600 602 </div>`; 601 603 } 602 604
+3 -1
src/js/views/postLikes.view.js
··· 31 31 console.error(error); 32 32 return html`<div class="error-state"> 33 33 <div>Error loading likes</div> 34 - <button @click=${() => window.location.reload()}>Try again</button> 34 + <button class="rounded-button" @click=${() => window.location.reload()}> 35 + Try again 36 + </button> 35 37 </div>`; 36 38 } 37 39
+3 -1
src/js/views/postQuotes.view.js
··· 33 33 console.error(error); 34 34 return html`<div class="error-state"> 35 35 <div>Error loading quotes</div> 36 - <button @click=${() => window.location.reload()}>Try again</button> 36 + <button class="rounded-button" @click=${() => window.location.reload()}> 37 + Try again 38 + </button> 37 39 </div>`; 38 40 } 39 41
+3 -1
src/js/views/postReposts.view.js
··· 31 31 console.error(error); 32 32 return html`<div class="error-state"> 33 33 <div>Error loading reposts</div> 34 - <button @click=${() => window.location.reload()}>Try again</button> 34 + <button class="rounded-button" @click=${() => window.location.reload()}> 35 + Try again 36 + </button> 35 37 </div>`; 36 38 } 37 39
+12 -2
src/js/views/postThread.view.js
··· 60 60 ) { 61 61 return html`<div class="error-state" data-testid="post-not-found"> 62 62 <div>Post not found</div> 63 - <button @click=${() => window.location.reload()}>Try again</button> 63 + <button 64 + class="rounded-button" 65 + @click=${() => window.location.reload()} 66 + > 67 + Try again 68 + </button> 64 69 </div>`; 65 70 } else { 66 71 console.error(error); 67 72 return html`<div class="error-state" data-testid="thread-error"> 68 73 <div>Error loading thread</div> 69 - <button @click=${() => window.location.reload()}>Try again</button> 74 + <button 75 + class="rounded-button" 76 + @click=${() => window.location.reload()} 77 + > 78 + Try again 79 + </button> 70 80 </div>`; 71 81 } 72 82 }
+9 -2
src/js/views/profile.view.js
··· 278 278 return html`<div class="error-state"> 279 279 <h3>Not Found</h3> 280 280 <div>${message}</div> 281 - <button @click=${() => window.location.reload()}>Try again</button> 281 + <button 282 + class="rounded-button" 283 + @click=${() => window.location.reload()} 284 + > 285 + Try again 286 + </button> 282 287 </div>`; 283 288 } 284 289 console.error(error); 285 290 return html`<div class="error-state"> 286 291 <div>There was an error loading the profile.</div> 287 - <button @click=${() => window.location.reload()}>Try again</button> 292 + <button class="rounded-button" @click=${() => window.location.reload()}> 293 + Try again 294 + </button> 288 295 </div>`; 289 296 } 290 297
+3 -1
src/js/views/profileFollowers.view.js
··· 33 33 console.error(error); 34 34 return html`<div class="error-state"> 35 35 <div>Error loading followers</div> 36 - <button @click=${() => window.location.reload()}>Try again</button> 36 + <button class="rounded-button" @click=${() => window.location.reload()}> 37 + Try again 38 + </button> 37 39 </div>`; 38 40 } 39 41
+3 -1
src/js/views/profileFollowing.view.js
··· 33 33 console.error(error); 34 34 return html`<div class="error-state"> 35 35 <div>Error loading following</div> 36 - <button @click=${() => window.location.reload()}>Try again</button> 36 + <button class="rounded-button" @click=${() => window.location.reload()}> 37 + Try again 38 + </button> 37 39 </div>`; 38 40 } 39 41
+3 -1
src/js/views/profileKnownFollowers.view.js
··· 33 33 console.error(error); 34 34 return html`<div class="error-state"> 35 35 <div>Error loading followers you know</div> 36 - <button @click=${() => window.location.reload()}>Try again</button> 36 + <button class="rounded-button" @click=${() => window.location.reload()}> 37 + Try again 38 + </button> 37 39 </div>`; 38 40 } 39 41
+2 -2
src/js/views/settings/advanced.view.js
··· 207 207 <div class="button-group"> 208 208 <button 209 209 type="submit" 210 - class="settings-button" 210 + class="rounded-button rounded-button-primary settings-button" 211 211 ?disabled=${state.$loading.get() || !isDirty()} 212 212 > 213 213 Save and reload ··· 257 257 <div class="button-group"> 258 258 <button 259 259 type="submit" 260 - class="settings-button" 260 + class="rounded-button rounded-button-primary settings-button" 261 261 data-testid="install-unregistered-plugin-submit" 262 262 ?disabled=${state.$pluginInstallLoading.get()} 263 263 >
+3 -1
src/js/views/settings/blockedAccounts.view.js
··· 20 20 console.error(error); 21 21 return html`<div class="error-state"> 22 22 <div>Error loading blocked accounts</div> 23 - <button @click=${() => window.location.reload()}>Try again</button> 23 + <button class="rounded-button" @click=${() => window.location.reload()}> 24 + Try again 25 + </button> 24 26 </div>`; 25 27 } 26 28
+3 -1
src/js/views/settings/mutedAccounts.view.js
··· 20 20 console.error(error); 21 21 return html`<div class="error-state"> 22 22 <div>Error loading muted accounts</div> 23 - <button @click=${() => window.location.reload()}>Try again</button> 23 + <button class="rounded-button" @click=${() => window.location.reload()}> 24 + Try again 25 + </button> 24 26 </div>`; 25 27 } 26 28
+1 -1
src/js/views/settings/mutedWords.view.js
··· 313 313 </label> 314 314 315 315 <button 316 - class="settings-button" 316 + class="rounded-button rounded-button-primary settings-button" 317 317 data-testid="muted-word-add" 318 318 type="submit" 319 319 ?disabled=${state.$isSaving.get() || !state.$hasValue.get()}