Skip to content

feat(frontend): add Motion transitions for template chip + sessions - #5252

Merged
ardaerzin merged 3 commits into
big-agentsfrom
fe-refactor/add-motion-transitions-initial-batch
Jul 12, 2026
Merged

feat(frontend): add Motion transitions for template chip + sessions#5252
ardaerzin merged 3 commits into
big-agentsfrom
fe-refactor/add-motion-transitions-initial-batch

Conversation

@ardaerzin

Copy link
Copy Markdown
Contributor

Context

Two spots in the agent experience changed with no motion, or with hand-rolled animation code. On the home composer, switching templates snapped the provenance chip's width and swapped its content instantly. In the playground, session items had no coordinated enter/exit: the chat-mode rail hand-rolled a grid-collapse plus a rAF reveal plus a 220ms setTimeout delete-defer, and the build-mode tag bar just popped.

This is the first batch of moving those onto Motion (the motion package was already a dependency but unused until now).

Changes

Two independent, file-disjoint pieces (one commit each).

Template chip (TemplateStrip/)

  • The chip's width now morphs when you switch templates, via Motion's layout. CSS transition-[width] can't animate an auto width, which is why the old code measured an off-flow ghost with a ResizeObserver and drove an explicit width. All of that machinery is deleted.
  • The content group (initials badge, name, provider logos) crossfades on a switch via AnimatePresence, instead of snapping.
  • AnimatePresence owns the chip's fade/rise on select and clear.

Agent sessions (AgentChatSlice/)

  • New assets/sessionMotion.ts holds one shared spring plus the tag/row variants, so a session's tag (bar) and row (rail) enter and leave with identical physics.
  • Each item collapses its own size in step with its fade (rows their height, tags their width), and the inter-item spacing is an animated margin that collapses to nothing with the item. Removing a session closes the gap as one continuous motion, with no leftover hop when the node unmounts.
  • Deleting a rail row is now immediate; AnimatePresence plays the exit. This replaces the leavingIds / deleteTimersRef / 220ms-timer bookkeeping.

Both surfaces are wrapped in MotionConfig reducedMotion="user", so the transform and layout animations degrade to plain opacity when the OS asks for reduced motion.

Tests / notes

  • pnpm lint-fix clean across the workspace.
  • The modern spring API (visualDuration / bounce) and reducedMotion are type-checked against the installed motion@12.38.0.
  • No automated coverage (animation); verified by eye in the playground.
  • The two features are separate commits touching disjoint files, if you would rather split them into two PRs.

What to QA

  • Home composer: pick a template, then switch between a short-named and a long-named one. The chip width morphs and the badge/name/logos crossfade. No snap.
  • Home composer: clear the chip (the x). It fades and rises out.
  • Playground build mode: add a session (+) and close one (hover the x on a tag). Tabs slide in and out and neighbours close up with no jump at the end of the close.
  • Playground chat mode: add and delete rows in the Sessions rail, and type in Search. Rows collapse and expand as one motion.
  • Turn on OS reduced-motion: all of the above become a plain fade.
  • Regression: rename a session (double-click a tag or row); active-tab styling and scroll-into-view still work.

The chip morph was hand-rolled: an off-flow ghost measured by a ResizeObserver
drove an explicit width onto the visible chip, with CSS transitions for the
width/opacity/fade. It only animated the container — switching templates snapped
the initials, name, and provider logos.

Rebuild it on Motion (already a dep, previously unused):
- the chip's `layout` prop morphs the auto width (a no-bounce spring via the
  visualDuration/bounce API, so the 1.5px seam border never overshoots), deleting
  the ghost, ResizeObserver, useLayoutEffect, and width state;
- an inner AnimatePresence keyed on the template transitions the whole content
  group (badge + name + logos), so the content swaps instead of snapping;
- AnimatePresence in the dock owns the fade/rise on select/clear;
- MotionConfig reducedMotion="user" collapses the transform/layout animations to
  plain opacity for users who ask for reduced motion.
The playground shows the same sessions two ways — compact tags in the build-mode
bar, list rows in the chat-mode rail — and neither entered or left with any motion
(the rail hand-rolled a grid-collapse + rAF + setTimeout delete-defer; the bar just
snapped). Add a coordinated Motion group across both.

- shared assets/sessionMotion.ts holds one SESSION_SPRING plus the tag/row variants,
  so a session's two representations enter and leave with identical physics — the
  "connected" feel between the bar and the rail;
- each item collapses its OWN size in step with its fade (rows their height, tags
  their width) so a neighbour closes the gap as one continuous motion rather than a
  pop-then-reflow two-step, and the inter-item gap is an animated margin that
  collapses to nothing with the item so nothing snaps on unmount;
