Skip to content

fix(Toast): reset the UA popover width so an end toast lands on the end edge - #5822

Open
freddymeta wants to merge 1 commit into
mainfrom
fix/toast-viewport-popover-width
Open

fix(Toast): reset the UA popover width so an end toast lands on the end edge#5822
freddymeta wants to merge 1 commit into
mainfrom
fix/toast-viewport-popover-width

Conversation

@freddymeta

Copy link
Copy Markdown
Contributor

Why

A default bottomEnd toast renders on the left. Reproduced on a bare page with no application CSS, so it is not a consumer override — and it is in the released v0.5.2 but not v0.5.0.

The viewport reaches the top layer through popover="manual", and the UA stylesheet gives every popover width: fit-content. That was harmless while the element was anchored by insetInlineEnd: 0: a shrink-wrapped box sits on the end edge whatever its width.

#5353 changed the model — the viewport now spans the inline axis (viewportInlineSpan sets both inset edges to 0) and places the toast with align-items inside itself. A shrink-wrapped box cannot span. Both inset edges cannot be honoured at once, so the box resolves against the start edge at its content width, and align-items: flex-end then aligns the toast to the right of a box that is itself on the left.

Every computed value reads correct in isolation, which is what makes this hard to spot:

align-items:        flex-end   ✓
inset-inline-start: 0px        ✓
inset-inline-end:   0px        ✓
width:              438px      ← in a 1200px viewport

What

One declaration, in the UA-reset block that already neutralises inset, margin, border and background for exactly this reason and just missed width.

Testing

Chromium, 1200px, default position, clean page:

viewport toast x
as shipped 438px at x=0 19
+ width: auto 1200px 781
+ inset-inline-start: auto (pre-#5353 model) 438px 781

Both spellings fix it; width: auto is the one that belongs with the rest of the reset.

All four placements after the fix, plus a narrow viewport:

bottomEnd    toast 781..1181      bottomStart  toast 19..419
topEnd       toast 781..1181      topStart     toast 19..419
360px wide   toast 19..341, inside the viewport

bottomStart / topStart looked right before this only by accident — a shrink-wrapped box on the start edge is where a start-aligned toast belongs anyway.

Full suite: 8887 tests / 316 files pass, typecheck, typecheck:docs, check:repo, lint:strict all clean.

On the test

It asserts the reset declaration, not the rendered geometry. jsdom resolves neither UA popover styles nor a cascade, so it cannot reproduce the bug — the existing placement test asserting width !== '100%' passed happily throughout. Negative control: with the declaration removed it fails expected '' to be 'auto'. The rendered proof is the matrix above.

If a browser-level guard is wanted instead, this is the same shape as the Chromium guards in pr-a11y and I am happy to add one.

Risk

One property on one element. Defaults for bottomStart/topStart are unchanged in output; bottomEnd/topEnd change from broken to correct.

…nd edge

A default `bottomEnd` toast renders on the LEFT. Reproduced on a bare page with
no application CSS, so it is not a consumer override.

The viewport reaches the top layer through `popover="manual"`, and the UA
stylesheet gives every popover `width: fit-content`. That was harmless while
the element was anchored by `insetInlineEnd: 0` — a shrink-wrapped box sat on
the end edge whatever its width. #5353 changed the model: the viewport now
spans the inline axis (`viewportInlineSpan` sets both inset edges to 0) and
places the toast with `align-items` inside itself.

A shrink-wrapped box cannot span. Both inset edges cannot be honoured at once,
so the box resolves against the START edge at its content width, and
`align-items: flex-end` then aligns the toast to the right of a box that is
itself on the left. Every computed value reads correct in isolation, which is
what makes it hard to see: `align-items: flex-end` ✓, `inset-inline-start: 0` ✓,
`inset-inline-end: 0` ✓ — and `width: 438px` inside a 1200px viewport.

Measured in Chromium at 1200px, default position, clean page:

  as shipped              viewport 438px at x=0     toast x=19    ✗
  + width: auto           viewport 1200px           toast x=781   ✓
  + inset-inline-start:auto (the pre-#5353 model)   toast x=781   ✓

Both spellings fix it; `width: auto` is the one that belongs, because the reset
block right there already neutralises `inset`, `margin`, `border` and
`background` for exactly this reason and just missed `width`.

All four placements after the fix, and a 360px viewport:

  bottomEnd    toast 781..1181     bottomStart  toast 19..419
  topEnd       toast 781..1181     topStart     toast 19..419
  360px wide   toast 19..341, inside the viewport

`bottomStart` and `topStart` looked right before this only by accident: a
shrink-wrapped box on the start edge is where a start-aligned toast belongs
anyway.

The new unit test asserts the reset declaration rather than the rendered
geometry — jsdom resolves neither UA popover styles nor a cascade, so it cannot
see the bug itself, and the existing placement test asserting
`width !== '100%'` passed throughout. Negative control: with the declaration
removed the test fails `expected '' to be 'auto'`.
@vercel

vercel Bot commented Sep 1, 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 Sep 1, 2026 11:08am UTC

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Sep 1, 2026
@github-actions github-actions Bot added community Authored by a community contributor (not on the eng/design team) needs:code-review High-risk change (new package/component/API) — needs human code review before merge labels Sep 1, 2026
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

PR Analysis Report

Preview availability: Storybook and Sandbox were not published for this CI run.

Modified Components

Toast (@astryxdesign/core)
Metric Before After Delta
Bundle Size (ESM) N/A N/A N/A
Lines of Code N/A 1251 -
Complexity N/A Very High (126) -

Bundle Size Summary

Package Size (ESM) Size (CJS) Gzipped
@astryxdesign/core N/A 4.8KB 1.2KB

Accessibility Audit

Status: No accessibility violations detected.

Visual Regression

Status: No visual change across 238 compared shot(s).


Generated by PR Enrichment workflow | View full report

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. community Authored by a community contributor (not on the eng/design team) needs:code-review High-risk change (new package/component/API) — needs human code review before merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant