Skip to content

feat(frontend): motion + price-chart polish — app-wide ease-in-out · sidebar smooth · risk-flag static · price-chart tweaks#330

Merged
dackclup merged 6 commits into
mainfrom
claude/optimistic-brown-UUcXA
May 31, 2026
Merged

feat(frontend): motion + price-chart polish — app-wide ease-in-out · sidebar smooth · risk-flag static · price-chart tweaks#330
dackclup merged 6 commits into
mainfrom
claude/optimistic-brown-UUcXA

Conversation

@dackclup
Copy link
Copy Markdown
Owner

Per user direction (2026-05-30): "เปลี่ยนไปใช้ animation ขยับแบบ ease in and out ทั้ง app" — unify every discrete move / entrance / slide / sweep animation onto a single ease-in-out timing curve (accelerate out of the start, decelerate into the end — one calm, symmetric feel). Frontend-only; timing-function diff; zero schema / compute change.

Changes (6 files)

File Was Now
tailwind.config.ts fade-in (ease-out) · rise-in / gauge-style (cubic-bezier(0.22,1,0.36,1)) · chip-pop (cubic-bezier(0.34,1.56,0.64,1) back-out) · flag-pulse (ease-out) ease-in-out
app/globals.css .gauge-sweep (ease-out cubic-bezier) · .hover-lift (ease-out) ease-in-out
components/FilterDrawer.tsx slide-over duration-300 ease-out ease-in-out
components/Sidebar.tsx collapse/expand [transition:…_ease-out] ease-in-out
components/PriceHistoryChart.tsx intro-sweep rAF easeOutCubic easeInOutCubic
lib/useMotion.ts useCountUp rAF easeOutCubic easeInOutCubic

Two deliberate carve-outs

  1. shimmer stays linear infinite — ease-in-out on a seamless background-position loop double-decelerates at every wrap boundary (a visible 1.5s "stall pulse"). linear is the only correct choice for a seamless loop.
  2. Bare Tailwind transition-* (no explicit ease-*) already compiles to cubic-bezier(0.4,0,0.2,1) ≈ ease-in-out — left as-is.

chip-pop's overshoot (70% → 1.04) and flag-pulse's settle (55% → 1.012) live in the keyframe %-stops, not the timing curve — so ease-in-out just eases into them and the pop/beat character is preserved. Reduced-motion guard (@media (prefers-reduced-motion: reduce) + the rAF JS-side matchMedia check) untouched — every animation still snaps to its end state.

⚠️ Supersedes a prior ask: last session the price-chart intro sweep was set to เร็วไปช้า (fast→slow = ease-out). The "ทั้ง app" directive makes it match the rest, so the left→right reveal now starts gently. One-line revert (easeInOuteaseOut) if the chart should keep its fast→slow feel.

Verification

  • next build502 routes ✅ · tsc --noEmit clean on edited files ✅
  • Compiled CSS confirms ease-in-out on every animation: / transition: rule (chip-pop / rise-in / flag-pulse / gauge-sweep .8s / hover-lift .16s / Sidebar .2s,width .2s) + linear preserved on shimmer
  • node frontend/components/downsample.test.mjs → 14/14 ✅ · ruff check . clean (no Python) ✅
  • frontend-design-reviewer (sonnet) — PASS all sections, 0 FAIL, 2 non-blocking WARN (chip-pop pop may read marginally softer; chart sweep slow-start on wide viewports — both UX-perception, targeted fixes noted, no revert)

Lockstep via PHASE_STATUS_INFLIGHT.md (#330 entry, per #237) + a CLAUDE.md §Gotchas convention entry ("App-wide motion uses ONE ease-in-out timing curve").

https://claude.ai/code/session_0144kHrCYNaamMPH57b7xdM7


Generated by Claude Code

Unify every discrete move/entrance/slide/sweep animation onto a single
ease-in-out timing curve per user direction ("ease in and out ทั้ง app").

- tailwind.config.ts: fade-in/rise-in/chip-pop/flag-pulse -> ease-in-out
  (shimmer kept linear infinite -- ease-in-out stutters at the loop wrap)
- globals.css: .gauge-sweep + .hover-lift -> ease-in-out
- FilterDrawer + Sidebar slide transitions -> ease-in-out
- PriceHistoryChart intro sweep + useMotion count-up -> easeInOutCubic

Keyframe %-stop overshoots (chip-pop 1.04 / flag-pulse 1.012) preserved;
reduced-motion guard untouched. Timing-function-only; no schema/compute.

https://claude.ai/code/session_0144kHrCYNaamMPH57b7xdM7
@vercel
Copy link
Copy Markdown

vercel Bot commented May 30, 2026

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

Project Deployment Actions Updated (UTC)
quantrank Ready Ready Preview, Comment May 31, 2026 4:31am

The ease-in-out swap alone didn't smooth the desktop sidebar collapse:
the aside transition listed width but not max-width, while the collapsed
state toggles md:max-w-[64px] (+ the globals.css pre-paint rule sets
max-width:4rem). On collapse the un-transitioned max-width snapped to the
64px cap instantly and clamped the rendered width -> the width animation
was nullified -> collapse "snapped" while expand (growing max-width never
clamps) stayed smooth = asymmetric jank.

Add max-width to the transition list so width + max-width animate in
lockstep. Verified via Playwright frame-sampling at 1280px: collapse now
interpolates 240->72px over 13 distinct steps (was a 1-2 frame snap),
expand 72->240px over 10 steps. max-width kept (load-bearing: caps the
fluid-rem w-60 ~270px at the font-size ceiling to a stable 240px).

https://claude.ai/code/session_0144kHrCYNaamMPH57b7xdM7
Per user request ("ช่อง risk flag เอา animation ออก") the veto rows in
RiskFlagsCard now render statically — drop the animate-flag-pulse
stagger entrance beat + the now-unused usePlayOnMount hook/import/index.
The card's rose ring + tone carry the "look here" weight without motion.

flag-pulse keyframe + Tailwind animation entry retained as defined
motion vocabulary (design.md §Motion / web-animation-design skill still
cite it); RiskFlagsCard was its only consumer so the .animate-flag-pulse
utility is no longer emitted (0 in compiled CSS). Verified via Playwright
on /stock/AEP: card renders, rows carry no animate-/stagger class.

https://claude.ai/code/session_0144kHrCYNaamMPH57b7xdM7
…selector below date axis

Per user request ("ตรงหัวข้อ price เอา (1Y) ออก และย้าย 1D-5Y ลงมาไว้ใต้เส้น
แนวนอนวันที่ด้านล่างกราฟ"):

1. Remove the PERIOD_LABEL[period] span ("past year" / "year-to-date" / …)
   from the price-change row, plus the now-unused `scrubbing` local + the
   module-level PERIOD_LABEL map + 2 stale comments.
2. Move <PriceTimePeriodSelector> from above the chart canvas to below the
   chart wrapper (under the X-axis date labels).

Verified via Playwright on /stock/AAPL @1280px: selectorTop 1019 > chartBottom
1006 > xAxisBottom 994 (selector below the date axis); headline change row
renders no period word. next build -> 502 routes; tsc clean.

https://claude.ai/code/session_0144kHrCYNaamMPH57b7xdM7
…ore change-row period label

Correction of the prior commit (a974c82), which removed the WRONG (1Y):
the user meant the big <h2>Price (1y)</h2> section heading on the stock
detail page, not the small period label in the price-change row.

- app/stock/[ticker]/page.tsx: "Price (1y)" -> "Price"
- PriceHistoryChart.tsx: restore the change-row PERIOD_LABEL ("past year")
  + scrubbing local + conditional span + 2 comments that a974c82 deleted.

The selector-below-the-chart move from a974c82 was correct and is kept.
Verified via Playwright on /stock/AAPL: heading "Price" (no 1y), change row
shows "past year", selector below the date axis. next build -> 502 routes; tsc clean.

https://claude.ai/code/session_0144kHrCYNaamMPH57b7xdM7
Per user request: "past year" disappeared while dragging the crosshair and
came back on release. The change-row period label was gated by {!scrubbing
&& ...}; remove the gate so it renders unconditionally, and drop the now-
unused `scrubbing` local + update 3 comments.

Semantically safe: headlineAt always measures the change from the window
start (price[i] - price[0]), so the baseline is constant and "past year"
correctly names the window at any scrubbed point. next build -> 502 routes;
tsc clean.

https://claude.ai/code/session_0144kHrCYNaamMPH57b7xdM7
@dackclup dackclup changed the title feat(frontend): app-wide ease-in-out motion curve feat(frontend): motion + price-chart polish — app-wide ease-in-out · sidebar smooth · risk-flag static · price-chart tweaks May 31, 2026
@dackclup dackclup marked this pull request as ready for review May 31, 2026 04:33
@dackclup dackclup merged commit ba218ff into main May 31, 2026
4 checks passed
@dackclup dackclup deleted the claude/optimistic-brown-UUcXA branch May 31, 2026 04:33
dackclup added a commit that referenced this pull request May 31, 2026
…doc drift (#331)

Adds the 20th subagent `financial-engineer` (Tier 3 Specialized, opus, read-only) — the team's first generative quant-design seat, the design counterpart to methodology-scientist's validation seat. Charter Phase 4-7; hands off design -> methodology-scientist (ratify) -> test-engineer (tests) -> quantrank-reviewer (review). New README Flow 8.

Also drains #311-#330 doc drift (PHASE_STATUS.md was 8 PRs behind) + locksteps subagent counts (19->20 agents, 4->5 opus, 7->8 flows, Tier 3 5->6) across all six current-state doc homes.

Doc + agent-infra only — no compute / schema / scoring / valuation / frontend code change. docs-reviewer + phase-coordinator Mode B gates passed (1 stale-opus-list FAIL caught + fixed). CI green: Python lint+test, Frontend build, Vercel preview all success.
dackclup added a commit that referenced this pull request Jun 1, 2026
…ccable document) (#354)

Full regenerate of the impeccable design-context (created in #350) against the
current code. The creative decisions locked in #350 (North Star, palette,
typography, Named Rules, the 4 anti-references) are preserved verbatim; only the
spec's accuracy had drifted, fixed here:

- Elevation: DESIGN.md/sidecar claimed cards rest on shadow-medium and the hero
  on shadow-large. Reality (post-A3 reskin): only shadow-overlay is used anywhere
  (FilterDrawer) -- every card/table/hero is border-only `rounded`. Rewrote the
  Elevation section + sidecar shadow purposes so Subtle/Medium/Large read as
  defined-but-unused; an agent will no longer reach for a resting shadow.
- Components: added ListingChips (#351 country/exchange chips) +
  HeroAttributeTiles (#344 4-box tile grid) to DESIGN.md and the sidecar, plus an
  Icons subsection (lucide named-import / country-flag-icons per-country
  tree-shake discipline) and the signature Score Gauge as the 8th sidecar entry.
- Motion: corrected two sidecar easings -- gauge-sweep cubic-bezier(.22,1,.36,1)
  -> ease-in-out, hover-lift ease-out -> ease-in-out (the app-wide single curve,
  #330).
- Sidecar Card css dropped its stale box-shadow (border-only); Recommendation
  Chip now uses the soft-OKLCH values that actually render after the globals.css
  override (expert-user-explorer-measured) instead of raw emerald hex. Added a
  Colors + Do's note on the soft-override allowlist (the bg-rose-600 gap from
  #352) + the gauge-stroke inline-rgb carve-out to the Tailwind-Class Rule.

Doc-only (root DESIGN.md + .impeccable/design.json + PHASE_STATUS_INFLIGHT.md) --
no compute / schema / scoring / valuation / frontend-code change. JSON validated
(schemaVersion 2, 8 components); the 6 Stitch headers present in order; YAML
frontmatter parses.

https://claude.ai/code/session_012xxKfyR939bZDmbxxqMFZi

Co-authored-by: Claude <noreply@anthropic.com>
dackclup pushed a commit that referenced this pull request Jun 2, 2026
…In-flight entries

- CLAUDE.md §Phase status: new "Recently merged" block (PR #331#373,
  2026-05-31→2026-06-02, 43 PRs covering $impeccable full-frontend pass +
  financial-engineer subagent + PR-B country/exchange chips + Commit A
  MUST-FIX sweep); old #303#330 block demoted to new "Earlier" section;
  "In flight" entries (PR-B + financial-engineer) replaced with "(none)"
- PHASE_STATUS.md: date 2026-05-31 → 2026-06-02; same recently-merged /
  earlier restructure with compact one-liners for all 43 PRs
- AGENTS.md §Phase + version state: "In flight — PR-B" bullet replaced
  with "all PRs through #373 merged" pointer to CLAUDE.md
- PHASE_STATUS_INFLIGHT.md: Commit B entry appended

No compute / schema / scoring / valuation / frontend code change.

https://claude.ai/code/session_01ELWfJoJp5kMje2j4zoUCQh
dackclup added a commit that referenced this pull request Jun 2, 2026
…ntries (#380)

Drains 43 PRs (#331#373) into CLAUDE.md + PHASE_STATUS.md Recently-merged blocks. Old #303#330 block demoted to Earlier. In-flight entries for PR-B and financial-engineer replaced with (none). AGENTS.md In-flight bullet updated. PHASE_STATUS_INFLIGHT.md Commit B entry appended. No compute/schema/frontend change.
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