Skip to content

release: version packages - #5775

Open
github-actions[bot] wants to merge 1 commit into
mainfrom
changeset-release/main
Open

release: version packages#5775
github-actions[bot] wants to merge 1 commit into
mainfrom
changeset-release/main

Conversation

@github-actions

@github-actions github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

@marigold/components@18.2.0

Minor Changes

  • 4b9631c: feat(DST-889): mark links that open in a new window

    A <Link> that opens a new window or tab now shows an external-link icon after its label plus a hidden, localized "opens in a new window" warning (WCAG G201). Targets that stay in the current window (_self, _top, _parent, in any casing) are untouched, and so are links that open nothing: disabled ones, ones with no href, and download ones, where the browser saves the file and ignores target.

    target="_blank" also defaults rel to noopener, which your own rel still overrides. A named window gets no default rel, because noopener makes the browser ignore the window name and open a new tab on every click instead of reusing the window. The cost is that a named window keeps a live window.opener handle on your page, which browsers still allow for named targets even though they severed it for _blank, so don't point one at an origin you don't control.

    This is automatic and retroactive. Every existing target="_blank" link gains the icon and a longer accessible name, so tests asserting an exact name need updating: getByRole('link', { name: 'Terms' }) becomes getByRole('link', { name: 'Terms opens in a new window' }).

    An aria-label replaces a link's content in its accessible name, so the warning is appended to it rather than dropped. With aria-labelledby it is referenced by id instead. That also fixes the master/admin access label, which an aria-label used to swallow.

    There is no external prop and no opt-out. Deriving from target keeps the API unchanged and makes the indicator reliable, since an opt-in prop gets forgotten and a missing icon reads as "this one stays here". If a link should not carry the icon, do not force the new window.

    Theme: master and admin render slightly differently. They coloured every descendant svg with the access token, which would have painted the new-tab glyph too, so AccessIcon now carries an access-icon class for the theme to select instead. Menu's master and admin items moved to that same selector. Nothing renders differently today, because an access item's only glyph is the access one, but a consumer icon dropped into such an item no longer picks up the access colour. They also placed their icon with inline-flex items-center gap-1, which puts a trailing icon beside a wrapped label instead of after its last word. Both icons are now inline and sized in em, so they follow size="small" instead of staying at 16px.

  • 0c56a11: feat(DST-1391): add Stepper, a progress indicator for multi-step tasks.

    <Stepper> shows where a user stands in a checkout, an onboarding flow, or a multi-page form, replacing the one-off "Step 1 of 4" widgets that several product flows had each built for themselves. It renders a <nav> landmark around an ordered list, announces each step's label, position, and state, and never relies on colour alone to convey which step is which.

    State is entirely consumer-owned. completedKeys is a set rather than a high-water mark, so non-contiguous completion coming from a server is expressible, and the component never infers that a step is finished: only your code knows whether validation passed. selectableKeys replaces the built-in "completed, errored, or current" rule when a backend decides what is reachable, and disabledKeys always wins over both. Errored steps stay clickable by default, so a user who is told a step failed has a way back to it, unless selectableKeys leaves them out.

    Steps with an href render as real links and route through RouterProvider; steps without one render as buttons. Steps that are not reachable render as plain text rather than as disabled controls, since an unreachable step is not a disabled widget. hideLabels drops labels visually for flows with too many steps to label, keeping them for screen readers and adding a visible "Step 3 of 5" counter so sighted users still know how far along they are.

