feat(frontend): motion + price-chart polish — app-wide ease-in-out · sidebar smooth · risk-flag static · price-chart tweaks#330
Merged
Conversation
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
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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
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>
5 tasks
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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-outtiming 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)
tailwind.config.tsfade-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-outapp/globals.css.gauge-sweep(ease-out cubic-bezier) ·.hover-lift(ease-out)ease-in-outcomponents/FilterDrawer.tsxduration-300 ease-outease-in-outcomponents/Sidebar.tsx[transition:…_ease-out]ease-in-outcomponents/PriceHistoryChart.tsxeaseOutCubiceaseInOutCubiclib/useMotion.tsuseCountUprAFeaseOutCubiceaseInOutCubicTwo deliberate carve-outs
shimmerstayslinear infinite— ease-in-out on a seamless background-position loop double-decelerates at every wrap boundary (a visible 1.5s "stall pulse").linearis the only correct choice for a seamless loop.transition-*(no explicitease-*) already compiles tocubic-bezier(0.4,0,0.2,1)≈ ease-in-out — left as-is.chip-pop's overshoot (70% → 1.04) andflag-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-sidematchMediacheck) untouched — every animation still snaps to its end state.Verification
next build→ 502 routes ✅ ·tsc --noEmitclean on edited files ✅ease-in-outon everyanimation:/transition:rule (chip-pop/rise-in/flag-pulse/gauge-sweep .8s/hover-lift .16s/ Sidebar.2s,width .2s) +linearpreserved onshimmer✅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 ONEease-in-outtiming curve").https://claude.ai/code/session_0144kHrCYNaamMPH57b7xdM7
Generated by Claude Code