- deleting a rail row is now immediate — AnimatePresence plays the exit — replacing
  the leavingIds/deleteTimersRef/220ms-timer machinery;
- MotionConfig reducedMotion="user" honours the OS setting on both.
@dosubot dosubot Bot added size:XL This PR changes 500-999 lines, ignoring generated files. enhancement New feature or request Frontend labels Jul 12, 2026
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9e8614cc-b1bc-4ac0-b1c8-9ecd1fdf6e14

📥 Commits

Reviewing files that changed from the base of the PR and between 4770ae1 and 08052c4.

📒 Files selected for processing (6)
  • web/oss/src/components/AgentChatSlice/assets/sessionMotion.ts
  • web/oss/src/components/AgentChatSlice/components/SessionRail.tsx
  • web/oss/src/components/AgentChatSlice/components/SessionTagBar.tsx
  • web/oss/src/components/TemplateStrip/components/TemplateChip.tsx
  • web/oss/src/components/TemplateStrip/components/TemplateChipDock.tsx
  • web/oss/src/components/TemplateStrip/hooks/useTemplateProvenance.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
  • web/oss/src/components/AgentChatSlice/assets/sessionMotion.ts
  • web/oss/src/components/TemplateStrip/hooks/useTemplateProvenance.tsx
  • web/oss/src/components/TemplateStrip/components/TemplateChip.tsx
  • web/oss/src/components/AgentChatSlice/components/SessionTagBar.tsx
  • web/oss/src/components/AgentChatSlice/components/SessionRail.tsx
  • web/oss/src/components/TemplateStrip/components/TemplateChipDock.tsx

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added smoother animated transitions when session tabs, session rail items, and template chips appear, change, or are removed.
    • Animations now respect the user’s reduced-motion preference.
    • Improved template chip transitions with coordinated resizing and content fading.
  • Documentation

    • Clarified documentation for template chip exit behavior.

Walkthrough

Motion-based transitions are added for session rail rows, session tags, and template chips. Shared spring and variant definitions replace timer- and measurement-driven animations, with presence handling, layout morphing, keyed crossfades, and reduced-motion support.

Changes

Motion UI animations

Layer / File(s) Summary
Shared session animation contracts
web/oss/src/components/AgentChatSlice/assets/sessionMotion.ts
Defines shared spring, row, and tag variants that synchronize size changes with spacing collapse and expansion.
Session rail and tag presence animations
web/oss/src/components/AgentChatSlice/components/SessionRail.tsx, web/oss/src/components/AgentChatSlice/components/SessionTagBar.tsx
Replaces row timing and delayed deletion state with AnimatePresence, Motion rows, animated tags, and reduced-motion configuration.
Template chip and dock transitions
web/oss/src/components/TemplateStrip/components/TemplateChip.tsx, web/oss/src/components/TemplateStrip/components/TemplateChipDock.tsx, web/oss/src/components/TemplateStrip/hooks/useTemplateProvenance.tsx
Adds layout width morphing, keyed content crossfades, fade-rise presence animations, and updated transition documentation while removing width measurement and the style prop.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SessionRail
  participant AnimatePresence
  participant SessionRailRow
  SessionRail->>AnimatePresence: Render session rows
  AnimatePresence->>SessionRailRow: Mount or unmount rows
  SessionRailRow->>SessionRailRow: Apply ROW_VARIANTS and SESSION_SPRING
Loading
sequenceDiagram
  participant TemplateChipDock
  participant AnimatePresence
  participant TemplateChip
  TemplateChipDock->>AnimatePresence: Render visible template chip
  AnimatePresence->>TemplateChip: Animate mount or unmount
  TemplateChip->>TemplateChip: Morph layout and crossfade keyed content
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: Motion transitions for template chips and agent sessions.
Description check ✅ Passed The description accurately describes the template-chip and session Motion refactor and matches the changed files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 60.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fe-refactor/add-motion-transitions-initial-batch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@vercel

vercel Bot commented Jul 12, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview, Comment Jul 12, 2026 4:17pm

Request Review

@ardaerzin

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
web/oss/src/components/TemplateStrip/components/TemplateChip.tsx (1)

13-30: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Trim the animation implementation comments.

These new comment blocks substantially exceed the one-short-line rule. Retain only the non-obvious Motion scale-correction rationale.

Proposed cleanup
-// Modern spring API: `visualDuration` is when the bulk of the width morph lands; `bounce: 0`
-// keeps the 1.5px border from overshooting its target width. Timed to the content crossfade.
+// Align the width spring with the content crossfade without overshoot.
 
-/**
- * Provenance chip docked above the composer ("From template: <name>"). No bottom border —
- * it sits flush against the composer's top edge (adjacent siblings, no gap).
- *
- * Two Motion transitions run on a template switch:
- *  - the container's `layout` spring morphs the chip's auto width (CSS `transition-[width]` couldn't);
- *  - an inner `AnimatePresence` (keyed on the template) crossfades the WHOLE content group —
- *    initials badge, name, and provider logos — so they swap rather than snap. `popLayout` pulls
- *    the outgoing group out of flow so the container can measure + morph to the incoming width.
- * `LayoutGroup` coordinates the exit + layout animations; the ✕ lives outside the presence so it
- * stays put while the content swaps. Reduced-motion handling lives in the parent MotionConfig.
- */
+/** Crossfade template content while the chip width morphs. */
 
-// border-radius via style so Motion scale-corrects it during the width morph (Tailwind
-// classes aren't corrected). `relative` gives popLayout a non-static positioning parent.
-// The tint composites over the composer base so the bg stays opaque
-// (--ag-strip-selected-bg is 6%-alpha in dark) and the overlap hides its border.
+// Inline radius lets Motion scale-correct the layout transform.

As per coding guidelines, “Keep in-code comments to one short line maximum unless a genuinely surprising constraint requires a brief exception.”

Also applies to: 44-47

Source: Coding guidelines

web/oss/src/components/TemplateStrip/components/TemplateChipDock.tsx (1)

17-24: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Condense the new dock documentation.

This repeats implementation mechanics over eight lines; keep a single concise description.

Proposed cleanup
-/**
- * Docks the provenance chip above the composer. AnimatePresence fades + rises the chip as it
- * mounts/unmounts; the chip's own `layout` morphs its width when the template switches. During
- * the exit the caller keeps passing the last template, so it fades out with its real content.
- *
- * `MotionConfig reducedMotion="user"` respects the OS setting: transform + layout animations
- * (the rise and the width morph) collapse to instant, leaving only the opacity crossfades.
- */
+/** Animates chip presence while TemplateChip handles template width changes. */

As per coding guidelines, “Keep in-code comments to one short line maximum unless a genuinely surprising constraint requires a brief exception.”

Source: Coding guidelines

web/oss/src/components/TemplateStrip/hooks/useTemplateProvenance.tsx (1)

108-111: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Attribute the width morph to TemplateChip.

TemplateChipDock owns presence fade/rise only; TemplateChip owns layout and WIDTH_SPRING. Make the comment both accurate and concise.

Proposed cleanup
-// During the exit `selectedTemplate` is already null, so we show the retained last template
-// (falling back to the registry's first only for the very first, never-picked render) — the
-// chip fades out with its real content. TemplateChipDock owns the AnimatePresence fade/rise
-// and the width-morph; passing `visible` drives them.
+// Retain the last template for exit; TemplateChipDock handles presence and TemplateChip width.

As per coding guidelines, “Keep in-code comments to one short line maximum unless a genuinely surprising constraint requires a brief exception.”

Source: Coding guidelines

web/oss/src/components/AgentChatSlice/components/SessionRail.tsx (1)

200-225: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Keep AnimatePresence mounted across the empty states
Mounting it only in the non-empty branch skips the row exit animation when the last session is deleted or the search filters everything out. Move the empty/mismatch rendering outside the presence block so the final row can animate out.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7690b53b-08ae-4744-a011-578cd7412de2

📥 Commits

Reviewing files that changed from the base of the PR and between 910c20c and 4770ae1.

📒 Files selected for processing (6)
  • web/oss/src/components/AgentChatSlice/assets/sessionMotion.ts
  • web/oss/src/components/AgentChatSlice/components/SessionRail.tsx
  • web/oss/src/components/AgentChatSlice/components/SessionTagBar.tsx
  • web/oss/src/components/TemplateStrip/components/TemplateChip.tsx
  • web/oss/src/components/TemplateStrip/components/TemplateChipDock.tsx
  • web/oss/src/components/TemplateStrip/hooks/useTemplateProvenance.tsx

- SessionRail: keep AnimatePresence always mounted (render the empty/no-match
  states as siblings) so the last row still plays its exit when the session list
  is emptied by a delete or filtered to nothing.
- Trim the new animation comments to the repo's one-line rule and correct the
  width-morph attribution (TemplateChip owns it, not TemplateChipDock).
@ardaerzin

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@ardaerzin
ardaerzin merged commit 729e945 into big-agents Jul 12, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request Frontend size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant