Skip to content

feat(remix): add toast action placement and stack a narrow toast's action - #318

Open
leoafarias wants to merge 3 commits into
mainfrom
fix/remix-toast-narrow-reflow
Open

leoafarias wants to merge 3 commits into
mainfrom
fix/remix-toast-narrow-reflow

Conversation

@leoafarias

@leoafarias leoafarias commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Description

RemixToast kept its icon, message, action, and close button in one row, so a narrow toast or large text squeezed the message to a sliver. This adds a style-driven action placement and a width-based fallback, so presets can choose the layout per breakpoint and narrow toasts stay readable.

  • API: ToastSpec.actionPlacement / ToastStyler.actionPlacement with RemixToastActionPlacement { inline, below } (null means inline).
    • below puts the action under the title and description, aligned with their start; the icon, message, and close button align to the top, so the close button stays on the first line, after the message.
    • inline keeps the action in the row while the message has room and otherwise uses the below arrangement.
    • It is a spec field, so any Mix variant can switch it, for example ToastStyler().onBreakpoint(Breakpoint.maxWidth(768), ToastStyler().actionPlacement(.below)).
  • Fallback: about 280 logical pixels times the text scale, measured from the width the toast actually gets (parent constraints less the container margin, with the style constraints applied). Toasts with only a close button, or no controls, never stack.
  • Order and focus: screen readers read title, description, action, close, and Tab visits the action before the close button, in LTR and RTL. RemixToast is now a StatefulWidget (same constructor) that keeps its buttons under GlobalKeys, so keyboard focus survives a layout flip and the toast scope's Escape and timeout keep working.
  • Limit: a toast with an inline action measures its width, so it cannot sit under IntrinsicWidth or IntrinsicHeight; use below there. Documented in the docs page and the CHANGELOG.
  • Preset recipes, registry output, and installed app copies are unchanged; presets adopt the property after release.

Validation

  • Tests: placement below and inline; the fallback by width, style max width, container margin, and text scale; a breakpoint variant; LTR and RTL geometry; semantics and Tab order; tapping both buttons; IntrinsicWidth for below and action-less toasts; element identity across layout flips; focus, Escape, and timeout inside a real RemixToastScope after a flip.
  • New tests fail on the earlier implementations (9 on the first approach, 7 without the focus and margin fixes), and each semantics, alignment, and focus-group line fails its test when removed.
  • Full remix suite (2869), registry_source toast and Vanilla tests (439), dart analyze (no new issues), root dart format check, melos run ci:checks with docs:check, open-code:apps:check: passed.

Related Issues

None.


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.

RemixToast laid the message, action, and close button in one row, so a narrow
toast or large text squeezed the message into a sliver. Measure the width the
toast gets (parent constraints enforced by its style constraints, scaled by the
text scale) and, below the breakpoint, move the action and close button to
their own row under the message. Wider toasts keep the single row.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 26, 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-26T18:53:23.633367Z 71bf103 New commits
ℹ️ 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.

Add RemixToastActionPlacement (inline, below) as ToastSpec.actionPlacement
and the generated ToastStyler.actionPlacement. Being a spec field, a style
can switch it with a Mix variant such as onBreakpoint.

`below` puts the action under the title and description, aligned with
their start, and top-aligns the icon, message, and close button so the
close button stays at the trailing top corner. An inline toast that is too
narrow for one row at the current text scale uses the same arrangement;
the fallback keeps the existing width measurement and no longer moves the
close button, or a toast without an action, anywhere.

The stacked arrangement groups the message and action into one semantics
node and keeps widget-order focus traversal, so assistive technology and
Tab still reach the title, description, action, then close button.
RemixToast is now a StatefulWidget with the same constructor. It keeps
the action and close button under GlobalKeys, so their elements, and the
keyboard focus on them, survive a switch between the inline and stacked
arrangements. Before, a resize, rotation, or text-scale change that
crossed the breakpoint or the narrow cutoff re-created both buttons;
focus fell to the route, the scope's focus-within state never cleared,
the countdown stayed paused, and Escape no longer reached the toast.

The narrow fallback now subtracts the container margin from the parent
constraints before applying the style constraints, so a toast whose box
is below the cutoff stacks even when its parent is wide enough.

Reword the placement docs to what holds: the close button stays on the
first line after the message, `inline` keeps the action in the row only
while the message has room, and a toast with an inline action measures
its width and so does not support intrinsic sizing. The docs example
uses Breakpoint.maxWidth(768).
@leoafarias leoafarias changed the title fix(remix): reflow toast actions below the message when narrow feat(remix): add toast action placement and stack a narrow toast's action Oct 26, 2026

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