aboutsummaryrefslogtreecommitdiffstats
path: root/frontend-vanilla
Commit message (Collapse)AuthorAgeFilesLines
* Fix star/read buttons: _id string vs number type mismatchclaude/agents-file-mobile-stars-2nj6yClaude24 hours3-16/+33
| | | | | | | | | | | | | | | The Go API returns _id as a JSON string (due to the `json:",string"` tag on Item.Id), but the frontend compared it with === against numbers from parseInt(). String "5" === number 5 is always false in JS, so toggleStar, mark-as-read, and keyboard shortcuts silently did nothing. Fix: - Coerce _id to Number() when items are loaded from the API - Use Number() coercion in all store.items.find() comparisons as defense - Revert the CSS touch-target changes (the issue was never about size) - Add a regression test with string _id to prevent reintroduction https://claude.ai/code/session_012CNdRhGhU3hxjrwvZt2BHZ
* Add AGENTS.md and fix star button tap targets on mobileClaude25 hours1-0/+9
| | | | | | | | | | | | Add AGENTS.md with TDD workflow and check-in guidance for agents. Fix star buttons being nearly impossible to tap on mobile by: - Adding min-width/min-height of 44px for proper touch targets - Adding flex-shrink: 0 so the button isn't squeezed by long titles - Overriding generic button styles (height, text-transform, font-weight) that bled into the star button https://claude.ai/code/session_012CNdRhGhU3hxjrwvZt2BHZ
* Remove scrape/text button that caused squished body textclaude/fix-mobile-scrolling-Ls0FrClaude30 hours1-7/+4
| | | | | | | | | The float:right "text" button inside .dateline was causing .item-description content to wrap around it when .feed-item gained overflow:hidden. Removing the button fixes the squished text regression. The backend scrape endpoint and scrapeItem() handler remain intact for potential future use. https://claude.ai/code/session_0141nhxmYfoFPVPZ813K1XFD
* Exclude test files from tsc build and rebuild production assetsClaude41 hours2-2/+3
| | | | | | | | | | Test files use Node built-ins (fs, path) which aren't available to the browser-targeted tsconfig. Excluding *.test.ts from tsc is the standard Vite/Vitest pattern — vitest handles test type-checking separately. Also rebuilds web/dist/v3/ to include the CSS overflow fixes. https://claude.ai/code/session_0141nhxmYfoFPVPZ813K1XFD
* Fix feed-item overflow and flex shrink bug causing mobile horizontal scrollClaude43 hours2-56/+68
| | | | | | | | | | | | | The previous fix (overflow-x:hidden on .main-content and .item-description) was insufficient because mobile Safari ignores overflow-x:hidden on elements with overflow-y:auto. The real fix is item-level containment: - .feed-item: add overflow:hidden to create a BFC so no child content can push the viewport wider, even during async image load reflows - .item-title: add min-width:0 (fixes flex min-width:auto bug that prevents shrinking below content width) and overflow-wrap:break-word for long titles https://claude.ai/code/session_0141nhxmYfoFPVPZ813K1XFD
* Fix mobile horizontal scrolling caused by wide RSS contentClaude2 days2-1/+158
| | | | | | | | | | | RSS feeds can contain tables, iframes, and other elements with explicit widths that overflow the viewport on mobile. Added overflow-x: hidden to .item-description and .main-content, and extended max-width: 100% to cover table and iframe elements inside item descriptions. Includes TDD tests verifying the CSS containment rules. https://claude.ai/code/session_0141nhxmYfoFPVPZ813K1XFD
* Remove link underline on hover for item titlesClaude8 days1-1/+1
| | | | | | | Removed text-decoration: underline from .item-title:hover in the source CSS and rebuilt the frontend assets so the compiled dist reflects the change. https://claude.ai/code/session_011Y2tBL3goxNWHqUaJ8Bpzh
* Add core robustness tests for scroll-to-read, infinite scroll, and keyboard ↵Adam Mathes11 days1-0/+226
| | | | navigation
* Remove visual styling for read items per user requestAdam Mathes11 days5-39/+4
|
* Improve scroll-to-read robustness and add visual feedback for read items ↵Adam Mathes11 days6-36/+87
| | | | across all themes
* Add regression tests for mark-as-read and partial updatesAdam Mathes11 days1-139/+13
|
* Fix mark-as-read regression and add debugging toolsAdam Mathes11 days1-44/+52
|
* Revert polling interval back to 1sclaude/investigate-theme-performance-GjjYAClaude11 days3-6/+6
| | | | https://claude.ai/code/session_0187FXrbScDSWfbNEk9SfJaj
* Fix theme performance regressions affecting mobile scrollClaude11 days7-41/+55
| | | | | | | | | | | | | | | | | | | | | The new theme CSS files introduced several patterns that cause scroll jank and memory pressure, especially on mobile: - terminal.css: Full-viewport fixed pseudo-element with repeating gradient scanlines forced GPU compositing on every scroll frame. Now limited to desktop only with will-change layer promotion. - codex.css/sakura.css: text-rendering: optimizeLegibility on body triggered expensive kerning/ligature computation on all text. - codex.css: font-feature-settings forced text shaper on every glyph. - codex.css: hyphens: auto required dictionary lookups during layout. - style.css: transition: all on buttons and sidebar links caused unnecessary animation work during scroll hover state changes. - main.ts: checkReadItems did O(n) individual querySelector calls per scroll tick; switched to single querySelectorAll batch query. - Polling interval reduced from 1s to 3s (scroll handler already covers the normal case, polling is just a robustness fallback). https://claude.ai/code/session_0187FXrbScDSWfbNEk9SfJaj
* Redesign sidebar theme controls layout and fix dark mode visibilityclaude/add-css-themes-QGTmPClaude12 days2-36/+51
| | | | | | | | | | | | Split light/dark into ☀ ☽ buttons above a horizontal rule, with the 5 style emoji below. Increases icon size from 0.8rem to 1rem. Replaces opacity-only approach with explicit rgba(0,0,0) color in dark mode (sidebar remains grey in dark theme, so icons need dark ink). Switches hover/active backgrounds to neutral rgba(128,128,128) so they work correctly across all themes and modes. https://claude.ai/code/session_01Jv3c8GdaDQMm5WYwHUJMVe
* Remove visual 'selected' state highlight from feed itemsAdam Mathes12 days4-25/+9
|
* Fix scrolling behavior, CI linting, and update DockerfileAdam Mathes12 days1-1/+1
|
* Replace sidebar style cycle button with 5 emoji iconsClaude12 days2-21/+43
| | | | | | | | | Swap the single cycle button for individual emoji per theme: ○ Default, ◆ Refined, ▮ Terminal, ❧ Codex, ❀ Sakura. Active theme gets a highlighted state. Separated from the light/dark toggle with a thin divider. https://claude.ai/code/session_01Jv3c8GdaDQMm5WYwHUJMVe
* Refine themes, add sidebar controls, and theme docsClaude12 days5-80/+342
| | | | | | | | | | | | | | | | | | | | Refined: softer dark-mode link color (#a0c4e8), fix export button vertical alignment with inline-flex, tighten settings page spacing (reduce gaps from 3rem to 1.5rem). Terminal: switch accent from cyan to green (#4ae54a dark / #1a7a2e light), add proper light mode with pale steel background, scanlines only in dark mode. Sidebar: add quick-access controls in footer — moon/sun icon toggles light/dark, circle icon cycles through style themes showing current name. Both update reactively on state change. Add THEMES.md with full documentation on creating new themes: variable reference, selector guide, light/dark mode tips, and the registration process. https://claude.ai/code/session_01Jv3c8GdaDQMm5WYwHUJMVe
* Add 4 CSS style themes with runtime switcherClaude12 days6-3/+1686
| | | | | | | | | | | | | | | | Adds a style theme system that layers additional CSS files on top of the base stylesheet. Themes are loaded/unloaded dynamically via <link> tags. - Default: existing look, unchanged - Refined: typographic rhythm fixes, consistent spacing on settings page - Terminal: monospace, dark phosphor CRT aesthetic (scanlines, cyan glow) - Codex: book/Tufte-inspired with warm paper tones, serif type, fleurons - Sakura: Japanese-inspired calm aesthetic (named for neko = cat) Each theme supports both light and dark mode. Style selection persists in localStorage and is independent of the light/dark toggle. https://claude.ai/code/session_01Jv3c8GdaDQMm5WYwHUJMVe
* Refine Settings labels and apply heading font to sidebarAdam Mathes12 days2-5/+5
|
* Refine Settings UI: Fix dark mode text colors, split font controls for ↵Adam Mathes12 days5-10/+89
| | | | headers and body, update monospace stack, and soft-deprecate tags
* Soft deprecate tags feature in Sidebar and fix lint errorsAdam Mathes12 days1-11/+15
|
* Soft deprecate tags feature in SettingsAdam Mathes12 days2-1/+6
|
* Fix feed handling: Send full feed object on update to satisfy backend ↵Adam Mathes12 days2-2/+16
| | | | requirements
* Refine Settings UI: Full-width feed list, simplified data section, removed ↵Adam Mathes12 days2-122/+31
| | | | dividers
* Refine Settings page: Consistently use Helvetica fonts, remove dividers, ↵Adam Mathes12 days1-363/+162
| | | | simplify Feed list to rows
* Redesign Settings page: grid layout and extended import/export optionsAdam Mathes12 days2-81/+483
|
* Fix regression: mark-as-read not triggering on window scrollAdam Mathes12 days2-29/+65
|
* Fix infinite scroll not triggering on scrollAdam Mathes12 days2-1/+123
|
* Configure vitest for low-resource VM environmentsAdam Mathes12 days1-0/+3
|
* fix: add explicit height to .main-content so overflow-y scrollsClaude12 days1-0/+1
| | | | | | | | | | | | | | | | When the sidebar was changed to position:fixed (overlay mode), flex:1 was removed from .main-content. Without flex:1 or an explicit height, .main-content relied on align-items:stretch for its height constraint. This is unreliable for establishing a definite height that overflow-y:auto respects — the element can grow with its content instead of constraining at 100vh and scrolling. Add height:100% to .main-content so it has a definite height from the parent chain (body 100vh → #app 100% → .layout 100% → .main-content 100%). This ensures overflow-y:auto creates a proper scroll container, which is required for both the scroll-based infinite loading and mark-as-read to work. https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
* fix: replace IntersectionObserver with scroll-position check for infinite scrollClaude12 days2-67/+66
| | | | | | | | | | | | | | | | | | | | | | | | | | The IntersectionObserver approach for infinite scroll was unreliable — items would not load when scrolling to the bottom in v3, while v1's polling approach worked fine. The issue was that IntersectionObserver with a custom root element (main-content, whose height comes from flex align-items:stretch rather than an explicit height) didn't fire reliably, and renderItems() being called 3 times per fetch cycle (from both items-updated and loading-state-changed events) kept destroying and recreating the observer. Replace with a simple scroll-position check in the existing onscroll handler, matching v1's proven approach: when the user scrolls within 200px of the bottom of #main-content, trigger loadMore(). This runs on every scroll event (cheap arithmetic comparison) and only fires when content actually overflows the container. Remove the unused itemObserver module-level variable. Update regression tests to simulate scroll position instead of IntersectionObserver callbacks, with 4 cases: scroll near bottom triggers load, scroll far from bottom doesn't, loading=true blocks, and hasMore=false hides sentinel. https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
* fix: store sentinel IntersectionObserver in module-level variable to prevent GCClaude12 days2-3/+98
| | | | | | | | | | | | | | | | | | The load-more sentinel observer was assigned to a local `const observer` that fell out of scope after renderItems() returned. Without a persistent JS reference, engines can garbage-collect the observer, silently breaking infinite scroll (no more items loaded on scroll). Fix: assign to the existing module-level `itemObserver` variable, which is already disconnected/replaced at the top of each renderItems() call. Add three regression tests in regression.test.ts that use a class-based IntersectionObserver mock to capture the callback and verify: - sentinel visible → loadMore fires - sentinel visible while loading → loadMore suppressed - hasMore=false → no sentinel rendered, no loadMore https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
* test: loosen DOM insertion perf thresholds for slow CI runnersClaude12 days1-3/+3
| | | | | | | | 100-item DOM insertion: 200ms -> 500ms (CI took 260ms, 2x headroom) 500-item DOM insertion: update test name to match actual 1400ms threshold (the 1400ms limit was already in code; test name was stale) Update benchmarks-02.md to reflect corrected thresholds.
* Add regression tests for NK-t8qnrh, NK-mcl01m, NK-z1czaq (NK-26sdqp)Claude13 days1-1/+91
| | | | | | | | | | - NK-t8qnrh: test that item-description renders links in feed items - NK-mcl01m: test sidebar section order (filters → search → feeds → tags), and presence of "+ new" link - NK-z1czaq: test that sidebar and main-content are siblings (overlay layout) - Import renderLayout and createFeedItem into regression test suite https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
* v3 UI: Sidebar always overlays content, never shifts it (NK-z1czaq)Claude13 days1-13/+29
| | | | | | | | Make sidebar position: fixed on desktop, same as mobile. Content area fills full viewport width and items remain centered regardless of sidebar state. Easy-to-revert CONTENT CENTERING PARAMETER comment added. https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
* v3 UI: Fix dark mode visual bugs (NK-pbqvke)Claude13 days1-0/+33
| | | | | | | | | | - Sidebar uses grey background with dark text in dark mode - Sidebar toggle has no background in dark mode - Sidebar search input uses light bg with dark text in dark mode - item-description links use correct color (--link-color = #5ac8fa in dark) and no underline (fixed in prior commit) https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
* v3 UI: Reorder sidebar sections per ticket NK-mcl01mClaude13 days2-7/+13
| | | | | | | | | New order: filters (Unread/All/Starred) → search → "+ new" → Feeds → Tags Previously: search → filters → Tags → Feeds Also adjust sidebar-search margin now that it's inside the scroll area. https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
* Fix link underlines in v3 UI and SSRF proxy bypassClaude13 days1-0/+5
| | | | | | | | | | - Add text-decoration: none to .item-description a links in v3 CSS to match v1 style (no underlines on feed item content links) - Fix safehttp to disable proxy on safe client; without this, HTTP proxy env vars bypass the DialContext SSRF check for IPs like 10.0.0.1, causing TestSafeClient to fail https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
* Complete V2 removal from Makefile and check in updated V3 production assetsAdam Mathes13 days1-1/+1
|
* Update V3 dark mode to use true black background (#000000) matching V1 ↵Adam Mathes13 days1-5/+5
| | | | legacy theme
* Update V2/V3 'mark as read' logic to require item bottom to be above ↵Adam Mathes13 days3-17/+48
| | | | viewport, while keeping V1 unchanged
* Update frontend build artifacts and fix test lint errorsAdam Mathes13 days2-2/+2
|
* Add regression test for scroll-to-read functionalityAdam Mathes13 days1-0/+138
|
* Fix scroll-to-read functionality across all UIs (V1, V2, V3)Adam Mathes13 days2-32/+55
|
* Remove circle styling from NEKO sidebar toggle buttonclaude/thicket-ready-crank-RmQuIClaude13 days1-6/+2
| | | | | | | Strip border-radius, box-shadow, background, and backdrop-filter from the sidebar toggle in both v2 and v3 frontends so the logo appears flat. https://claude.ai/code/session_019Z4VJxzY7tcAuNkPAkvry9
* Merge pull request #7 from adammathes/claude/thicket-ready-crank-RmQuIAdam Mathes13 days1-6/+4
|\ | | | | More crank pulls from claude
| * Align sidebar CSS breakpoints with JS threshold at 1024pxClaude13 days1-6/+4
| | | | | | | | | | | | | | | | The sidebar default-closed JS logic used 1024px but CSS media queries used 768px, causing inconsistent behavior on tablets. Updated all sidebar-related breakpoints to 1024px/1025px to match. https://claude.ai/code/session_019Z4VJxzY7tcAuNkPAkvry9
* | Fix mobile scroll not marking items as read in v3 UIClaude13 days2-8/+13
|/ | | | | | | | | | | | | | Two issues prevented IntersectionObserver from firing on mobile: 1. threshold: 1.0 required items to be 100% visible, but on mobile viewports items with descriptions are often taller than the screen 2. root: null used the viewport, but scrolling happens inside .main-content (overflow-y: auto) while body has overflow: hidden Switched to "scrolled past" pattern: items are marked read when they scroll above the viewport (like the working legacy UI). Set root to the actual scroll container element. https://claude.ai/code/session_01NSUnBzNrgQVUNg9PnugF7N