Patch Changes

  • 8ba1cc4: fix(DST-1684): ignore virtualized ListBox row measurements taken before the list has a width

    ListLayout sizes each virtualized row from the virtualizer's own width, which is 0 on the
    first layout pass and non-finite in browser-mode test runs. Either way the row wrapper collapses,
    and since wrap-anywhere removed the min-width: auto floor on options (DSTSUP-269), a row
    measured in that state wraps character by character and reports a height in the hundreds of pixels.
    The resulting scroll-into-view puts the list behind React Aria's 300ms pointer-events: none
    cooldown, which swallows a click on an option.

    The observable failure was confined to browser-mode test runs, where the width never becomes
    finite. In a real browser the first-pass window never reaches the DOM — ScrollView settles its
    width before commit — so no change in behaviour is expected for Select, ComboBox,
    Autocomplete or TagField. ListBoxLayout now rejects measurements taken in that state, closing
    both paths.

  • 7ef7733: Input no longer clones its icon and action children to inject positioning
    classes. It renders the positioned box itself and lets the child fill it, so a
    Fragment or a non-element child is placed like anything else, and a className
    you set on the icon or action is left alone instead of being merged. Rendered
    geometry is unchanged; the icon and action each gain a wrapping <span>.

  • Updated dependencies [0c56a11]

    • @marigold/system@18.2.0

@marigold/system@18.2.0

Minor Changes

  • 0c56a11: feat(DST-1391): add Stepper, a progress indicator for multi-step tasks.

    <Stepper> shows where a user stands in a checkout, an onboarding flow, or a multi-page form, replacing the one-off "Step 1 of 4" widgets that several product flows had each built for themselves. It renders a <nav> landmark around an ordered list, announces each step's label, position, and state, and never relies on colour alone to convey which step is which.

    State is entirely consumer-owned. completedKeys is a set rather than a high-water mark, so non-contiguous completion coming from a server is expressible, and the component never infers that a step is finished: only your code knows whether validation passed. selectableKeys replaces the built-in "completed, errored, or current" rule when a backend decides what is reachable, and disabledKeys always wins over both. Errored steps stay clickable by default, so a user who is told a step failed has a way back to it, unless selectableKeys leaves them out.

    Steps with an href render as real links and route through RouterProvider; steps without one render as buttons. Steps that are not reachable render as plain text rather than as disabled controls, since an unreachable step is not a disabled widget. hideLabels drops labels visually for flows with too many steps to label, keeping them for screen readers and adding a visible "Step 3 of 5" counter so sighted users still know how far along they are.

@marigold/theme-rui@6.2.0

Minor Changes

  • 741774f: fix(DST-1640): give the Sidebar.Rail an overflow affordance and a footer seam

    When a rail's top-level list outgrew the viewport it scrolled, but nothing except the scrollbar said so, and the pinned footer had no seam against the scrolling list, so the two ran together and the scrollbar ended against a hard footer edge. Two scroll-state-aware cues now sit on top of the scrollbar, and a rail that fits still shows no extra chrome:

    • The list fades its overflowing edges via a new ui-scroll-mask-y utility, the block-axis twin of ui-scroll-mask-x (already behind Tabs and SegmentedControl). scroll-padding keeps a focused tile clear of the fade so its focus ring is never half-erased.
    • The footer takes the ui-scroll-seam-* top hairline the single-column sidebar's footer already had, fading out as the list bottoms out. Being a following sibling of the list is not enough to see its named scroll timeline, so the rail column hoists the name with ui-scroll-seam-scope. That scope belongs on the column and no higher: the section panel's nav declares the same name, and two declarations in one scope are ambiguous, which kills the animation.

    ui-scroll-mask-y differs from the horizontal version in two ways. Its fade defaults narrower (1.25rem), because a row is shorter than a horizontal scroller is wide and 2.5rem would swallow a whole one. And it keeps the scrollbar, where ui-scroll-mask-x hides it: a horizontal scrollbar under a row of tabs is unconventional chrome a fade can replace outright, but down the block axis the scrollbar is the conventional affordance and the one a pointer user looks for, so the fade is additive. Pair it with ui-scrollbar to theme the scrollbar as usual.

    One caveat, since a mask applies to the whole element: the fade also thins the ends of the scrollbar track. The animation ranges keep the thumb clear of it where it matters (the top fade is 0 exactly when the thumb is at the top), and the narrow default keeps the rest subtle, but it is why the utility wants no border of its own on the masked element.

    Progressive enhancement follows the horizontal version: without scroll-driven animation support (Firefox as of 153) there is no fade, just the scrollbar. The seam now degrades the same way. Its @supports not branch pins a hairline on unconditionally, which suits the single-column sidebar, whose nav usually overflows, but not a rail of three to seven sections, which usually fits. Pinning it on there would put a permanent divider under a rail that never scrolls, the one thing a scroll-state-aware affordance exists to avoid. So ui-scroll-seam-footer gained a --seam-fallback-color hook, and the rail's footer sets it to transparent. The cost is that the footer-meets-scrollbar seam stays unfixed in that engine, exactly as it is today. Existing consumers are untouched: leave the property unset and the fallback hairline behaves as before.

    The rail's guidance is unchanged. It is still meant for a small, stable set of sections, and this only makes sure it never looks broken past that, on a short viewport, at high zoom, or with large text.

  • 0c56a11: feat(DST-1391): add Stepper, a progress indicator for multi-step tasks.

    <Stepper> shows where a user stands in a checkout, an onboarding flow, or a multi-page form, replacing the one-off "Step 1 of 4" widgets that several product flows had each built for themselves. It renders a <nav> landmark around an ordered list, announces each step's label, position, and state, and never relies on colour alone to convey which step is which.

    State is entirely consumer-owned. completedKeys is a set rather than a high-water mark, so non-contiguous completion coming from a server is expressible, and the component never infers that a step is finished: only your code knows whether validation passed. selectableKeys replaces the built-in "completed, errored, or current" rule when a backend decides what is reachable, and disabledKeys always wins over both. Errored steps stay clickable by default, so a user who is told a step failed has a way back to it, unless selectableKeys leaves them out.

    Steps with an href render as real links and route through RouterProvider; steps without one render as buttons. Steps that are not reachable render as plain text rather than as disabled controls, since an unreachable step is not a disabled widget. hideLabels drops labels visually for flows with too many steps to label, keeping them for screen readers and adding a visible "Step 3 of 5" counter so sighted users still know how far along they are.

Patch Changes

  • 4b9631c: feat(DST-889): mark links that open in a new window

    A <Link> that opens a new window or tab now shows an external-link icon after its label plus a hidden, localized "opens in a new window" warning (WCAG G201). Targets that stay in the current window (_self, _top, _parent, in any casing) are untouched, and so are links that open nothing: disabled ones, ones with no href, and download ones, where the browser saves the file and ignores target.

    target="_blank" also defaults rel to noopener, which your own rel still overrides. A named window gets no default rel, because noopener makes the browser ignore the window name and open a new tab on every click instead of reusing the window. The cost is that a named window keeps a live window.opener handle on your page, which browsers still allow for named targets even though they severed it for _blank, so don't point one at an origin you don't control.

    This is automatic and retroactive. Every existing target="_blank" link gains the icon and a longer accessible name, so tests asserting an exact name need updating: getByRole('link', { name: 'Terms' }) becomes getByRole('link', { name: 'Terms opens in a new window' }).

    An aria-label replaces a link's content in its accessible name, so the warning is appended to it rather than dropped. With aria-labelledby it is referenced by id instead. That also fixes the master/admin access label, which an aria-label used to swallow.

    There is no external prop and no opt-out. Deriving from target keeps the API unchanged and makes the indicator reliable, since an opt-in prop gets forgotten and a missing icon reads as "this one stays here". If a link should not carry the icon, do not force the new window.

    Theme: master and admin render slightly differently. They coloured every descendant svg with the access token, which would have painted the new-tab glyph too, so AccessIcon now carries an access-icon class for the theme to select instead. Menu's master and admin items moved to that same selector. Nothing renders differently today, because an access item's only glyph is the access one, but a consumer icon dropped into such an item no longer picks up the access colour. They also placed their icon with inline-flex items-center gap-1, which puts a trailing icon beside a wrapped label instead of after its last word. Both icons are now inline and sized in em, so they follow size="small" instead of staying at 16px.

  • Updated dependencies [4b9631c]

  • Updated dependencies [8ba1cc4]

  • Updated dependencies [7ef7733]

  • Updated dependencies [0c56a11]

    • @marigold/components@18.2.0
    • @marigold/system@18.2.0

