Skip to content

fix(components): prevent overlay subtitle slot from leaking into nested Alert#1939

Open
ShreyasGit51283 wants to merge 6 commits into
mainfrom
dsys-nested-overlays
Open

fix(components): prevent overlay subtitle slot from leaking into nested Alert#1939
ShreyasGit51283 wants to merge 6 commits into
mainfrom
dsys-nested-overlays

Conversation

@ShreyasGit51283

@ShreyasGit51283 ShreyasGit51283 commented Jun 23, 2026

Copy link
Copy Markdown

Summary

Fixes DSYS-157. When an Alert is nested inside an overlay (Dialog/Modal), the overlay's subtitle slot context leaked into the Alert's Text:

  • It forced slot="subtitle" on the Alert's Text (a bare <Text> threw "A slot prop is required...").
  • The text inherited the Dialog's id + elementType: 'h3', so the Alert body became the Dialog's aria-describedby description rendered as an <h3> (an accessibility bug).
  • The text picked up the overlay's [slot="subtitle"] CSS (wrong color/size/position).

Root cause

  • Dialog provides a RAC TextContext with slots: { subtitle: { id, elementType: 'h3' } }.
  • Alert only overrode HeadingContext/ButtonGroupContext, so its descendants inherited the Dialog's TextContext.
  • Modal.module.css styled [slot="subtitle"] via a descendant selector, reaching into nested alerts.

Changes

  • Alert.tsx — establish Alert's own TextContext (default slot + subtitle slot). Insulates Alert content from ancestor overlays, fixes the a11y leak, and allows a bare <Text> inside an Alert. Backward-compatible: existing <Text slot="subtitle"> usage still works.
  • Modal.module.css — scope the subtitle rule with :not([role='alert'] *) so it no longer reaches into nested alerts. The overlay's own subtitle is unaffected.
  • TestsAlert.spec.tsx adds nested-in-Dialog regression coverage (verified to fail without the fix with the exact "A slot prop is required" error).
  • StoryAlert.stories.tsx adds "Nested in Dialog (DSYS-157)" for visual + Chromatic regression coverage.

Test plan

  • Components/Status/Alert -> "Nested in Dialog (DSYS-157)": both nested alerts render with Alert text styling; the Dialog's own subtitle keeps overlay styling.
  • Existing Alert/Dialog/Modal stories and tests unaffected (pnpm --filter @launchpad-ui/components test).
  • Confirm a bare <Text> inside an Alert (in and out of a Dialog) renders without throwing.
  • Chromatic diff review for Alert/Dialog/Modal.

Made with Cursor

…ed Alert

When an Alert is nested inside a Dialog/Modal, the overlay's `subtitle` slot
context captured the Alert's Text: it forced `slot="subtitle"`, rendered the
text as the Dialog's `h3` description, and applied the overlay's subtitle CSS
(wrong color/size/position). Alert now establishes its own TextContext (default
+ subtitle slots), and the Modal subtitle rule is scoped to skip alert-nested
text. Adds regression tests and a nested-overlay story.

DSYS-157

Co-authored-by: Cursor <cursoragent@cursor.com>
@ShreyasGit51283 ShreyasGit51283 requested a review from a team as a code owner June 23, 2026 15:56
@changeset-bot

changeset-bot Bot commented Jun 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 30fc2cd

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@launchpad-ui/components Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jun 23, 2026

Copy link
Copy Markdown
yarn add https://pkg.pr.new/@launchpad-ui/components@1939.tgz
yarn add https://pkg.pr.new/@launchpad-ui/icons@1939.tgz
yarn add https://pkg.pr.new/@launchpad-ui/tokens@1939.tgz

commit: 30fc2cd

Comment thread packages/components/src/Alert.tsx Outdated
}

& [slot='subtitle'] {
/* Scope to the overlay's own subtitle. The `:not()` keeps this from reaching into a

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mentioned this during the meeting, but let's undo this change for now

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see where you're coming from @nhironaka. I refactored the selectors (commit) to make it explicit that we support slot="header" as a direct child of Modal as well as nested in Dialog, but I made a ticket to deprecate the former, as I see a few usages in Gonfalon

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good!

…wn slots

Replace the global `[slot='subtitle']:not([role='alert'] *)` selector with
dialog-scoped selectors (`[role='dialog'] > [slot='subtitle']` and
`[slot='header'] > [slot='subtitle']`), declared once and shared via a single
selector list. This targets the overlay's own subtitle in both the header and
headerless layouts without the `:not()` guard, and cannot reach a nested Alert
that reuses the `subtitle` slot.
Remove the nested-overlay regression story (and its now-unused imports) from
Alert.stories, and add a `WithHeader` story to Modal.stories so the Dialog/Modal
header layout is demonstrated alongside the Modal component. The header lives
inside the Dialog render prop so the `subtitle` slot context and the dialog's
close handler resolve correctly.
* text. The Dialog's own subtitle keeps the overlay styling, while both nested Alerts
* render with the Alert's body-text styling — identical to how they look outside a modal.
*/
export const NestedInDialog: Story = {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved this to the Modal stories as a "With header" story because I realized we haven't documented the header slot at all. Also removed the ticket from the story name so we don't conflate LP with internal data

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 74b91da. Configure here.

Comment thread packages/components/stories/Modal.stories.tsx Outdated
Comment thread packages/components/stories/Modal.stories.tsx Outdated
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.

3 participants