Skip to content

feat(frontend): animation polish PR 2 — secondary polish (Tier 1 P2 + Tier 2 layout)#251

Merged
dackclup merged 1 commit into
mainfrom
claude/anim-pr2-secondary
May 25, 2026
Merged

feat(frontend): animation polish PR 2 — secondary polish (Tier 1 P2 + Tier 2 layout)#251
dackclup merged 1 commit into
mainfrom
claude/anim-pr2-secondary

Conversation

@dackclup
Copy link
Copy Markdown
Owner

Summary

Second PR of the post-LedgerCraft animation polish series (continuation from #250). Continues the frontend-design-reviewer audit Section C PR 2 scope — P2 micro-interaction polish + Tier 2 layout refactor.

13 edits across 6 components — pure className diff + 1 small JSX refactor. Zero new keyframes, zero new deps, zero schema / Python / scoring / valuation / output JSON change.

LedgerCraft compliance: every transition ≤ 200ms; ease-out standard; functional state-change feedback only.

The 13 edits

P2 button hover transitions (smooth color fade was instant-snap):

# File:line Element
B1 FilterDrawer.tsx:127 Close button (X)
B2 FilterDrawer.tsx:289 "Clear all" button
B3 AppShell.tsx:58 mobile hamburger menu button

Active filter chip dismissal (RankingTable toolbar — 5 chip variants):

# File:line Element
B4 RankingTable.tsx:334 active sector filter chip
B5 RankingTable.tsx:349 active tier filter chip
B6 RankingTable.tsx:364 active MoS filter chip
B7 RankingTable.tsx:377 active recommendation filter chip
B8 RankingTable.tsx:388 active score-range filter chip

All five gain transition-opacity duration-100 so the hover → 75% opacity fade is smooth.

Pagination buttons (RankingTable footer):

# File:line Element
B9 RankingTable.tsx:620 "← Prev"
B10 RankingTable.tsx:631 "Next →"

Per-method row hover (Fair price card list):

# File:line Change
B11 FairPriceBarChart.tsx:316 <li> gains hover:bg-slate-50 dark:hover:bg-slate-800/30 transition-colors duration-100. Previously had ZERO hover state (sibling FairPriceCard.tsx MethodRow already has hover post-PR 1)

Filing link hover (Tier-2 event card):

# File:line Change
B12 Tier2EventCard.tsx:202 "View filing" external link — transition-colors duration-150 smoothens hover → text-slate-900 + underline

Tier 2 layout refactor (small JSX change, not just className):

# File:lines Change
B13 Sidebar.tsx:84-91 mobile overlay backdrop refactored from conditional render ({mobileOpen && <button>}) to always-mounted opacity toggle. Mirrors FilterDrawer backdrop pattern: transition-opacity duration-200 with pointer-events-none opacity-0 when closed. Added aria-hidden={!mobileOpen} + tabIndex={mobileOpen ? 0 : -1} so the invisible backdrop can't trap keyboard focus when closed. Visual result: mobile nav drawer backdrop now FADES in/out instead of snap-appearing/disappearing

Out of scope this PR

Queued for PR 3 — skeleton loaders:

  • @keyframes shimmer + @keyframes fade-in in globals.css
  • tailwind.config.ts keyframes/animation registration
  • PriceHistoryChart loading state → shimmer
  • StockLogo image fade-in

Permanently out (LedgerCraft restraint, carry-over from PR 1):

  • Decorative animations (ScoreBadge / MoSBadge radial arc-draw)
  • ThemeToggle icon crossfade (Framer Motion territory)
  • Body color crossfade on theme toggle (next-themes disableTransitionOnChange blocks)
  • Recharts Area draw animation (kept isAnimationActive={false})

Test plan

  • cd frontend && npx --no -- tsc --noEmit clean (CI runs with deps)
  • cd frontend && npx --no -- next build produces all 506 static pages
  • Vercel preview spot-check (when posted):
    • Hover Close button (X) in FilterDrawer header — slate-100 fade
    • Hover "Clear all" button in FilterDrawer footer — slate-100 fade
    • Mobile: tap hamburger → backdrop FADES in (not snap-in) alongside sidebar slide
    • Open RankingTable filters → apply 2-3 filters → hover active chip → 75% opacity smooth fade (not snap)
    • Hover Prev/Next pagination buttons — slate-50 fade
    • Open a stock detail page → hover any Fair Price per-method row — slate-50 fade
    • Open a stock with Tier-2 events → hover "View filing" link — text-slate-900 + underline fade
    • Mobile drawer close: tap backdrop → backdrop FADES out (was snap-disappear)
    • Dark mode parity — every transition works identically with dark variants
  • Accessibility: focus the mobile backdrop with Tab when sidebar is closed — focus should NOT land on the invisible backdrop (verified by tabIndex={-1} when !mobileOpen)

Doc lockstep

PHASE_STATUS_INFLIGHT.md side-file pattern (PR #237) satisfies §Conventions "ship with every PR" lockstep. CLAUDE.md / AGENTS.md substance UNCHANGED.

Series progress

  • PR 1 (#250) — 11 micro-interactions
  • PR 2 (this) — 13 secondary polish + layout refactor
  • 🔜 PR 3 — skeleton loaders + globals.css @keyframes

Generated by Claude Code

… Tier 2 layout)

13 edits across 6 components — pure className diff + 1 small JSX
refactor. Zero new keyframes, zero new deps, zero schema change.
LedgerCraft compliance: every transition ≤ 200ms; ease-out standard;
functional state-change feedback only.

P2 button hover transitions:
- FilterDrawer.tsx:127 — Close button (X)
- FilterDrawer.tsx:289 — "Clear all" button
- AppShell.tsx:58 — mobile hamburger menu button

Active filter chip dismissal (5 chip variants):
- RankingTable.tsx:334/349/364/377/388 — sector/tier/MoS/recommendation
  /score-range chips get transition-opacity duration-100

Pagination buttons:
- RankingTable.tsx:620/631 — Prev/Next buttons

Per-method row hover (Fair price card list):
- FairPriceBarChart.tsx:316 — li gains hover:bg-slate-50 +
  dark:hover:bg-slate-800/30 + transition-colors duration-100
  (sibling FairPriceCard.tsx MethodRow already had hover post-PR 1)

Filing link hover (Tier-2 event card):
- Tier2EventCard.tsx:202 — "View filing" external link

Tier 2 layout refactor (JSX change):
- Sidebar.tsx:84-91 — mobile overlay backdrop refactored from
  conditional render to always-mounted opacity toggle. Mirrors
  FilterDrawer backdrop pattern: transition-opacity duration-200
  + aria-hidden + tabIndex toggle. Backdrop now FADES in/out instead
  of snap-appearing/disappearing alongside the sidebar slide.

PHASE_STATUS_INFLIGHT.md side-file pattern (PR #237) satisfies
§Conventions lockstep. CLAUDE.md / AGENTS.md substance UNCHANGED.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 25, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
quantrank Ready Ready Preview, Comment May 25, 2026 3:06am

@dackclup dackclup marked this pull request as ready for review May 25, 2026 03:10
@dackclup dackclup merged commit e23861a into main May 25, 2026
4 checks passed
@dackclup dackclup deleted the claude/anim-pr2-secondary branch May 25, 2026 03:10
dackclup added a commit that referenced this pull request May 25, 2026
…#252)

Closes the 3-tier animation polish series (PR 1 #250 + PR 2 #251 + this).
Adds the project's first @Keyframes declarations + Tailwind animation
utilities. Zero new deps; +~600 bytes CSS uncompressed.

LedgerCraft compliance: shimmer at 1.5s linear (loading convention,
not the 200ms button transition budget); fade-in at 200ms ease-out;
prefers-reduced-motion guard falls back to static slate-200 (light) /
slate-800 (dark) placeholder so the skeleton STILL communicates
"loading" without motion.

The 5 edits:

- tailwind.config.ts — register shimmer + fade-in keyframes +
  animation utilities in theme.extend
- app/globals.css (end) — @Keyframes shimmer (background-position
  sweep -200% → +200%) + @Keyframes fade-in + .animate-shimmer
  light/dark gradient + reduced-motion guard
- PriceHistoryChart.tsx:118-124 — loading state replaced from
  centered text "Loading price history…" to 4-block shimmer
  skeleton (headline + change row + period selector + chart canvas).
  Wrapped in aria-busy + aria-live="polite" + sr-only span for
  screen reader announcement
- StockLogo.tsx:80-88 — imgStyle gains animation: 'fade-in 200ms
  ease-out' so the Parqet SVG logo fades in on mount instead of
  flashing in
- StockLogo.tsx:57-72 — fallbackStyle (deterministic letter-avatar)
  also gains the fade-in animation for visual symmetry with the img
  path when onError swaps in

PHASE_STATUS_INFLIGHT.md side-file pattern (PR #237) satisfies
§Conventions lockstep. CLAUDE.md / AGENTS.md substance UNCHANGED.

Co-authored-by: Claude <noreply@anthropic.com>
dackclup added a commit that referenced this pull request May 26, 2026
…stale INFLIGHT markers (#267)

Phase B (post-tag housekeeping) per the v1.3.0 release plan. Pure
doc-pointer maintenance; no code touched.

Scope (3 files):
- CLAUDE.md §Phase status — Latest release tag pointer bumped
  v1.2.0-phase4.5 (6d414a9) → v1.3.0-phase4.5e (5db3b97);
  prior tag preserved as historical reference
- PHASE_STATUS.md §Current state — same pointer bump + one-line
  description of what the release closes
- PHASE_STATUS_INFLIGHT.md — 11 stale (in flight) header markers
  updated to (merged YYYY-MM-DD, SHA) with PR number prefix; PRs
  drained: #244 / #245 / #246 / #250 / #251 / #252 / #256 / #257 /
  #258 / #263 / #266. Bodies stay in place (full historical record
  preserved); future weekly housekeeping commit moves them between
  sections per PR #237 convention.

Note on tag: v1.3.0-phase4.5e was created locally during the
release session but `git push origin <tag>` failed HTTP 403 from
sandbox (proxy permits branch pushes, not tag-ref pushes). User
runs the tag commit + push from their own machine on the squash-
merge SHA 5db3b97. This PR's pointer bumps reference the tag AS
IF live per release-tag SKILL.md §7 (anchors to commit SHA, not
tag-availability state).

Markdown-only diff; ruff / schema_check / pytest N/A.

PHASE_STATUS_INFLIGHT.md side-file satisfies §Conventions "ship
with every PR" lockstep per PR #237 convention.

https://claude.ai/code/session_01JwntEE4PNAXSMkZxRA9BB4

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants