Skip to content

feat(registry)!: adopt the new Remix APIs in the HeroUI preset - #343

Draft
leoafarias wants to merge 24 commits into
stack/follow-ups-integrationfrom
feat/registry-heroui-adopt-remix-apis
Draft

leoafarias wants to merge 24 commits into
stack/follow-ups-integrationfrom
feat/registry-heroui-adopt-remix-apis

Conversation

@leoafarias

@leoafarias leoafarias commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Draft, stacked on #339. Do not merge until remix 1.0.0-beta.14 and naked_ui 1.3.0 are on pub.dev. The preset uses APIs that exist only in those releases, and the registry remix: floor moves in the beta.14 release PR, not here.

The HeroUI preset adopts the Remix and Naked UI APIs from the follow-up PRs, so it stops approximating what they now express.

  • Radio and switch labels (feat(remix)!: add label to RemixRadio and RemixSwitch #332): both pass label. The label is inside the tap target, so hover, press, focus, and semantics cover one target. HeroUiControlRow becomes HeroUiDescribedControl, which lays out only the description beneath the label.
  • Focus rings (feat(remix): add containerEffects to focusable parts #331): the ring is an outline effect (containerEffects, triggerEffects) on tabs, toggles, toggle group items, select and menu rows, the menu trigger, and the accordion and disclosure triggers.
    • Focus no longer changes layout.
    • Toggle group items draw the ring inside, as upstream ring-inset does. The surface accordion's trigger also draws it inside, as an approximation.
  • Selected tab shadow: it is containerEffects(heroUiSurfaceEffects()), so it follows --surface-shadow (none in dark) and combines with the focus ring.
  • Select width (feat(remix): expose the anchor width to select and menu overlays #326): the select content takes remixAnchorWidth() as its minWidth.
  • Overlay triggers (feat(remix)!: let a real button trigger RemixMenu #337, fix(naked_ui): keep focus on the caller's control in a popover opened without tap #338): a HeroUiButton is the dropdown trigger through RemixMenuTrigger.control, and a popover button shares one FocusNode with the popover. The gallery fixture uses both.
  • Toast: the action stacks under the message at 768px and below (actionPlacement: below, inclusive like max-width: 768px). Below 640px it adds mt-2 through onNot(Breakpoint.minWidth(640)), the exact complement of sm:mt-0.
  • Docs: the worksheets, a dated adoption revision in ADR 0002, and skills/using-remix/references/heroui.md record what this closes.

Not done:

  • HeroUI's .animate(...) transitions still ignore reduced motion, because Mix 2.3.1's .animate does not read it. This is tracked as a Mix follow-up.
  • From 640 to 768px the toast's action sits 6px below the message, where upstream has 0. This is recorded in toast.yaml.

Restacked onto the refreshed integration hub #339 (d5990f4d) on main ca9331be. Remains DRAFT and release-blocked until naked_ui 1.3.0 and Remix 1.0.0-beta.14 are available on pub.dev and their runtime/registry floor updates are approved. Registry dependency floors are unchanged.

The pushed installed-gallery wiring tests are preserved. The held HeroUI ADR 0002 rewrite has not been applied.

leoafarias and others added 24 commits October 29, 2026 21:44
HeroUiRadio and HeroUiSwitch take the label RemixRadio and RemixSwitch now
draw inside their tap target, so pointing at the label hovers, presses, and
toggles the control and one semantics node carries its name. The group
composition drops its label row; HeroUiControlRow becomes
HeroUiDescribedControl, which lays out only the description beneath the
label.
Tabs, toggles, toggle group items, select and menu rows, the menu trigger, and
the accordion and disclosure triggers paint HeroUI's focus ring as an outline
effect instead of an always-present transparent inside border. The ring takes
no layout space, so focus no longer resizes a part or needs padding reduced by
the ring width, and it is the measured gap-then-ring outside the part.
Toggle group items and the surface accordion, whose parent clips, draw
ring-inset inside the part. heroUiRingBorder and heroUiInsideRing are gone.
The select content takes remixAnchorWidth() as its minimum width, the port of
min-w-(--trigger-width), so the popover is at least as wide as the trigger
instead of as wide as its widest item.
RemixMenuTrigger.control makes a real HeroUiButton the menu trigger, so the
dropdown no longer needs a label standing in for it. The tests pin one tab
stop, focus returning to the button, one expandable semantics node, and a
disabled button not opening the menu.
… 768px

The toast sets actionPlacement to below under maxWidth(768), inclusive like
max-width: 768px, and adds mt-2 below 640px by restating the action style
under maxWidth(639), because an action replaces rather than merges.
… button

A HeroUiButton that opens a popover with openOnTap: false passes the same
FocusNode as the popover's triggerFocusNode and its own focusNode, so the
button is the only tab stop and takes focus back on close. The recipe doc, the
worksheet, and the popover test show it.
…gers

The gallery's dropdown trigger is an AcmeButton through
RemixMenuTrigger.control, and its popover button shares a focus node with the
popover. The fixture tests pin that the menu opens, a row reports its action,
and focus returns to each button.
…kill

ADR 0002's verdict rows for focus rings, the select width, radio and switch
labels, and the dropdown trigger now say they shipped and are adopted. The
HeroUI reference covers labeled controls, the button triggers and shared
popover focus node, the select width, the toast action placement, and that
Mix's .animate does not yet honor reduced motion.
A labeled radio or switch group sits under IntrinsicWidth in an alert dialog's
content, and Remix's labeled-control helper used a LayoutBuilder that cannot
report intrinsic sizes. The two tests fail until the Remix fix for that reaches
this branch.
…fects

The selected pill takes heroUiSurfaceEffects() instead of plain box shadows, so
it follows the --surface-shadow token (none in dark) and combines with the
focus ring field by field. heroUiSurfaceBoxShadows is removed, and the dark
mode approximation with it.
onNot(Breakpoint.minWidth(sm)) is the complement of sm:mt-0, so the margin
reaches the last fraction below 640px where maxWidth(639) missed 639 to 640.
The recipe doc and the test spell out the caller pattern: restate
heroUiButtonStyle() in the base action and in the below-sm fragment, and assert
the restated size, fill, and gap.
The inset check only repeated the shadow parsing, so expectFocusRing takes an
inset flag. The dropdown button's height comes from the measured secondary
button instead of a literal.
The decided table stays as written, and a dated Adoption revision lists the
four approximations it replaces and what remains, with the surface accordion's
inside ring attributed as an approximation. The select alignment claim is
softened, the corner crop of the inside rings is recorded, the toast caller
pattern is documented, and the reduced-motion note no longer links a closed
Mix PR.
…bels

Besides laying out without an exception, the radio and switch groups under
IntrinsicWidth and IntrinsicHeight take a finite size that contains every label.
The variant holds the 640px-and-up breakpoint, so onNot(fromSm, ...) reads as
the below-sm fragment it is.
…s ends

The inside ring survives the group's clip except at the joined pill's rounded
ends, as toggle_button_group.yaml records.
… notes

The revision quotes the popover row's verdict as decided, names the five rows it
supersedes, and folds the tab shadow into the ring row, where it matches
upstream. Reduced motion says only that Mix 2.3.1's .animate does not read it.
The toast example restates a HeroUI variant, and toast.yaml says the 640 and
768px heights are derived from the CSS and cites the 768px rule in the
published @heroui/react 3.2.6 toast.js.
@leoafarias
leoafarias force-pushed the stack/follow-ups-integration branch from c931a3a to d5990f4 Compare October 29, 2026 21:44
@leoafarias
leoafarias force-pushed the feat/registry-heroui-adopt-remix-apis branch from 4eb0022 to 820af81 Compare October 29, 2026 21:44

This branch has not been deployed

No deployments
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.

1 participant