Skip to content

fix(remix): keep outside widget state out of table headers, panel content, and sidebar slots - #340

Open
leoafarias wants to merge 2 commits into
mainfrom
fix/remix-widget-state-scope
Open

leoafarias wants to merge 2 commits into
mainfrom
fix/remix-widget-state-scope

Conversation

@leoafarias

Copy link
Copy Markdown
Collaborator

Description

Mix onFocusVisible, onHovered, onPressed, and onDisabled variants resolve against the nearest WidgetStateProvider. Three Remix parts had no scope of their own where they needed one.

  • Data table headers. A RemixDataTable header without sortable, including the selection header, resolved against whatever state scope encloses the table. A table inside a Pressable or a focused disclosure trigger lit its header styles.
    • Non-sortable headers now get an empty scope, as body cells already have.
    • Sortable headers still resolve against their own state, as the DataTableSpec docs say.
    • Content of a non-sortable header's custom header also resolves against an empty state, so a plain Mix widget there does not react to its own hover or press. The docs now say to wrap it in its own Pressable if it should.
  • Accordion and disclosure content. RemixAccordion and RemixDisclosure mount the panel content inside the trigger's state scope. Widgets in the panel changed when the trigger was hovered, pressed, focused, or disabled.
    • The content now gets an empty scope.
    • The trigger's parts and the item-level container and content regions are unchanged.
  • Sidebar header and footer. RemixSidebar publishes disabled over its whole panel. An onDisabled widget in header or footer therefore lit when the sidebar was disabled, contradicting the enabled documentation.
    • Header and footer content now gets an empty scope.
    • The sidebar's own regions, including the header and footer boxes, still resolve onDisabled.

Validation

Related Issues

Unblocks re-adding the Fortal sortable-header focus ring that #328 withheld because of this leak. No issue to close.


Checklist

  • My PR includes unit or integration tests for all changed/updated/fixed behaviors.
  • I have updated or added relevant documentation (doc comments with ///).
  • I am prepared to follow up on review comments in a timely manner.

Breaking Change

  • Yes, this is a breaking change.
  • No, this is not a breaking change.

Anything that styled a data-table header, accordion or disclosure content, or sidebar header or footer content from outside state was relying on the bug. That reliance is not a supported contract.

…content

Mix `onFocusVisible`, `onHovered`, and `onPressed` variants resolve against
the nearest `WidgetStateProvider`. Two Remix parts had no scope of their own
where they needed one:

- A data-table header without `sortable`, including the selection header,
  resolved against whatever state scope encloses the table, so a table inside
  a focused disclosure trigger or a `Pressable` lit its header styles.
- Accordion and disclosure content is mounted inside the trigger's state
  scope, so widgets in the panel changed when the trigger was hovered,
  pressed, focused, or disabled.

Both now get an empty scope. The trigger's own parts and sortable headers keep
resolving against their own state.
RemixSidebar published `disabled` over its whole panel, so a widget in
`header` or `footer` with an `onDisabled` style lit when the sidebar was
disabled, contradicting the `enabled` documentation. Header and footer now get
an empty scope; the sidebar's own regions still resolve `onDisabled`.

Also cover disabled accordion and disclosure content, document that the
content of a non-sortable data-table header resolves widget-state variants
against an empty state, and reword the changelog entries.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-27T13:10:41.449633Z 0bead48 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

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