Skip to content

feat(sandbox): the motion lab previews ProgressBar's fill as width against scaleX - #8606

Merged
cixzhang merged 15 commits into
mainfrom
sandbox/motion-lab-progress-fill-scalex
Oct 27, 2026
Merged

cixzhang merged 15 commits into
mainfrom
sandbox/motion-lab-progress-fill-scalex

Conversation

@cixzhang

@cixzhang cixzhang commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #8617 (the motion lab fits a phone screen), merged in so this card's phone evidence shows the fixed layout. Review only this PR's own change: the ProgressBar fill card in LabDemos.tsx, MotionLab.module.css and previews/page.tsx. It merges after #8617.

The motion lab's live previews page gets a ProgressBar fill card comparing width against transform: scaleX for the determinate fill.

  • Today: the real ProgressBar, which transitions width on every data change. That re-lays out the bar every frame of every tick, so a fast upload behaves like a layout loop.
  • Proposed: a sandbox copy of the same track and fill (8 px, muted track, accent fill, full radius) moving the fill with transform: scaleX on the same duration token and curve, so only the technique differs.
  • The hint names the cost of scaleX: the rounded ends squash at small values, so it needs an exception or a different structure before Core can adopt it.
  • Sandbox only. Core's ProgressBar is unchanged, there's no package change and no changeset.

Evidence

Real Chrome (headless, Linux), rendering this PR's CI sandbox build at ca36245 (which includes #8617's phone layout). The values cycle 12 → 58 → 34 → 86 %.

Desktop, 1280 px Phone, 390 px
Reduce Motion off desktop phone
Reduce Motion on desktop, reduce motion phone, reduce motion

…ainst scaleX

The live previews page gets a ProgressBar fill card: the real ProgressBar,
which transitions width on every data change, beside a sandbox copy of its
track and fill that moves the same fill with transform: scaleX on the same
token and curve, so only the technique differs. A fill slider tunes the
shared duration. The hint names the cost of scaleX (the rounded ends
squash at small values). Core's ProgressBar is unchanged.

Co-authored-by: Ernest <ernesttien@meta.com>
@vercel

vercel Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
astryx Ready Ready Preview Oct 27, 2026 3:29am UTC

Request Review

@astracat-bot

astracat-bot Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Oct 27, 2026, 3:53 AM UTC

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 26, 2026
@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

Previews ready: Storybook and Sandbox were built with this PR's docsite. CI evidence will be added when available.

View Storybook for this PR · View Sandbox for this PR

cixzhang and others added 3 commits October 26, 2026 16:19
…390 px screen

The two-column card grid it sat in has a 420 px column minimum, which ran
off a phone screen.

Co-authored-by: Ernest <ernesttien@meta.com>
At 390 px the lab kept its 228 px page panel beside the content, leaving
every card a 162 px column, and its widest card grids (420, 460 and 380 px
column minimums) ran off the screen. Below 720 px the pages now fold into a
collapsible list above the content, and those grids cap at two columns,
which lets each column shrink to the screen. At desktop widths the layout
is unchanged.

Co-authored-by: Ernest <ernesttien@meta.com>
@cixzhang
cixzhang changed the base branch from main to sandbox/motion-lab-phone-layout October 26, 2026 23:28
@cixzhang
cixzhang changed the base branch from sandbox/motion-lab-phone-layout to main October 26, 2026 23:29
cixzhang and others added 4 commits October 26, 2026 16:36
…eed controls wrap

The collapsible page list opened by default, pushing the lab below a long
list, and the speed row ran past a 390 px screen.

Co-authored-by: Ernest <ernesttien@meta.com>
…the card drops a slider that tuned nothing

The lab's sliders tune its semantic tokens, and ProgressBar reads the
primitive duration, so the fill slider read 0 ms and moved nothing. The
copy also carries ProgressBar's theming-target classes, so the theme paints
its track as it paints the real bar's.

Co-authored-by: Ernest <ernesttien@meta.com>
…e theme's track colour reaches it

The copy's paint sat in the unlayered lab stylesheet and outranked the
theme's rule for the ProgressBar track, so its track stayed lighter than
the real bar's.

Co-authored-by: Ernest <ernesttien@meta.com>
…g target too

The theme sets the track colour from ProgressBar's root target, so the copy
now sits in a root with that target (themeProps, public from core/utils),
and its track paints like the real bar's.

Co-authored-by: Ernest <ernesttien@meta.com>
cixzhang and others added 2 commits October 26, 2026 17:21
…the springs plots and a code line fit their cards

