max / balanced_breakfast
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
13 files changed,
+156 insertions,
-156 deletions
| @@ -19,18 +19,18 @@ | |||
| 19 | 19 | <input type="text" id="search-input" placeholder="Search... (/) | ? for help" class="search-input"> | |
| 20 | 20 | <span id="search-spinner" class="search-spinner" aria-hidden="true"></span> | |
| 21 | 21 | <label for="sort-select" class="sr-only">Sort order</label> | |
| 22 | - | <button id="unread-toggle" class="btn btn-sm" title="Show unread only (U)" aria-pressed="false">Unread</button> | |
| 22 | + | <button id="unread-toggle" class="button button--sm" title="Show unread only (U)" aria-pressed="false">Unread</button> | |
| 23 | 23 | <select id="sort-select" class="sort-select" title="Sort order (S)"> | |
| 24 | 24 | <option value="chronological">Newest First</option> | |
| 25 | 25 | <option value="score">By Score</option> | |
| 26 | 26 | <option value="unread">Unread First</option> | |
| 27 | 27 | <option value="starred">Starred First</option> | |
| 28 | 28 | </select> | |
| 29 | - | <button id="mark-all-read-btn" class="btn btn-sm" title="Mark all as read (Shift+A)">Mark All Read</button> | |
| 30 | - | <button id="refresh-btn" class="btn btn-primary" title="Refresh all feeds (R)">Refresh</button> | |
| 31 | - | <button id="add-feed-btn" class="btn btn-success" title="Add a new feed source">+ Add Feed</button> | |
| 32 | - | <button id="help-btn" class="btn btn-sm" title="Keyboard shortcuts (?)" aria-label="Help">?</button> | |
| 33 | - | <button id="settings-btn" class="btn btn-sm" title="Settings" aria-label="Settings">⚙</button> | |
| 29 | + | <button id="mark-all-read-btn" class="button button--sm" title="Mark all as read (Shift+A)">Mark All Read</button> | |
| 30 | + | <button id="refresh-btn" class="button button--primary" title="Refresh all feeds (R)">Refresh</button> | |
| 31 | + | <button id="add-feed-btn" class="button button--success" title="Add a new feed source">+ Add Feed</button> | |
| 32 | + | <button id="help-btn" class="button button--sm" title="Keyboard shortcuts (?)" aria-label="Help">?</button> | |
| 33 | + | <button id="settings-btn" class="button button--sm" title="Settings" aria-label="Settings">⚙</button> | |
| 34 | 34 | </div> | |
| 35 | 35 | </header> | |
| 36 | 36 | ||
| @@ -52,7 +52,7 @@ | |||
| 52 | 52 | <span id="saved-count" class="source-count">0</span> | |
| 53 | 53 | </div> | |
| 54 | 54 | <div class="sidebar-footer"> | |
| 55 | - | <button id="sync-settings-btn" class="btn btn-sm" title="Cloud Sync Settings">Sync</button> | |
| 55 | + | <button id="sync-settings-btn" class="button button--sm" title="Cloud Sync Settings">Sync</button> | |
| 56 | 56 | </div> | |
| 57 | 57 | </aside> | |
| 58 | 58 | ||
| @@ -69,15 +69,15 @@ | |||
| 69 | 69 | </div> | |
| 70 | 70 | <ul id="items-list" class="items-list well" aria-live="polite"></ul> | |
| 71 | 71 | <div id="load-more" class="load-more" style="display: none;"> | |
| 72 | - | <button id="load-more-btn" class="btn">Load More</button> | |
| 72 | + | <button id="load-more-btn" class="button">Load More</button> | |
| 73 | 73 | </div> | |
| 74 | 74 | </section> | |
| 75 | 75 | ||
| 76 | 76 | <!-- Item detail panel --> | |
| 77 | 77 | <aside class="detail-panel" id="detail-panel"> | |
| 78 | 78 | <div class="detail-header"> | |
| 79 | - | <button id="save-detail" class="btn btn-sm" aria-label="Add to Reading List" title="Add to Reading List">Bookmark</button> | |
| 80 | - | <button id="close-detail" class="btn btn-sm" aria-label="Close">×</button> | |
| 79 | + | <button id="save-detail" class="button button--sm" aria-label="Add to Reading List" title="Add to Reading List">Bookmark</button> | |
| 80 | + | <button id="close-detail" class="button button--sm" aria-label="Close">×</button> | |
| 81 | 81 | </div> | |
| 82 | 82 | <article id="item-detail" class="item-detail"></article> | |
| 83 | 83 | </aside> | |
| @@ -107,7 +107,7 @@ | |||
| 107 | 107 | <div class="modal-content" role="dialog" aria-modal="true" aria-labelledby="modal-title"> | |
| 108 | 108 | <div class="modal-header"> | |
| 109 | 109 | <h2 id="modal-title">Modal</h2> | |
| 110 | - | <button id="close-modal" class="btn btn-sm" aria-label="Close">×</button> | |
| 110 | + | <button id="close-modal" class="button button--sm" aria-label="Close">×</button> | |
| 111 | 111 | </div> | |
| 112 | 112 | <div id="modal-body" class="modal-body"></div> | |
| 113 | 113 | </div> |
| @@ -13,11 +13,11 @@ | |||
| 13 | 13 | section}, .stack + | |
| 14 | 14 | .stack-{peer,group, | |
| 15 | 15 | section}) | |
| 16 | - | 3. Use a COMPONENT PRIMITIVE for a UI element (.btn, .card, .modal, | |
| 16 | + | 3. Use a COMPONENT PRIMITIVE for a UI element (.button, .card, .modal, | |
| 17 | 17 | .form-input, | |
| 18 | 18 | .form-select, .badge, | |
| 19 | 19 | .tag, .toast) | |
| 20 | - | 4. Extend a primitive with a modifier (.btn-primary, .btn-sm, | |
| 20 | + | 4. Extend a primitive with a modifier (.button--primary, .button--sm, | |
| 21 | 21 | .form-select--ghost) | |
| 22 | 22 | 5. ONLY THEN consider a new class, and add it to the right BAND below | |
| 23 | 23 | ||
| @@ -62,7 +62,7 @@ | |||
| 62 | 62 | 8. Detail panel | |
| 63 | 63 | ||
| 64 | 64 | BAND: COMPONENT PRIMITIVES | |
| 65 | - | 9. Buttons: .btn family | |
| 65 | + | 9. Buttons: .button family | |
| 66 | 66 | 10. Forms: .form-group, .form-input | |
| 67 | 67 | 11. Modal: .modal-overlay/.modal-content | |
| 68 | 68 | 12. Toast: .toast | |
| @@ -171,7 +171,7 @@ | |||
| 171 | 171 | Geometry is app-local by contract: a theme overrides color only, so | |
| 172 | 172 | border width, bevel thickness and radius cannot be reached from a | |
| 173 | 173 | theme file. */ | |
| 174 | - | --accent-red-hover: color-mix(in oklch, var(--danger) 90%, white); /* composition: .btn-danger:hover */ | |
| 174 | + | --accent-red-hover: color-mix(in oklch, var(--danger) 90%, white); /* composition: .button--danger:hover */ | |
| 175 | 175 | --accent-yellow-light: color-mix(in oklch, var(--category-four) 82%, white); /* composition */ | |
| 176 | 176 | --shadow-color: color-mix(in oklch, var(--content-muted) 88%, black); /* composition */ | |
| 177 | 177 | --border-width: 1px; /* invariant */ | |
| @@ -429,7 +429,7 @@ | |||
| 429 | 429 | <div class="empty-state"> | |
| 430 | 430 | <div class="empty-state-icon">...</div> | |
| 431 | 431 | <p class="empty-state-text">No items</p> | |
| 432 | - | <button class="btn btn-primary">Add one</button> | |
| 432 | + | <button class="button button--primary">Add one</button> | |
| 433 | 433 | </div> | |
| 434 | 434 | */ | |
| 435 | 435 | .empty-state { | |
| @@ -572,11 +572,11 @@ | |||
| 572 | 572 | } | |
| 573 | 573 | ||
| 574 | 574 | /* === 9. Buttons ======================================================== | |
| 575 | - | Canonical: .btn (+ .btn-primary, .btn-secondary, .btn-success, .btn-danger, | |
| 576 | - | .btn-icon, .btn-text, .btn-link; size .btn-sm; state .btn-loading). | |
| 575 | + | Canonical: .button (+ .button--primary, .button--secondary, .button--success, .button--danger, | |
| 576 | + | .button--icon, .button--text, .button--link; size .button--sm; state .button--loading). | |
| 577 | 577 | Charter target: collapse remaining one-off *-btn classes onto this family. | |
| 578 | 578 | ========================================================================== */ | |
| 579 | - | .btn { | |
| 579 | + | .button { | |
| 580 | 580 | padding: var(--gap-peer) var(--gap-group); | |
| 581 | 581 | border: var(--border-width) solid var(--border); | |
| 582 | 582 | border-radius: var(--radius-sm); | |
| @@ -587,49 +587,49 @@ | |||
| 587 | 587 | font-size: var(--font-size-base); | |
| 588 | 588 | box-shadow: var(--bevel-raised); | |
| 589 | 589 | } | |
| 590 | - | .btn:hover { | |
| 590 | + | .button:hover { | |
| 591 | 591 | background-color: var(--surface-sunken); | |
| 592 | 592 | border-color: var(--border-strong); | |
| 593 | 593 | } | |
| 594 | 594 | /* Pressed inverts the bevel and drops the fill a step. No offset, no | |
| 595 | 595 | translate: the button reads as pushed into the page, and every modifier | |
| 596 | 596 | below inherits the state for free. */ | |
| 597 | - | .btn:active { | |
| 597 | + | .button:active { | |
| 598 | 598 | background-color: var(--surface-sunken); | |
| 599 | 599 | box-shadow: var(--bevel-inset); | |
| 600 | 600 | } | |
| 601 | 601 | /* Disabled keeps its bevel. The object is still there; greying the content | |
| 602 | 602 | is what says the action is unavailable. */ | |
| 603 | - | .btn:disabled { | |
| 603 | + | .button:disabled { | |
| 604 | 604 | color: var(--content-muted); | |
| 605 | 605 | border-color: var(--content-muted); | |
| 606 | 606 | cursor: not-allowed; | |
| 607 | 607 | } | |
| 608 | - | .btn:disabled:active { box-shadow: var(--bevel-raised); } | |
| 609 | - | .btn-primary { | |
| 608 | + | .button:disabled:active { box-shadow: var(--bevel-raised); } | |
| 609 | + | .button--primary { | |
| 610 | 610 | background-color: var(--action); | |
| 611 | 611 | border-color: var(--action); | |
| 612 | 612 | color: var(--content-on-action); | |
| 613 | 613 | } | |
| 614 | - | .btn-primary:hover { background-color: var(--action-hover); border-color: var(--action-hover); } | |
| 615 | - | .btn-success { | |
| 614 | + | .button--primary:hover { background-color: var(--action-hover); border-color: var(--action-hover); } | |
| 615 | + | .button--success { | |
| 616 | 616 | background-color: var(--category-four); | |
| 617 | 617 | border-color: var(--category-four); | |
| 618 | 618 | color: var(--content-on-action); | |
| 619 | 619 | } | |
| 620 | - | .btn-success:hover { background-color: var(--accent-yellow-light); border-color: var(--accent-yellow-light); } | |
| 621 | - | /* .btn-sm: canonical small-button size (see wiki note `bb-design-system`). */ | |
| 622 | - | .btn-sm { padding: var(--gap-bound) var(--gap-peer); font-size: var(--font-size-md); } | |
| 623 | - | .btn-sm.active { background: var(--category-four); color: var(--content-on-action); border-color: var(--category-four); } | |
| 620 | + | .button--success:hover { background-color: var(--accent-yellow-light); border-color: var(--accent-yellow-light); } | |
| 621 | + | /* .button--sm: canonical small-button size (see wiki note `bb-design-system`). */ | |
| 622 | + | .button--sm { padding: var(--gap-bound) var(--gap-peer); font-size: var(--font-size-md); } | |
| 623 | + | .button--sm.active { background: var(--category-four); color: var(--content-on-action); border-color: var(--category-four); } | |
| 624 | 624 | ||
| 625 | - | /* .btn-danger: destructive action. Consumes the previously-unused | |
| 625 | + | /* .button--danger: destructive action. Consumes the previously-unused | |
| 626 | 626 | --accent-red-hover token. Replaces .hp-action-danger in F5. */ | |
| 627 | - | .btn-danger { | |
| 627 | + | .button--danger { | |
| 628 | 628 | background-color: var(--danger); | |
| 629 | 629 | border-color: var(--danger); | |
| 630 | 630 | color: var(--content-on-action); | |
| 631 | 631 | } | |
| 632 | - | .btn-danger:hover { background-color: var(--accent-red-hover); border-color: var(--accent-red-hover); } | |
| 632 | + | .button--danger:hover { background-color: var(--accent-red-hover); border-color: var(--accent-red-hover); } | |
| 633 | 633 | ||
| 634 | 634 | /* === N. Row primitive (F2-sub addition, 2026-06-02) =================== | |
| 635 | 635 | Canonical slot layout: [icon] [primary · badges] [meta] [actions]. | |
| @@ -923,12 +923,12 @@ | |||
| 923 | 923 | ||
| 924 | 924 | /* mobile.js action sheets: stacked full-width buttons. Replaces inline | |
| 925 | 925 | `style.display='block'; style.width='100%'; style.marginBottom='0.5rem'`. */ | |
| 926 | - | .btn-stacked { | |
| 926 | + | .button--stacked { | |
| 927 | 927 | display: block; | |
| 928 | 928 | width: 100%; | |
| 929 | 929 | margin-bottom: var(--gap-peer); | |
| 930 | 930 | } | |
| 931 | - | .btn-stacked:last-child { margin-bottom: 0; } | |
| 931 | + | .button--stacked:last-child { margin-bottom: 0; } | |
| 932 | 932 | ||
| 933 | 933 | /* app.js settings theme-import/export row. Layout-only; class-ifying. */ | |
| 934 | 934 | .theme-actions { | |
| @@ -1239,7 +1239,7 @@ | |||
| 1239 | 1239 | } | |
| 1240 | 1240 | ||
| 1241 | 1241 | /* === 19. Health popover ================================================ | |
| 1242 | - | Floating panel from gear icon. Actions use the .btn family (.hp-actions .btn | |
| 1242 | + | Floating panel from gear icon. Actions use the .button family (.hp-actions .button | |
| 1243 | 1243 | fills the row). .hp-row is a one-off label/value line (kept). | |
| 1244 | 1244 | ========================================================================== */ | |
| 1245 | 1245 | .health-popover { | |
| @@ -1295,9 +1295,9 @@ | |||
| 1295 | 1295 | padding-top: var(--gap-peer); | |
| 1296 | 1296 | border-top: var(--border-width) solid var(--border); | |
| 1297 | 1297 | } | |
| 1298 | - | /* Popover actions are the .btn family (Mark Read / Edit / Tags / Delete); | |
| 1298 | + | /* Popover actions are the .button family (Mark Read / Edit / Tags / Delete); | |
| 1299 | 1299 | they fill the row equally. */ | |
| 1300 | - | .hp-actions .btn { flex: 1; } | |
| 1300 | + | .hp-actions .button { flex: 1; } | |
| 1301 | 1301 | ||
| 1302 | 1302 | ||
| 1303 | 1303 | /* === 20. Sources list: sidebar entries ================================ | |
| @@ -1667,7 +1667,7 @@ | |||
| 1667 | 1667 | for inputs (avoids layout shift). Rule: every new interactive | |
| 1668 | 1668 | primitive must appear in one of these selector lists. | |
| 1669 | 1669 | ========================================================================== */ | |
| 1670 | - | .btn:focus-visible, | |
| 1670 | + | .button:focus-visible, | |
| 1671 | 1671 | .source-item:focus-visible, | |
| 1672 | 1672 | .star-btn:focus-visible, | |
| 1673 | 1673 | .source-delete:focus-visible, | |
| @@ -1953,9 +1953,9 @@ | |||
| 1953 | 1953 | .source-item.active:hover { background-color: var(--surface-sunken); } | |
| 1954 | 1954 | .sidebar-saved:hover { background-color: transparent; } | |
| 1955 | 1955 | .sidebar-saved.active:hover { background-color: var(--surface-sunken); } | |
| 1956 | - | .btn:hover { background-color: var(--surface-page); border-color: var(--border); } | |
| 1957 | - | .btn-primary:hover { background-color: var(--action); border-color: var(--action); } | |
| 1958 | - | .btn-success:hover { background-color: var(--category-four); border-color: var(--category-four); } | |
| 1956 | + | .button:hover { background-color: var(--surface-page); border-color: var(--border); } | |
| 1957 | + | .button--primary:hover { background-color: var(--action); border-color: var(--action); } | |
| 1958 | + | .button--success:hover { background-color: var(--category-four); border-color: var(--category-four); } | |
| 1959 | 1959 | .star-btn:hover { color: var(--content-muted); transform: none; } | |
| 1960 | 1960 | .star-btn.starred:hover { color: var(--category-four); } | |
| 1961 | 1961 | .tag-chip:hover { border-color: var(--border); color: var(--content-secondary); } |
| @@ -111,10 +111,10 @@ | |||
| 111 | 111 | * Toggle the "unread only" filter on/off. | |
| 112 | 112 | */ | |
| 113 | 113 | function toggleUnreadFilter() { | |
| 114 | - | const btn = document.getElementById('unread-toggle'); | |
| 115 | - | const active = btn.getAttribute('aria-pressed') === 'true'; | |
| 116 | - | btn.setAttribute('aria-pressed', !active); | |
| 117 | - | btn.classList.toggle('active', !active); | |
| 114 | + | const button = document.getElementById('unread-toggle'); | |
| 115 | + | const active = button.getAttribute('aria-pressed') === 'true'; | |
| 116 | + | button.setAttribute('aria-pressed', !active); | |
| 117 | + | button.classList.toggle('active', !active); | |
| 118 | 118 | BB.state.set('unreadOnly', !active); | |
| 119 | 119 | BB.state.resetPagination(true); | |
| 120 | 120 | BB.items.load(); | |
| @@ -369,13 +369,13 @@ | |||
| 369 | 369 | themeActions.className = 'theme-actions'; | |
| 370 | 370 | ||
| 371 | 371 | const themeImportBtn = document.createElement('button'); | |
| 372 | - | themeImportBtn.className = 'btn btn-sm'; | |
| 372 | + | themeImportBtn.className = 'button button--sm'; | |
| 373 | 373 | themeImportBtn.textContent = 'Import Theme'; | |
| 374 | 374 | themeImportBtn.onclick = () => BB.themes.importTheme(); | |
| 375 | 375 | themeActions.appendChild(themeImportBtn); | |
| 376 | 376 | ||
| 377 | 377 | const themeExportBtn = document.createElement('button'); | |
| 378 | - | themeExportBtn.className = 'btn btn-sm'; | |
| 378 | + | themeExportBtn.className = 'button button--sm'; | |
| 379 | 379 | themeExportBtn.textContent = 'Export Current'; | |
| 380 | 380 | themeExportBtn.onclick = () => BB.themes.exportTheme(); | |
| 381 | 381 | themeActions.appendChild(themeExportBtn); | |
| @@ -394,13 +394,13 @@ | |||
| 394 | 394 | dataActions.className = 'row-flex row-flex-peer'; | |
| 395 | 395 | ||
| 396 | 396 | const importBtn = document.createElement('button'); | |
| 397 | - | importBtn.className = 'btn btn-sm'; | |
| 397 | + | importBtn.className = 'button button--sm'; | |
| 398 | 398 | importBtn.textContent = 'Import OPML'; | |
| 399 | 399 | importBtn.onclick = () => { BB.ui.closeModal(); BB.feeds.importOpml(); }; | |
| 400 | 400 | dataActions.appendChild(importBtn); | |
| 401 | 401 | ||
| 402 | 402 | const exportBtn = document.createElement('button'); | |
| 403 | - | exportBtn.className = 'btn btn-sm'; | |
| 403 | + | exportBtn.className = 'button button--sm'; | |
| 404 | 404 | exportBtn.textContent = 'Export OPML'; | |
| 405 | 405 | exportBtn.onclick = () => { BB.ui.closeModal(); BB.feeds.exportOpml(); }; | |
| 406 | 406 | dataActions.appendChild(exportBtn); | |
| @@ -416,7 +416,7 @@ | |||
| 416 | 416 | syncLabel.textContent = 'Cloud Sync'; | |
| 417 | 417 | syncGroup.appendChild(syncLabel); | |
| 418 | 418 | const syncBtn = document.createElement('button'); | |
| 419 | - | syncBtn.className = 'btn btn-sm'; | |
| 419 | + | syncBtn.className = 'button button--sm'; | |
| 420 | 420 | syncBtn.textContent = 'Sync Settings'; | |
| 421 | 421 | syncBtn.onclick = () => { BB.ui.closeModal(); BB.sync.openSettings(); }; | |
| 422 | 422 | syncGroup.appendChild(syncBtn); | |
| @@ -426,7 +426,7 @@ | |||
| 426 | 426 | const actions = document.createElement('div'); | |
| 427 | 427 | actions.className = 'form-actions'; | |
| 428 | 428 | const closeBtn = document.createElement('button'); | |
| 429 | - | closeBtn.className = 'btn'; | |
| 429 | + | closeBtn.className = 'button'; | |
| 430 | 430 | closeBtn.textContent = 'Close'; | |
| 431 | 431 | closeBtn.addEventListener('click', BB.ui.closeModal); | |
| 432 | 432 | actions.appendChild(closeBtn); | |
| @@ -492,11 +492,11 @@ | |||
| 492 | 492 | const cta = document.createElement('div'); | |
| 493 | 493 | cta.className = 'welcome-cta'; | |
| 494 | 494 | const addBtn = document.createElement('button'); | |
| 495 | - | addBtn.className = 'btn btn-success'; | |
| 495 | + | addBtn.className = 'button button--success'; | |
| 496 | 496 | addBtn.textContent = 'Add Your First Feed'; | |
| 497 | 497 | addBtn.addEventListener('click', BB.feeds.openAddFeed); | |
| 498 | 498 | const exploreBtn = document.createElement('button'); | |
| 499 | - | exploreBtn.className = 'btn'; | |
| 499 | + | exploreBtn.className = 'button'; | |
| 500 | 500 | exploreBtn.textContent = 'Explore First'; | |
| 501 | 501 | exploreBtn.addEventListener('click', BB.ui.closeModal); | |
| 502 | 502 | cta.appendChild(addBtn); |
| @@ -103,12 +103,12 @@ | |||
| 103 | 103 | ||
| 104 | 104 | // Actions slot: Open + more (hover-revealed via .row-actions). | |
| 105 | 105 | const openBtn = document.createElement('button'); | |
| 106 | - | openBtn.className = 'btn btn-sm'; | |
| 106 | + | openBtn.className = 'button button--sm'; | |
| 107 | 107 | openBtn.title = 'Open URL'; | |
| 108 | 108 | openBtn.textContent = 'Open'; | |
| 109 | 109 | openBtn.onclick = (e) => { e.stopPropagation(); openUrl(bm.url); }; | |
| 110 | 110 | const moreBtn = document.createElement('button'); | |
| 111 | - | moreBtn.className = 'btn btn-sm'; | |
| 111 | + | moreBtn.className = 'button button--sm'; | |
| 112 | 112 | moreBtn.title = 'More actions'; | |
| 113 | 113 | moreBtn.textContent = '\u22EF'; | |
| 114 | 114 | moreBtn.onclick = (e) => { e.stopPropagation(); showContextMenu(e, bm.id); }; | |
| @@ -168,16 +168,16 @@ | |||
| 168 | 168 | bar.appendChild(allBtn); | |
| 169 | 169 | ||
| 170 | 170 | for (const tag of tags) { | |
| 171 | - | const btn = document.createElement('button'); | |
| 172 | - | btn.className = 'tag-chip' + (currentTag === tag ? ' active' : ''); | |
| 173 | - | btn.textContent = tag; | |
| 174 | - | btn.onclick = () => load(tag); | |
| 175 | - | bar.appendChild(btn); | |
| 171 | + | const button = document.createElement('button'); | |
| 172 | + | button.className = 'tag-chip' + (currentTag === tag ? ' active' : ''); | |
| 173 | + | button.textContent = tag; | |
| 174 | + | button.onclick = () => load(tag); | |
| 175 | + | bar.appendChild(button); | |
| 176 | 176 | } | |
| 177 | 177 | ||
| 178 | 178 | // "Add Bookmark" button | |
| 179 | 179 | const addBtn = document.createElement('button'); | |
| 180 | - | addBtn.className = 'btn btn-sm btn-primary'; | |
| 180 | + | addBtn.className = 'button button--sm button--primary'; | |
| 181 | 181 | addBtn.textContent = '+ Add'; | |
| 182 | 182 | addBtn.onclick = () => openAddModal(); | |
| 183 | 183 | bar.appendChild(addBtn); | |
| @@ -243,8 +243,8 @@ | |||
| 243 | 243 | <textarea id="bm-notes" class="form-input" rows="3" placeholder="Personal notes..."></textarea> | |
| 244 | 244 | </div> | |
| 245 | 245 | <div class="form-actions"> | |
| 246 | - | <button class="btn" id="bm-cancel">Cancel</button> | |
| 247 | - | <button class="btn btn-primary" id="bm-save">Save</button> | |
| 246 | + | <button class="button" id="bm-cancel">Cancel</button> | |
| 247 | + | <button class="button button--primary" id="bm-save">Save</button> | |
| 248 | 248 | </div> | |
| 249 | 249 | `; | |
| 250 | 250 | ||
| @@ -317,8 +317,8 @@ | |||
| 317 | 317 | <label><input type="checkbox" id="bm-edit-pinned" ${bm.isPinned ? 'checked' : ''}> Pin to top</label> | |
| 318 | 318 | </div> | |
| 319 | 319 | <div class="form-actions"> | |
| 320 | - | <button class="btn" id="bm-edit-cancel">Cancel</button> | |
| 321 | - | <button class="btn btn-primary" id="bm-edit-save">Save</button> | |
| 320 | + | <button class="button" id="bm-edit-cancel">Cancel</button> | |
| 321 | + | <button class="button button--primary" id="bm-edit-save">Save</button> | |
| 322 | 322 | </div> | |
| 323 | 323 | `; | |
| 324 | 324 | ||
| @@ -370,8 +370,8 @@ | |||
| 370 | 370 | <input type="text" id="bm-tags-input" class="form-input" value="${escapeAttr(bm.tags.join(', '))}"> | |
| 371 | 371 | </div> | |
| 372 | 372 | <div class="form-actions"> | |
| 373 | - | <button class="btn" id="bm-tags-cancel">Cancel</button> | |
| 374 | - | <button class="btn btn-primary" id="bm-tags-save">Save</button> | |
| 373 | + | <button class="button" id="bm-tags-cancel">Cancel</button> | |
| 374 | + | <button class="button button--primary" id="bm-tags-save">Save</button> | |
| 375 | 375 | </div> | |
| 376 | 376 | `; | |
| 377 | 377 |
| @@ -22,11 +22,11 @@ | |||
| 22 | 22 | toast.textContent = message; | |
| 23 | 23 | ||
| 24 | 24 | if (opts.action) { | |
| 25 | - | const btn = document.createElement('button'); | |
| 26 | - | btn.className = 'toast-action'; | |
| 27 | - | btn.textContent = opts.action.label; | |
| 28 | - | btn.onclick = () => { toast.remove(); opts.action.fn(); }; | |
| 29 | - | toast.appendChild(btn); | |
| 25 | + | const button = document.createElement('button'); | |
| 26 | + | button.className = 'toast-action'; | |
| 27 | + | button.textContent = opts.action.label; | |
| 28 | + | button.onclick = () => { toast.remove(); opts.action.fn(); }; | |
| 29 | + | toast.appendChild(button); | |
| 30 | 30 | } | |
| 31 | 31 | ||
| 32 | 32 | container.appendChild(toast); | |
| @@ -90,14 +90,14 @@ | |||
| 90 | 90 | ||
| 91 | 91 | const cancelBtn = document.createElement('button'); | |
| 92 | 92 | cancelBtn.type = 'button'; | |
| 93 | - | cancelBtn.className = 'btn'; | |
| 93 | + | cancelBtn.className = 'button'; | |
| 94 | 94 | cancelBtn.textContent = 'Cancel'; | |
| 95 | 95 | cancelBtn.onclick = closeModal; | |
| 96 | 96 | actions.appendChild(cancelBtn); | |
| 97 | 97 | ||
| 98 | 98 | const submitBtn = document.createElement('button'); | |
| 99 | 99 | submitBtn.type = 'submit'; | |
| 100 | - | submitBtn.className = 'btn btn-primary'; | |
| 100 | + | submitBtn.className = 'button button--primary'; | |
| 101 | 101 | submitBtn.textContent = opts.submitLabel || 'Save'; | |
| 102 | 102 | actions.appendChild(submitBtn); | |
| 103 | 103 | ||
| @@ -176,14 +176,14 @@ | |||
| 176 | 176 | ||
| 177 | 177 | const cancelBtn = document.createElement('button'); | |
| 178 | 178 | cancelBtn.type = 'button'; | |
| 179 | - | cancelBtn.className = 'btn'; | |
| 179 | + | cancelBtn.className = 'button'; | |
| 180 | 180 | cancelBtn.textContent = 'Cancel'; | |
| 181 | 181 | cancelBtn.onclick = () => { overlay.style.display = 'none'; resolve(false); }; | |
| 182 | 182 | actions.appendChild(cancelBtn); | |
| 183 | 183 | ||
| 184 | 184 | const confirmBtn = document.createElement('button'); | |
| 185 | 185 | confirmBtn.type = 'button'; | |
| 186 | - | confirmBtn.className = danger ? 'btn btn-primary' : 'btn btn-success'; | |
| 186 | + | confirmBtn.className = danger ? 'button button--primary' : 'button button--success'; | |
| 187 | 187 | confirmBtn.textContent = confirmLabel; | |
| 188 | 188 | confirmBtn.onclick = () => { overlay.style.display = 'none'; resolve(true); }; | |
| 189 | 189 | actions.appendChild(confirmBtn); | |
| @@ -225,14 +225,14 @@ | |||
| 225 | 225 | ||
| 226 | 226 | const cancelBtn = document.createElement('button'); | |
| 227 | 227 | cancelBtn.type = 'button'; | |
| 228 | - | cancelBtn.className = 'btn'; | |
| 228 | + | cancelBtn.className = 'button'; | |
| 229 | 229 | cancelBtn.textContent = 'Cancel'; | |
| 230 | 230 | cancelBtn.onclick = () => { overlay.style.display = 'none'; resolve(false); }; | |
| 231 | 231 | actions.appendChild(cancelBtn); | |
| 232 | 232 | ||
| 233 | 233 | const confirmBtn = document.createElement('button'); | |
| 234 | 234 | confirmBtn.type = 'button'; | |
| 235 | - | confirmBtn.className = danger ? 'btn btn-danger' : 'btn btn-primary'; | |
| 235 | + | confirmBtn.className = danger ? 'button button--danger' : 'button button--primary'; | |
| 236 | 236 | confirmBtn.textContent = confirmLabel; | |
| 237 | 237 | confirmBtn.onclick = () => { overlay.style.display = 'none'; resolve(true); }; | |
| 238 | 238 | actions.appendChild(confirmBtn); | |
| @@ -299,11 +299,11 @@ | |||
| 299 | 299 | el.appendChild(text); | |
| 300 | 300 | ||
| 301 | 301 | if (opts.buttonLabel && opts.onClick) { | |
| 302 | - | const btn = document.createElement('button'); | |
| 303 | - | btn.className = 'btn btn-primary'; | |
| 304 | - | btn.textContent = opts.buttonLabel; | |
| 305 | - | btn.onclick = opts.onClick; | |
| 306 | - | el.appendChild(btn); | |
| 302 | + | const button = document.createElement('button'); | |
| 303 | + | button.className = 'button button--primary'; | |
| 304 | + | button.textContent = opts.buttonLabel; | |
| 305 | + | button.onclick = opts.onClick; | |
| 306 | + | el.appendChild(button); | |
| 307 | 307 | } | |
| 308 | 308 | ||
| 309 | 309 | container.appendChild(el); | |
| @@ -329,11 +329,11 @@ | |||
| 329 | 329 | menu.style.top = event.clientY + 'px'; | |
| 330 | 330 | ||
| 331 | 331 | for (const item of items) { | |
| 332 | - | const btn = document.createElement('button'); | |
| 333 | - | btn.className = 'context-menu-item' + (item.danger ? ' context-menu-item--danger' : ''); | |
| 334 | - | btn.textContent = item.label; | |
| 335 | - | btn.onclick = () => { menu.remove(); item.fn(); }; | |
| 336 | - | menu.appendChild(btn); | |
| 332 | + | const button = document.createElement('button'); | |
| 333 | + | button.className = 'context-menu-item' + (item.danger ? ' context-menu-item--danger' : ''); | |
| 334 | + | button.textContent = item.label; | |
| 335 | + | button.onclick = () => { menu.remove(); item.fn(); }; | |
| 336 | + | menu.appendChild(button); | |
| 337 | 337 | } | |
| 338 | 338 | ||
| 339 | 339 | document.body.appendChild(menu); | |
| @@ -375,10 +375,10 @@ | |||
| 375 | 375 | msgEl.textContent = message; | |
| 376 | 376 | toast.appendChild(msgEl); | |
| 377 | 377 | ||
| 378 | - | const btn = document.createElement('button'); | |
| 379 | - | btn.className = 'undo-btn'; | |
| 380 | - | btn.textContent = 'Undo'; | |
| 381 | - | toast.appendChild(btn); | |
| 378 | + | const button = document.createElement('button'); | |
| 379 | + | button.className = 'undo-btn'; | |
| 380 | + | button.textContent = 'Undo'; | |
| 381 | + | toast.appendChild(button); | |
| 382 | 382 | ||
| 383 | 383 | const countdown = document.createElement('span'); | |
| 384 | 384 | countdown.className = 'undo-countdown'; | |
| @@ -392,7 +392,7 @@ | |||
| 392 | 392 | }, 1000); | |
| 393 | 393 | ||
| 394 | 394 | const dismiss = () => { clearInterval(tick); toast.remove(); }; | |
| 395 | - | btn.onclick = () => { dismiss(); undoFn(); }; | |
| 395 | + | button.onclick = () => { dismiss(); undoFn(); }; | |
| 396 | 396 | ||
| 397 | 397 | container.appendChild(toast); | |
| 398 | 398 | setTimeout(dismiss, duration); |
| @@ -107,26 +107,26 @@ | |||
| 107 | 107 | actions.className = 'detail-actions'; | |
| 108 | 108 | ||
| 109 | 109 | const readBtn = document.createElement('button'); | |
| 110 | - | readBtn.className = 'btn'; | |
| 110 | + | readBtn.className = 'button'; | |
| 111 | 111 | readBtn.textContent = item.isRead ? 'Mark Unread' : 'Mark Read'; | |
| 112 | 112 | readBtn.addEventListener('click', toggleRead); | |
| 113 | 113 | actions.appendChild(readBtn); | |
| 114 | 114 | ||
| 115 | 115 | const starBtn = document.createElement('button'); | |
| 116 | - | starBtn.className = 'btn'; | |
| 116 | + | starBtn.className = 'button'; | |
| 117 | 117 | starBtn.textContent = item.isStarred ? 'Unstar' : 'Star'; | |
| 118 | 118 | starBtn.addEventListener('click', toggleStar); | |
| 119 | 119 | actions.appendChild(starBtn); | |
| 120 | 120 | ||
| 121 | 121 | if (item.url) { | |
| 122 | 122 | const readerBtn = document.createElement('button'); | |
| 123 | - | readerBtn.className = 'btn'; | |
| 123 | + | readerBtn.className = 'button'; | |
| 124 | 124 | readerBtn.textContent = 'Reader View'; | |
| 125 | 125 | readerBtn.addEventListener('click', readerView); | |
| 126 | 126 | actions.appendChild(readerBtn); | |
| 127 | 127 | ||
| 128 | 128 | const openBtn = document.createElement('button'); | |
| 129 | - | openBtn.className = 'btn btn-primary'; | |
| 129 | + | openBtn.className = 'button button--primary'; | |
| 130 | 130 | openBtn.textContent = 'Open'; | |
| 131 | 131 | openBtn.addEventListener('click', openUrl); | |
| 132 | 132 | actions.appendChild(openBtn); | |
| @@ -134,7 +134,7 @@ | |||
| 134 | 134 | ||
| 135 | 135 | if (item.supernoteEligible) { | |
| 136 | 136 | const snBtn = document.createElement('button'); | |
| 137 | - | snBtn.className = 'btn'; | |
| 137 | + | snBtn.className = 'button'; | |
| 138 | 138 | snBtn.textContent = 'Send to Supernote'; | |
| 139 | 139 | snBtn.addEventListener('click', pushToSupernote); | |
| 140 | 140 | actions.appendChild(snBtn); | |
| @@ -143,17 +143,17 @@ | |||
| 143 | 143 | // Plugin-declared custom action buttons | |
| 144 | 144 | if (item.actions && item.actions.length > 0) { | |
| 145 | 145 | for (const action of item.actions) { | |
| 146 | - | const btn = document.createElement('button'); | |
| 147 | - | btn.className = 'btn'; | |
| 148 | - | btn.textContent = action.label; | |
| 146 | + | const button = document.createElement('button'); | |
| 147 | + | button.className = 'button'; | |
| 148 | + | button.textContent = action.label; | |
| 149 | 149 | if (action.actionType === 'open') { | |
| 150 | - | btn.addEventListener('click', () => { | |
| 150 | + | button.addEventListener('click', () => { | |
| 151 | 151 | window.__TAURI__.shell.open(action.url).catch(() => { | |
| 152 | 152 | BB.ui.showToast('Failed to open URL', 'error'); | |
| 153 | 153 | }); | |
| 154 | 154 | }); | |
| 155 | 155 | } else if (action.actionType === 'download') { | |
| 156 | - | btn.addEventListener('click', async () => { | |
| 156 | + | button.addEventListener('click', async () => { | |
| 157 | 157 | BB.ui.showToast('Downloading...'); | |
| 158 | 158 | try { | |
| 159 | 159 | await BB.api.actions.downloadAndOpen(action.url); | |
| @@ -162,7 +162,7 @@ | |||
| 162 | 162 | } | |
| 163 | 163 | }); | |
| 164 | 164 | } | |
| 165 | - | actions.appendChild(btn); | |
| 165 | + | actions.appendChild(button); | |
| 166 | 166 | } | |
| 167 | 167 | } | |
| 168 | 168 | ||
| @@ -187,7 +187,7 @@ | |||
| 187 | 187 | const header = document.querySelector('.detail-header'); | |
| 188 | 188 | if (!header.querySelector('.reader-back-btn')) { | |
| 189 | 189 | const backBtn = document.createElement('button'); | |
| 190 | - | backBtn.className = 'btn btn-sm reader-back-btn'; | |
| 190 | + | backBtn.className = 'button button--sm reader-back-btn'; | |
| 191 | 191 | backBtn.textContent = '\u2190 Back'; | |
| 192 | 192 | backBtn.addEventListener('click', collapseReader); | |
| 193 | 193 | header.prepend(backBtn); |
| @@ -44,14 +44,14 @@ | |||
| 44 | 44 | ||
| 45 | 45 | const cancelBtn = document.createElement('button'); | |
| 46 | 46 | cancelBtn.type = 'button'; | |
| 47 | - | cancelBtn.className = 'btn'; | |
| 47 | + | cancelBtn.className = 'button'; | |
| 48 | 48 | cancelBtn.textContent = 'Cancel'; | |
| 49 | 49 | cancelBtn.onclick = () => { BB.ui.closeModal(); resolve(false); }; | |
| 50 | 50 | actions.appendChild(cancelBtn); | |
| 51 | 51 | ||
| 52 | 52 | const acceptBtn = document.createElement('button'); | |
| 53 | 53 | acceptBtn.type = 'button'; | |
| 54 | - | acceptBtn.className = 'btn btn-primary'; | |
| 54 | + | acceptBtn.className = 'button button--primary'; | |
| 55 | 55 | acceptBtn.textContent = 'I Understand'; | |
| 56 | 56 | acceptBtn.onclick = () => { | |
| 57 | 57 | localStorage.setItem('bb_plugin_warning_ack', '1'); | |
| @@ -189,11 +189,11 @@ | |||
| 189 | 189 | * @returns {Promise<void>} | |
| 190 | 190 | */ | |
| 191 | 191 | async function refresh() { | |
| 192 | - | const btn = document.getElementById('refresh-btn'); | |
| 192 | + | const button = document.getElementById('refresh-btn'); | |
| 193 | 193 | // Lock button width before changing text to prevent header reflow | |
| 194 | - | btn.style.width = btn.offsetWidth + 'px'; | |
| 195 | - | btn.disabled = true; | |
| 196 | - | btn.textContent = 'Refreshing...'; | |
| 194 | + | button.style.width = button.offsetWidth + 'px'; | |
| 195 | + | button.disabled = true; | |
| 196 | + | button.textContent = 'Refreshing...'; | |
| 197 | 197 | ||
| 198 | 198 | const header = document.querySelector('.header'); | |
| 199 | 199 | const progress = BB.ui.showProgress(header); | |
| @@ -233,9 +233,9 @@ | |||
| 233 | 233 | } finally { | |
| 234 | 234 | if (unlisten) unlisten(); | |
| 235 | 235 | setTimeout(() => progress.remove(), 400); | |
| 236 | - | btn.disabled = false; | |
| 237 | - | btn.textContent = 'Refresh'; | |
| 238 | - | btn.style.width = ''; | |
| 236 | + | button.disabled = false; | |
| 237 | + | button.textContent = 'Refresh'; | |
| 238 | + | button.style.width = ''; | |
| 239 | 239 | } | |
| 240 | 240 | } | |
| 241 | 241 |
| @@ -273,14 +273,14 @@ | |||
| 273 | 273 | { label: 'Delete', action: () => BB.sources.deleteFeed(source), danger: true }, | |
| 274 | 274 | ]; | |
| 275 | 275 | // F4 (2026-06-02): inline styles + JS-set color retired in favor | |
| 276 | - | // of .btn-stacked utility and .btn-danger modifier (charter rule: | |
| 276 | + | // of .button--stacked utility and .button--danger modifier (charter rule: | |
| 277 | 277 | // destructive intent expressed via class, not inline color). | |
| 278 | 278 | for (const a of actions) { | |
| 279 | - | const btn = document.createElement('button'); | |
| 280 | - | btn.className = 'btn btn-stacked' + (a.danger ? ' btn-danger' : ''); | |
| 281 | - | btn.textContent = a.label; | |
| 282 | - | btn.addEventListener('click', () => { BB.ui.closeModal(); a.action(); }); | |
| 283 | - | body.appendChild(btn); | |
| 279 | + | const button = document.createElement('button'); | |
| 280 | + | button.className = 'button button--stacked' + (a.danger ? ' button--danger' : ''); | |
| 281 | + | button.textContent = a.label; | |
| 282 | + | button.addEventListener('click', () => { BB.ui.closeModal(); a.action(); }); | |
| 283 | + | body.appendChild(button); | |
| 284 | 284 | } | |
| 285 | 285 | BB.ui.openModal(); | |
| 286 | 286 | } | |
| @@ -305,14 +305,14 @@ | |||
| 305 | 305 | actions.push({ label: 'Open in Browser', action: () => BB.detail.openUrl() }); | |
| 306 | 306 | } | |
| 307 | 307 | ||
| 308 | - | // F4 (2026-06-02): .btn-stacked utility retires the inline | |
| 308 | + | // F4 (2026-06-02): .button--stacked utility retires the inline | |
| 309 | 309 | // style.display/width/marginBottom triple. | |
| 310 | 310 | for (const a of actions) { | |
| 311 | - | const btn = document.createElement('button'); | |
| 312 | - | btn.className = 'btn btn-stacked'; | |
| 313 | - | btn.textContent = a.label; | |
| 314 | - | btn.addEventListener('click', () => { BB.ui.closeModal(); a.action(); }); | |
| 315 | - | body.appendChild(btn); | |
| 311 | + | const button = document.createElement('button'); | |
| 312 | + | button.className = 'button button--stacked'; | |
| 313 | + | button.textContent = a.label; | |
| 314 | + | button.addEventListener('click', () => { BB.ui.closeModal(); a.action(); }); | |
| 315 | + | body.appendChild(button); | |
| 316 | 316 | } | |
| 317 | 317 | ||
| 318 | 318 | BB.ui.openModal(); |
| @@ -61,9 +61,9 @@ | |||
| 61 | 61 | const popover = document.getElementById('mobile-more-popover'); | |
| 62 | 62 | if (popover) { | |
| 63 | 63 | popover.addEventListener('click', (e) => { | |
| 64 | - | const btn = e.target.closest('[data-action]'); | |
| 65 | - | if (btn) { | |
| 66 | - | handleMoreAction(btn.dataset.action); | |
| 64 | + | const button = e.target.closest('[data-action]'); | |
| 65 | + | if (button) { | |
| 66 | + | handleMoreAction(button.dataset.action); | |
| 67 | 67 | closeMorePopover(); | |
| 68 | 68 | } | |
| 69 | 69 | }); | |
| @@ -163,7 +163,7 @@ | |||
| 163 | 163 | const header = document.querySelector('.detail-header'); | |
| 164 | 164 | if (header && !header.querySelector('.mobile-back-btn')) { | |
| 165 | 165 | const backBtn = document.createElement('button'); | |
| 166 | - | backBtn.className = 'btn btn-sm mobile-back-btn'; | |
| 166 | + | backBtn.className = 'button button--sm mobile-back-btn'; | |
| 167 | 167 | backBtn.textContent = '\u2190 Back'; | |
| 168 | 168 | backBtn.addEventListener('click', () => BB.detail.close()); | |
| 169 | 169 | header.prepend(backBtn); |
| @@ -68,12 +68,12 @@ | |||
| 68 | 68 | <div class="form-group"> | |
| 69 | 69 | <label>Conditions (all must match)</label> | |
| 70 | 70 | <div id="qf-conditions"></div> | |
| 71 | - | <button class="btn btn-sm add-condition-btn" type="button">+ Add Condition</button> | |
| 71 | + | <button class="button button--sm add-condition-btn" type="button">+ Add Condition</button> | |
| 72 | 72 | </div> | |
| 73 | 73 | <div class="match-preview" id="qf-match-preview"></div> | |
| 74 | 74 | <div class="modal-actions"> | |
| 75 | - | <button class="btn" id="qf-cancel">Cancel</button> | |
| 76 | - | <button class="btn btn-primary" id="qf-save">${isEdit ? 'Save' : 'Create'}</button> | |
| 75 | + | <button class="button" id="qf-cancel">Cancel</button> | |
| 76 | + | <button class="button button--primary" id="qf-save">${isEdit ? 'Save' : 'Create'}</button> | |
| 77 | 77 | </div> | |
| 78 | 78 | </div> | |
| 79 | 79 | `; | |
| @@ -123,7 +123,7 @@ | |||
| 123 | 123 | } | |
| 124 | 124 | ||
| 125 | 125 | row.innerHTML = `${fieldSelect} ${opSelect} ${valueInput} | |
| 126 | - | <button class="btn btn-sm cond-remove" data-idx="${idx}" title="Remove" aria-label="Remove condition">×</button>`; | |
| 126 | + | <button class="button button--sm cond-remove" data-idx="${idx}" title="Remove" aria-label="Remove condition">×</button>`; | |
| 127 | 127 | ||
| 128 | 128 | // Field change -> update operators and re-render | |
| 129 | 129 | row.querySelector('.cond-field').onchange = (e) => { |
| @@ -61,11 +61,11 @@ | |||
| 61 | 61 | div.innerHTML = | |
| 62 | 62 | '<p>Sync your feeds and preferences across devices via Makenot.work.</p>' + | |
| 63 | 63 | '<p>All data is encrypted on your device before it leaves.</p>'; | |
| 64 | - | const btn = document.createElement('button'); | |
| 65 | - | btn.className = 'btn btn-primary'; | |
| 66 | - | btn.textContent = 'Connect to Makenot.work'; | |
| 67 | - | btn.onclick = () => startAuth(); | |
| 68 | - | div.appendChild(btn); | |
| 64 | + | const button = document.createElement('button'); | |
| 65 | + | button.className = 'button button--primary'; | |
| 66 | + | button.textContent = 'Connect to Makenot.work'; | |
| 67 | + | button.onclick = () => startAuth(); | |
| 68 | + | div.appendChild(button); | |
| 69 | 69 | container.appendChild(div); | |
| 70 | 70 | } | |
| 71 | 71 | ||
| @@ -136,7 +136,7 @@ | |||
| 136 | 136 | ||
| 137 | 137 | const submitBtn = document.createElement('button'); | |
| 138 | 138 | submitBtn.type = 'submit'; | |
| 139 | - | submitBtn.className = 'btn btn-primary'; | |
| 139 | + | submitBtn.className = 'button button--primary'; | |
| 140 | 140 | submitBtn.textContent = 'Complete Auth'; | |
| 141 | 141 | form.appendChild(submitBtn); | |
| 142 | 142 | ||
| @@ -271,7 +271,7 @@ | |||
| 271 | 271 | actions.className = 'form-actions'; | |
| 272 | 272 | const submitBtn = document.createElement('button'); | |
| 273 | 273 | submitBtn.type = 'submit'; | |
| 274 | - | submitBtn.className = 'btn btn-primary'; | |
| 274 | + | submitBtn.className = 'button button--primary'; | |
| 275 | 275 | submitBtn.textContent = hasKey ? 'Unlock' : 'Set Password'; | |
| 276 | 276 | actions.appendChild(submitBtn); | |
| 277 | 277 | form.appendChild(actions); | |
| @@ -331,7 +331,7 @@ | |||
| 331 | 331 | ||
| 332 | 332 | // Sync now button | |
| 333 | 333 | const syncBtn = document.createElement('button'); | |
| 334 | - | syncBtn.className = 'btn btn-primary sync-action-spaced'; | |
| 334 | + | syncBtn.className = 'button button--primary sync-action-spaced'; | |
| 335 | 335 | syncBtn.textContent = 'Sync Now'; | |
| 336 | 336 | syncBtn.onclick = async () => { | |
| 337 | 337 | syncBtn.disabled = true; | |
| @@ -408,7 +408,7 @@ | |||
| 408 | 408 | ||
| 409 | 409 | // Disconnect | |
| 410 | 410 | const disconnectBtn = document.createElement('button'); | |
| 411 | - | disconnectBtn.className = 'btn sync-disconnect'; | |
| 411 | + | disconnectBtn.className = 'button sync-disconnect'; | |
| 412 | 412 | disconnectBtn.textContent = 'Disconnect'; | |
| 413 | 413 | disconnectBtn.onclick = async () => { | |
| 414 | 414 | // F6 fix (2026-06-02): was native confirm(), replaced per | |
| @@ -469,8 +469,8 @@ | |||
| 469 | 469 | 'On a monthly plan we pay that fee twelve times a year; annual pays it once.' + | |
| 470 | 470 | '</p>' + | |
| 471 | 471 | '<div class="sync-sub-actions">' + | |
| 472 | - | '<button class="btn btn-primary" id="sync-sub-annual">Subscribe (' + annual + '/year)</button>' + | |
| 473 | - | '<button class="btn" id="sync-sub-monthly">' + monthly + '/month</button>' + | |
| 472 | + | '<button class="button button--primary" id="sync-sub-annual">Subscribe (' + annual + '/year)</button>' + | |
| 473 | + | '<button class="button" id="sync-sub-monthly">' + monthly + '/month</button>' + | |
| 474 | 474 | '</div>'; | |
| 475 | 475 | } | |
| 476 | 476 | } catch (_) { /* fall through */ } |
| @@ -311,10 +311,10 @@ | |||
| 311 | 311 | ||
| 312 | 312 | // Action buttons | |
| 313 | 313 | const actions = `<div class="hp-actions"> | |
| 314 | - | <button class="btn btn-sm" data-action="mark-read">Mark All Read</button> | |
| 315 | - | <button class="btn btn-sm" data-action="edit">Edit Feed</button> | |
| 316 | - | <button class="btn btn-sm" data-action="tags">Edit Tags</button> | |
| 317 | - | <button class="btn btn-sm btn-danger" data-action="delete">Delete</button> | |
| 314 | + | <button class="button button--sm" data-action="mark-read">Mark All Read</button> | |
| 315 | + | <button class="button button--sm" data-action="edit">Edit Feed</button> | |
| 316 | + | <button class="button button--sm" data-action="tags">Edit Tags</button> | |
| 317 | + | <button class="button button--sm button--danger" data-action="delete">Delete</button> | |
| 318 | 318 | </div>`; | |
| 319 | 319 | ||
| 320 | 320 | pop.innerHTML = `<div class="hp-title">${escapeHtml(source.name)}</div>${rows}${actions}`; | |
| @@ -460,11 +460,11 @@ | |||
| 460 | 460 | bar.appendChild(allBtn); | |
| 461 | 461 | ||
| 462 | 462 | allTags.forEach(t => { | |
| 463 | - | const btn = document.createElement('button'); | |
| 464 | - | btn.className = 'tag-chip' + (currentTag === t ? ' active' : ''); | |
| 465 | - | btn.textContent = t; | |
| 466 | - | btn.addEventListener('click', () => selectTag(t)); | |
| 467 | - | bar.appendChild(btn); | |
| 463 | + | const button = document.createElement('button'); | |
| 464 | + | button.className = 'tag-chip' + (currentTag === t ? ' active' : ''); | |
| 465 | + | button.textContent = t; | |
| 466 | + | button.addEventListener('click', () => selectTag(t)); | |
| 467 | + | bar.appendChild(button); | |
| 468 | 468 | }); | |
| 469 | 469 | } | |
| 470 | 470 |
| @@ -705,7 +705,7 @@ | |||
| 705 | 705 | const readyDiv = body.children.find(c => c.className === 'sync-ready'); | |
| 706 | 706 | assert(readyDiv, 'Should have sync-ready div'); | |
| 707 | 707 | const hasDisconnect = readyDiv.children.some(c => | |
| 708 | - | c.className === 'btn sync-disconnect' && c._text === 'Disconnect' | |
| 708 | + | c.className === 'button sync-disconnect' && c._text === 'Disconnect' | |
| 709 | 709 | ); | |
| 710 | 710 | assert(hasDisconnect, 'Should have Disconnect button'); | |
| 711 | 711 | }); |