@marigold/cli@3.0.0

Patch Changes

  • 0c56a11: feat(DST-1391): add Stepper, a progress indicator for multi-step tasks.

    <Stepper> shows where a user stands in a checkout, an onboarding flow, or a multi-page form, replacing the one-off "Step 1 of 4" widgets that several product flows had each built for themselves. It renders a <nav> landmark around an ordered list, announces each step's label, position, and state, and never relies on colour alone to convey which step is which.

    State is entirely consumer-owned. completedKeys is a set rather than a high-water mark, so non-contiguous completion coming from a server is expressible, and the component never infers that a step is finished: only your code knows whether validation passed. selectableKeys replaces the built-in "completed, errored, or current" rule when a backend decides what is reachable, and disabledKeys always wins over both. Errored steps stay clickable by default, so a user who is told a step failed has a way back to it, unless selectableKeys leaves them out.

    Steps with an href render as real links and route through RouterProvider; steps without one render as buttons. Steps that are not reachable render as plain text rather than as disabled controls, since an unreachable step is not a disabled widget. hideLabels drops labels visually for flows with too many steps to label, keeping them for screen readers and adding a visible "Step 3 of 5" counter so sighted users still know how far along they are.

  • Updated dependencies [741774f]

  • Updated dependencies [4b9631c]

  • Updated dependencies [8ba1cc4]

  • Updated dependencies [7ef7733]

  • Updated dependencies [0c56a11]

    • @marigold/theme-rui@6.2.0
    • @marigold/components@18.2.0

@marigold/icons@2.0.2

Patch Changes

  • Updated dependencies [0c56a11]
    • @marigold/system@18.2.0

@marigold/docs@18.2.0

Patch Changes

  • af745a8: fix(DST-1689): make the Table cell alignment demo render the same on server and client

    table-cell-alignment.demo.tsx built its nights and guests columns with
    Math.floor(Math.random() * n) at render time. ComponentDemo is a client
    component, so the demo is server-rendered and then hydrated, which ran the
    generator twice and produced two unrelated datasets. React reported a hydration
    mismatch on the first Nights cell and regenerated the whole table on the client,
    so all eight generated cells visibly swapped values after the first paint. Three
    consecutive requests to the page returned three different tables.

    The two columns now come from a fixed four-entry fixture, merged into the venue
    data by index, and the derivation moves to module scope because it no longer
    depends on anything per render. The guest counts span one, two and three digits
    and stay under each venue's capacity, so the demo makes its own point about right
    alignment better than the random values did.

    table-appearance.demo.tsx also rendered <Table {...props}>, and AppearanceDemo
    passes only variant and size, so that grid had no accessible name. It now
    carries aria-label="Venues", matching how listview-appearance.demo.tsx labels
    the same shape. That was the whole source of the seven react-aria warnings the
    page logged, which fire once per render pass.

    Further console findings on neighbouring pages, same class of defect, fixed here
    rather than left behind:

    selectlist-selectable-cards.demo.tsx formatted capacity and price with
    Number.prototype.toLocaleString() and no locale argument, so it read the JS
    runtime default: en-US under Node, the viewer's own locale in the browser. That
    rendered $1,000 on the server and $1.000 on a de-DE client, a second
    hydration mismatch. ComponentDemo already pins <I18nProvider locale="en-US">
    to prevent exactly this, but toLocaleString bypasses the provider entirely.
    Both values now use NumericFormat, which reads the pinned locale through
    useNumberFormatter. The rendered text is unchanged ($1,000, no cents, via
    maximumFractionDigits), but the DOM gains a <span suppressHydrationWarning>
    per value. NumericFormat defaults to tabular, which suits the price and not
    the middle of a sentence, so the capacity passes tabular={false} and keeps the
    proportional figures the prose had before.

    The two closest copies of that code are fixed with it. card-grid.demo.tsx
    repeated both lines verbatim. card-appearance.demo.tsx rendered its price range
    as two bare toLocaleString() calls on four- and five-digit values, so the
    grouping separator always fired there. The range now goes through a single
    NumericFormat with a tuple value, which formats it through Intl.formatRange
    and reproduces the same en dash and spacing the hardcoded &ndash; produced.

    menu-dialog.demo.tsx wrapped each controlled dialog in <Dialog.Trigger> with
    the <Dialog> as its only child. Dialog.Trigger wraps its children in a
    PressResponder to turn a child into the trigger, and a Dialog never registers
    a press, so react-aria warned four times (two dialogs, doubled by StrictMode's
    effect). These dialogs are opened by the menu items, so they need no trigger at
    all: open and onOpenChange move onto Dialog itself, which already renders
    its own Modal. That is what ConfirmationDialog and useConfirmation do
    internally. Verified unchanged: both dialogs open from the menu, slot="close"
    still closes them, role="alertdialog" and the aria-labelledby title wiring
    survive, and Escape still dismisses.

  • 4b9631c: feat(DST-889): mark links that open in a new window

    A <Link> that opens a new window or tab now shows an external-link icon after its label plus a hidden, localized "opens in a new window" warning (WCAG G201). Targets that stay in the current window (_self, _top, _parent, in any casing) are untouched, and so are links that open nothing: disabled ones, ones with no href, and download ones, where the browser saves the file and ignores target.

    target="_blank" also defaults rel to noopener, which your own rel still overrides. A named window gets no default rel, because noopener makes the browser ignore the window name and open a new tab on every click instead of reusing the window. The cost is that a named window keeps a live window.opener handle on your page, which browsers still allow for named targets even though they severed it for _blank, so don't point one at an origin you don't control.

    This is automatic and retroactive. Every existing target="_blank" link gains the icon and a longer accessible name, so tests asserting an exact name need updating: getByRole('link', { name: 'Terms' }) becomes getByRole('link', { name: 'Terms opens in a new window' }).

    An aria-label replaces a link's content in its accessible name, so the warning is appended to it rather than dropped. With aria-labelledby it is referenced by id instead. That also fixes the master/admin access label, which an aria-label used to swallow.

    There is no external prop and no opt-out. Deriving from target keeps the API unchanged and makes the indicator reliable, since an opt-in prop gets forgotten and a missing icon reads as "this one stays here". If a link should not carry the icon, do not force the new window.

    Theme: master and admin render slightly differently. They coloured every descendant svg with the access token, which would have painted the new-tab glyph too, so AccessIcon now carries an access-icon class for the theme to select instead. Menu's master and admin items moved to that same selector. Nothing renders differently today, because an access item's only glyph is the access one, but a consumer icon dropped into such an item no longer picks up the access colour. They also placed their icon with inline-flex items-center gap-1, which puts a trailing icon beside a wrapped label instead of after its last word. Both icons are now inline and sized in em, so they follow size="small" instead of staying at 16px.

  • Updated dependencies [741774f]

  • Updated dependencies [4b9631c]

  • Updated dependencies [8ba1cc4]

  • Updated dependencies [7ef7733]

  • Updated dependencies [0c56a11]

    • @marigold/theme-rui@6.2.0
    • @marigold/components@18.2.0
    • @marigold/system@18.2.0
    • @marigold/icons@2.0.2

@vercel

vercel Bot commented Aug 31, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated
marigold-docs Ready Ready Preview Sep 2, 2026 1:00pm UTC
marigold-storybook Ready Ready Preview Sep 2, 2026 1:00pm UTC
1 Skipped Deployment
Project Deployment Actions Updated
marigold-production Ignored Ignored Sep 2, 2026 1:00pm UTC

Request Review

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.

0 participants