The shell outlives a page change, so the folded list stayed open after a
pick and the chosen page started below the screen; it is now keyed by
page. The springs plots draw a fixed 380 px SVG, which a 342 px phone card
clipped; they now shrink with the card (their own size otherwise). A long
inline code line on the JS mirror page wraps instead of running past its
card.

Co-authored-by: Ernest <ernesttien@meta.com>
cixzhang added a commit to cixzhang/astryx that referenced this pull request Oct 27, 2026
cixzhang and others added 2 commits October 26, 2026 17:57
A two-column card shrinks to the screen on a phone now, and a long code
reference (BottomSheet/BottomSheetPanel.tsx:172) had no break point, so the
card clipped it. It wraps instead.

Co-authored-by: Ernest <ernesttien@meta.com>

@astracat-bot astracat-bot 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.

Requesting changes: the ProgressBar fill card makes the width-against-scaleX trade-off easy to watch, and in the neutral and Stone themes both bars match in size, colour and timing, but the scaleX copy stops matching the real bar in three states.

  • Under the Y2K theme --radius-full is 0px, so the real bar is square while the copy keeps its hardcoded 9999px pill; border-radius: var(--radius-full) on .fillTrack fixes it.
  • The sandbox build turns :dir(rtl) .fillScale into a :lang() list that never matches dir="rtl", so in RTL the copy fills from the left; keying the rule on [dir='rtl'] fixes it.
  • With forced colours the copy's track and fill both become Canvas and vanish, so .fillScale needs the 1px CanvasText outline Core's fill already has.

[Automated review]

.fillTrack {
position: relative;
height: 8px;
border-radius: 9999px;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Core's track and fill read --radius-full, which the Y2K theme sets to 0px, so there the real bar is square while this copy stays a pill. border-radius: var(--radius-full); keeps the pair differing only in technique.

Comment on lines +768 to +774
.fillScale {
position: absolute;
inset: 0;
border-radius: inherit;
transform-origin: left center;
transition: transform var(--duration-medium) var(--ease-standard);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Core's fill draws a 1px CanvasText outline under @media (forced-colors: active); without one, this fill and its track are both Canvas with forced colours and the Proposed pane shows no progress. Giving .fillScale the same outline keeps both panes visible.

}
}

:dir(rtl) .fillScale {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The sandbox build emits this as :is(:lang(ae), :lang(ar), …) ._fillScale_…, which matches only an RTL lang, so under dir="rtl" on this English page the copy still fills from the left. [dir='rtl'] .fillScale (Core uses :is([dir="rtl"] *)) mirrors it as intended.

…der dir=rtl and keeps its shape in forced colours

The copy hardcoded a pill radius, so in a theme whose --radius-full is 0
it was a pill beside a square real bar; it reads the token now. Its RTL
origin was a :dir(rtl) selector the build turns into a :lang() list that
never matches dir="rtl"; it is [dir='rtl'] now. And with forced colours
both the copy's track and fill were Canvas, so it showed no progress; it
draws Core's 1px CanvasText outline.

Co-authored-by: Ernest <ernesttien@meta.com>

@astracat-bot astracat-bot 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.

Approving: the ProgressBar fill card now matches the real bar in every sandbox theme, in RTL and with forced colours, so the two panes differ only in technique, and the three issues from the previous review are fixed. One optional touch: the copy's “Uploading” label renders at weight 400 while Core's is 500, so <Text weight="medium"> would make the panes identical. As planned, land #8617 first so this pull request carries only the card.

[Automated review]

<div {...themeProps('progress-bar', {variant: 'accent'})}>
<VStack gap={1}>
<HStack gap={2} hAlign="between">
<Text>Uploading</Text>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Optional: this label computes font-weight: 400, while Core's ProgressBar label computes 500 (--font-weight-medium), so the two panes differ in something the technique doesn't cause. <Text weight="medium">Uploading</Text> matches it.

@astracat-bot astracat-bot 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.

Approving: the ProgressBar fill card plays Core's width-animated fill beside a scaleX copy that matches it in paint, radius and timing across the sandbox themes, in RTL and with forced colours, so the two panes differ only in technique, and with #8617 merged the diff is just the card. One optional touch: the copy's "Uploading" label renders at weight 400 while Core's is 500, so <Text weight="medium"> would make the panes identical.

[Automated review]

@cixzhang
cixzhang merged commit eb3d173 into main Oct 27, 2026
63 checks passed
@github-actions
github-actions Bot deleted the sandbox/motion-lab-progress-fill-scalex branch October 27, 2026 06:22

This branch was successfully deployed

1 active deployment
Preview — c76023ab Deployed Oct 27, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant