Skip to content

feat: add AlertDialog component#699

Open
rohanchkrabrty wants to merge 1 commit intomainfrom
worktree-feat-alert
Open

feat: add AlertDialog component#699
rohanchkrabrty wants to merge 1 commit intomainfrom
worktree-feat-alert

Conversation

@rohanchkrabrty
Copy link
Contributor

@rohanchkrabrty rohanchkrabrty commented Mar 12, 2026

Summary

  • Add AlertDialog component wrapping Base UI AlertDialog primitive
  • 1:1 API and style mapping with existing Dialog component (reuses dialog.module.css)
  • Uses role="alertdialog" — does not close on outside click, requiring explicit user action
  • Sub-components: Header, Footer, Body, Trigger, Content, Close, CloseButton, Title, Description
  • 12 passing tests covering rendering, overlay, close behavior, and custom components
  • Docs with playground, controlled, menu composition, discard changes, and nested examples

Summary by CodeRabbit

  • New Features

    • Added AlertDialog component with customizable properties including width, overlay styling, and animation controls.
    • Component includes composable subcomponents for flexible dialog layouts (Header, Footer, Body, Title, Description, etc.).
    • Built-in accessibility features with ARIA support and focus management.
  • Documentation

    • Added comprehensive AlertDialog documentation with usage examples, API reference, and accessibility guidelines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@vercel
Copy link

vercel bot commented Mar 12, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
apsara Ready Ready Preview, Comment Mar 12, 2026 11:14am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 12, 2026

📝 Walkthrough

Walkthrough

Introduces a complete AlertDialog component system with configurable content (showCloseButton, overlay styling, width), composed subcomponents (Header, Footer, Body, Title, Description, Close), extensive tests covering rendering and interaction patterns, and comprehensive documentation with multiple usage examples and prop references.

Changes

Cohort / File(s) Summary
Component Implementation
packages/raystack/components/alert-dialog/alert-dialog-content.tsx, packages/raystack/components/alert-dialog/alert-dialog-misc.tsx, packages/raystack/components/alert-dialog/alert-dialog.tsx, packages/raystack/components/alert-dialog/index.ts
New AlertDialog component with Content wrapper supporting showCloseButton, overlay blur, width customization, and nested animation control; utility subcomponents (Header, Footer, Body, Title, Description, CloseButton) composed from primitives and Flex; main export attaching subcomponents as static properties.
Component Tests
packages/raystack/components/alert-dialog/__tests__/alert-dialog.test.tsx
Comprehensive Vitest suite validating trigger/content rendering, overlay behavior, close via button or primitive, custom component support, and minimal configurations.
Documentation & Props
apps/www/src/content/docs/components/alert-dialog/index.mdx, apps/www/src/content/docs/components/alert-dialog/props.ts, apps/www/src/content/docs/components/alert-dialog/demo.ts
Full MDX documentation with anatomy, API references, and accessibility notes; TypeScript prop interfaces for all subcomponents; demo configurations for controlled, menu-triggered, discard, and nested dialog patterns.
Playground & Examples
apps/www/src/components/playground/alert-dialog-examples.tsx, apps/www/src/components/playground/index.ts
Client-side playground component demonstrating two AlertDialog usage patterns (delete confirmation and discard changes) with re-export in index.
Package Exports
packages/raystack/index.tsx
Added AlertDialog to main package public API.

Sequence Diagram

sequenceDiagram
    participant User
    participant Trigger as AlertDialog.Trigger
    participant Root as AlertDialog Root
    participant Portal as Portal
    participant Backdrop as Backdrop/Overlay
    participant Content as AlertDialog.Content
    participant Close as Close Handler

    User->>Trigger: Click Trigger Button
    Trigger->>Root: Emit Open State Change
    Root->>Root: Update open state
    Root->>Portal: Render (open=true)
    Portal->>Backdrop: Render with blur/className
    Portal->>Content: Mount Content
    Content->>Content: Render Header, Body, Footer
    Content->>Content: Conditionally render CloseButton

    User->>Close: Click CloseButton / Trigger Close
    Close->>Root: Emit Open State Change
    Root->>Root: Update open state (open=false)
    Root->>Portal: Unmount
    Portal-->>User: Dialog Hidden
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • raystack/apsara#579: Introduces Dialog component migration patterns that parallel the AlertDialog implementation, including similar content composition, overlay styling, and subcomponent architecture.

Suggested reviewers

  • rsbh
  • paanSinghCoder

Poem

🐰 A dialog appears, so bold and so bright,
Alert to the user with content just right,
Close buttons aplenty, overlay blur so fine,
Nested animations make interaction divine,
Documentation complete, tests running clean—
The finest AlertDialog ever seen!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add AlertDialog component' directly and clearly summarizes the main change—introducing a new AlertDialog component. It is concise, specific, and immediately conveys the primary change across all modified files.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch worktree-feat-alert

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (3)
apps/www/src/components/playground/alert-dialog-examples.tsx (1)

24-33: Make the primary actions self-contained in the playground.

Delete and Discard are plain buttons here, so clicking them leaves the dialog open and the demo ends in a no-op state. Wrapping them with AlertDialog.Close or wiring a demo handler would keep the example interactive.

♻️ Possible cleanup
-              <Button color='danger'>Delete</Button>
+              <AlertDialog.Close
+                render={<Button color='danger'>Delete</Button>}
+              />
...
-              <Button color='danger'>Discard</Button>
+              <AlertDialog.Close
+                render={<Button color='danger'>Discard</Button>}
+              />

Also applies to: 47-55

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/www/src/components/playground/alert-dialog-examples.tsx` around lines 24
- 33, The demo's primary action buttons ("Delete" and "Discard") are plain
Buttons so they don't close the dialog; wrap those Buttons with
AlertDialog.Close (or add an onClick that triggers the dialog close) so clicking
them actually closes the AlertDialog; update both occurrences (the Button inside
AlertDialog.Footer with label "Delete" and the similar "Discard" example around
lines 47-55) and ensure you use the AlertDialog.Close component to contain the
Button or call the AlertDialog's close handler so the playground remains
interactive.
packages/raystack/components/alert-dialog/alert-dialog-content.tsx (1)

40-46: Don't forward overlay.blur past this wrapper.

blur is only used to choose a CSS class here, but ...overlay forwards it as a real prop. Destructure it out first so this styling flag doesn't leak downstream.

♻️ Suggested cleanup
   (
     {
       className,
       children,
       showCloseButton = true,
       overlay,
       width,
       style,
       showNestedAnimation = true,
       ...props
     },
     ref
   ) => {
+    const { blur, className: overlayClassName, ...overlayProps } = overlay ?? {};
+
     return (
       <AlertDialogPrimitive.Portal>
         <AlertDialogPrimitive.Backdrop
-          {...overlay}
+          {...overlayProps}
           className={cx(
             styles.dialogOverlay,
-            overlay?.blur && styles.overlayBlur,
-            overlay?.className
+            blur && styles.overlayBlur,
+            overlayClassName
           )}
         />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/raystack/components/alert-dialog/alert-dialog-content.tsx` around
lines 40 - 46, Destructure the blur flag out of the overlay object so it isn't
forwarded to AlertDialogPrimitive.Backdrop: replace uses of overlay and
overlay?.className with a new const like const { blur, ...overlayProps } =
overlay || {} and then spread overlayProps into AlertDialogPrimitive.Backdrop
and use overlayProps.className in the cx call; keep using blur only to select
styles.overlayBlur and ensure AlertDialogPrimitive.Backdrop never receives the
blur prop.
apps/www/src/content/docs/components/alert-dialog/props.ts (1)

58-61: Missing children prop for consistency.

AlertDialogDescriptionProps lacks a children prop while other similar interfaces (AlertDialogHeaderProps, AlertDialogBodyProps, AlertDialogTitleProps, AlertDialogFooterProps) include it. For documentation consistency, consider adding it.

Proposed fix
 export interface AlertDialogDescriptionProps {
   /** Additional CSS class names for description */
   className?: string;
+
+  children?: React.ReactNode;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/www/src/content/docs/components/alert-dialog/props.ts` around lines 58 -
61, AlertDialogDescriptionProps is missing a children prop which breaks
consistency with sibling interfaces (AlertDialogHeaderProps,
AlertDialogBodyProps, AlertDialogTitleProps, AlertDialogFooterProps); add a
children?: React.ReactNode (or JSX.Element | ReactNode per project convention)
to the AlertDialogDescriptionProps interface so it accepts renderable children,
and update any related type imports if needed to match the other
AlertDialog*Props definitions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/www/src/content/docs/components/alert-dialog/demo.ts`:
- Around line 3-23: getCode currently accepts a single props object but the
playground calls getCode(updatedProps, componentProps) per the GetCodeType
signature; update getCode to accept two parameters (updatedProps: Record<string,
any>, props: Record<string, any>) and merge them (e.g., create a finalProps
where keys from props provide defaults for any missing in updatedProps) before
using title/description, ensuring the returned string never interpolates
undefined values; reference the getCode function and the title/description
usages inside the template and match the GetCodeType signature.

In `@apps/www/src/content/docs/components/alert-dialog/index.mdx`:
- Around line 73-89: The docs are missing the AlertDialog.Close API entry;
update the MDX to document the exported Close primitive by adding an API
reference for AlertDialog.Close (matching the symbol in
packages/raystack/components/alert-dialog/alert-dialog.tsx). Add an
auto-type-table or manual prop table for the Close primitive (e.g.,
AlertDialogCloseProps or the exact exported type name used in alert-dialog.tsx)
alongside the existing CloseButton and Trigger entries so the main
action-wrapping close component is documented.
- Around line 99-103: Update the prose to reference the exported root symbol
<AlertDialog> instead of AlertDialog.Root: change the sentence to say that when
the trigger is outside <AlertDialog> you should use the controlled open /
onOpenChange props; ensure the example line remains (Demo data={menuDemo}) and
that the docs mention the public API symbol AlertDialog (not AlertDialog.Root)
so readers are guided to the correct exported component.

In `@apps/www/src/content/docs/components/alert-dialog/props.ts`:
- Around line 63-69: The AlertDialogTriggerProps interface is using Radix's
asChild prop but should match base-ui's API; update AlertDialogTriggerProps so
it replaces asChild with base-ui composition prop render and include the other
base-ui props exposed by AlertDialog.Trigger (e.g., render, handle,
nativeButton, payload, id, style, className) to mirror the re-export of
AlertDialogPrimitive.Trigger from `@base-ui/react`; if you intend to expose a
subset, at minimum add render (with updated JSDoc) and remove asChild so the
interface matches the actual base-ui prop surface.

In `@packages/raystack/components/alert-dialog/__tests__/alert-dialog.test.tsx`:
- Around line 69-75: The current test 'renders in portal' uses
dialog.closest('body') which can be a false positive; update the test that calls
renderAndOpenAlertDialog(<BasicAlertDialog />) to capture the RTL render result
(container) and then assert the dialog is actually attached to document.body and
not inside the render container: e.g., use getByRole('alertdialog') and assert
document.body.contains(dialog) (or document.body toContainElement(dialog)) and
container not toContainElement(dialog). Ensure you reference the existing test
name 'renders in portal', the helper 'renderAndOpenAlertDialog', and component
'BasicAlertDialog' when making the change.

---

Nitpick comments:
In `@apps/www/src/components/playground/alert-dialog-examples.tsx`:
- Around line 24-33: The demo's primary action buttons ("Delete" and "Discard")
are plain Buttons so they don't close the dialog; wrap those Buttons with
AlertDialog.Close (or add an onClick that triggers the dialog close) so clicking
them actually closes the AlertDialog; update both occurrences (the Button inside
AlertDialog.Footer with label "Delete" and the similar "Discard" example around
lines 47-55) and ensure you use the AlertDialog.Close component to contain the
Button or call the AlertDialog's close handler so the playground remains
interactive.

In `@apps/www/src/content/docs/components/alert-dialog/props.ts`:
- Around line 58-61: AlertDialogDescriptionProps is missing a children prop
which breaks consistency with sibling interfaces (AlertDialogHeaderProps,
AlertDialogBodyProps, AlertDialogTitleProps, AlertDialogFooterProps); add a
children?: React.ReactNode (or JSX.Element | ReactNode per project convention)
to the AlertDialogDescriptionProps interface so it accepts renderable children,
and update any related type imports if needed to match the other
AlertDialog*Props definitions.

In `@packages/raystack/components/alert-dialog/alert-dialog-content.tsx`:
- Around line 40-46: Destructure the blur flag out of the overlay object so it
isn't forwarded to AlertDialogPrimitive.Backdrop: replace uses of overlay and
overlay?.className with a new const like const { blur, ...overlayProps } =
overlay || {} and then spread overlayProps into AlertDialogPrimitive.Backdrop
and use overlayProps.className in the cx call; keep using blur only to select
styles.overlayBlur and ensure AlertDialogPrimitive.Backdrop never receives the
blur prop.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cd433162-9765-4f44-ac93-237c2f7a7dec

📥 Commits

Reviewing files that changed from the base of the PR and between 6a23e71 and 55a4849.

📒 Files selected for processing (11)
  • apps/www/src/components/playground/alert-dialog-examples.tsx
  • apps/www/src/components/playground/index.ts
  • apps/www/src/content/docs/components/alert-dialog/demo.ts
  • apps/www/src/content/docs/components/alert-dialog/index.mdx
  • apps/www/src/content/docs/components/alert-dialog/props.ts
  • packages/raystack/components/alert-dialog/__tests__/alert-dialog.test.tsx
  • packages/raystack/components/alert-dialog/alert-dialog-content.tsx
  • packages/raystack/components/alert-dialog/alert-dialog-misc.tsx
  • packages/raystack/components/alert-dialog/alert-dialog.tsx
  • packages/raystack/components/alert-dialog/index.ts
  • packages/raystack/index.tsx

Comment on lines +3 to +23
export const getCode = (props: { title?: string; description?: string }) => {
const { title, description } = props;
return `
<AlertDialog>
<AlertDialog.Trigger render={<Button color="danger" />}>
Discard draft
</AlertDialog.Trigger>
<AlertDialog.Content width={400} showCloseButton={false}>
<AlertDialog.Body>
<AlertDialog.Title>${title}</AlertDialog.Title>
<AlertDialog.Description>
${description}
</AlertDialog.Description>
</AlertDialog.Body>
<AlertDialog.Footer>
<AlertDialog.Close render={<Button variant="outline" color="neutral">Cancel</Button>} />
<AlertDialog.Close render={<Button color="danger">Discard</Button>} />
</AlertDialog.Footer>
</AlertDialog.Content>
</AlertDialog>`;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Function signature mismatch with GetCodeType interface.

The getCode function accepts one parameter, but the playground infrastructure calls it with two: getCode(updatedProps, componentProps) (see demo-playground.tsx lines 66-75). The GetCodeType interface in types.ts expects (updatedProps: Record<string, any>, props: Record<string, any>) => string.

Currently, props receives updatedProps (only changed values), not the full props object with defaults. If a user doesn't modify title or description, they won't be in updatedProps, causing undefined to appear in the rendered code.

Proposed fix to match the expected signature
-export const getCode = (props: { title?: string; description?: string }) => {
-  const { title, description } = props;
+export const getCode = (
+  updatedProps: Record<string, any>,
+  props: Record<string, any>
+) => {
+  const { title, description } = props;
   return `
     <AlertDialog>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const getCode = (props: { title?: string; description?: string }) => {
const { title, description } = props;
return `
<AlertDialog>
<AlertDialog.Trigger render={<Button color="danger" />}>
Discard draft
</AlertDialog.Trigger>
<AlertDialog.Content width={400} showCloseButton={false}>
<AlertDialog.Body>
<AlertDialog.Title>${title}</AlertDialog.Title>
<AlertDialog.Description>
${description}
</AlertDialog.Description>
</AlertDialog.Body>
<AlertDialog.Footer>
<AlertDialog.Close render={<Button variant="outline" color="neutral">Cancel</Button>} />
<AlertDialog.Close render={<Button color="danger">Discard</Button>} />
</AlertDialog.Footer>
</AlertDialog.Content>
</AlertDialog>`;
};
export const getCode = (
updatedProps: Record<string, any>,
props: Record<string, any>
) => {
const { title, description } = props;
return `
<AlertDialog>
<AlertDialog.Trigger render={<Button color="danger" />}>
Discard draft
</AlertDialog.Trigger>
<AlertDialog.Content width={400} showCloseButton={false}>
<AlertDialog.Body>
<AlertDialog.Title>${title}</AlertDialog.Title>
<AlertDialog.Description>
${description}
</AlertDialog.Description>
</AlertDialog.Body>
<AlertDialog.Footer>
<AlertDialog.Close render={<Button variant="outline" color="neutral">Cancel</Button>} />
<AlertDialog.Close render={<Button color="danger">Discard</Button>} />
</AlertDialog.Footer>
</AlertDialog.Content>
</AlertDialog>`;
};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/www/src/content/docs/components/alert-dialog/demo.ts` around lines 3 -
23, getCode currently accepts a single props object but the playground calls
getCode(updatedProps, componentProps) per the GetCodeType signature; update
getCode to accept two parameters (updatedProps: Record<string, any>, props:
Record<string, any>) and merge them (e.g., create a finalProps where keys from
props provide defaults for any missing in updatedProps) before using
title/description, ensuring the returned string never interpolates undefined
values; reference the getCode function and the title/description usages inside
the template and match the GetCodeType signature.

Comment on lines +73 to +89
### Trigger

Renders the element that opens the alert dialog.

<auto-type-table path="./props.ts" name="AlertDialogTriggerProps" />

### CloseButton

Renders a button that closes the alert dialog.

<auto-type-table path="./props.ts" name="AlertDialogCloseButtonProps" />

### Footer

Renders the alert dialog footer section.

<auto-type-table path="./props.ts" name="AlertDialogFooterProps" />
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

AlertDialog.Close is missing from the API reference.

The anatomy block and packages/raystack/components/alert-dialog/alert-dialog.tsx both expose AlertDialog.Close, but the reference only documents CloseButton. That leaves the main action-wrapping close primitive undocumented.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/www/src/content/docs/components/alert-dialog/index.mdx` around lines 73
- 89, The docs are missing the AlertDialog.Close API entry; update the MDX to
document the exported Close primitive by adding an API reference for
AlertDialog.Close (matching the symbol in
packages/raystack/components/alert-dialog/alert-dialog.tsx). Add an
auto-type-table or manual prop table for the Close primitive (e.g.,
AlertDialogCloseProps or the exact exported type name used in alert-dialog.tsx)
alongside the existing CloseButton and Trigger entries so the main
action-wrapping close component is documented.

Comment on lines +99 to +103
### Composing with Menu

Open an alert dialog from a menu item. Since the trigger is outside the `AlertDialog.Root`, use the controlled `open` / `onOpenChange` props.

<Demo data={menuDemo} />
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use the exported root name in this note.

The public API is <AlertDialog>, not AlertDialog.Root, so this sentence currently points readers to a symbol that isn't part of the composed export.

📝 Suggested wording
-Open an alert dialog from a menu item. Since the trigger is outside the `AlertDialog.Root`, use the controlled `open` / `onOpenChange` props.
+Open an alert dialog from a menu item. Since the trigger is outside `AlertDialog`, use the controlled `open` / `onOpenChange` props.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
### Composing with Menu
Open an alert dialog from a menu item. Since the trigger is outside the `AlertDialog.Root`, use the controlled `open` / `onOpenChange` props.
<Demo data={menuDemo} />
### Composing with Menu
Open an alert dialog from a menu item. Since the trigger is outside `AlertDialog`, use the controlled `open` / `onOpenChange` props.
<Demo data={menuDemo} />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/www/src/content/docs/components/alert-dialog/index.mdx` around lines 99
- 103, Update the prose to reference the exported root symbol <AlertDialog>
instead of AlertDialog.Root: change the sentence to say that when the trigger is
outside <AlertDialog> you should use the controlled open / onOpenChange props;
ensure the example line remains (Demo data={menuDemo}) and that the docs mention
the public API symbol AlertDialog (not AlertDialog.Root) so readers are guided
to the correct exported component.

Comment on lines +63 to +69
export interface AlertDialogTriggerProps {
/** Boolean to merge props onto child element */
asChild?: boolean;

/** Additional CSS class names */
className?: string;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check how AlertDialog.Trigger is implemented and which props it accepts

# Search for Trigger implementation or re-export in alert-dialog
rg -nA 10 'Trigger' packages/raystack/components/alert-dialog/

Repository: raystack/apsara

Length of output: 7032


🏁 Script executed:

#!/bin/bash
# Find where AlertDialogPrimitive comes from
rg -nA 3 'AlertDialogPrimitive' packages/raystack/components/alert-dialog/alert-dialog.tsx

# Check what AlertDialog package is used
rg -n 'from.*alert' packages/raystack/components/alert-dialog/alert-dialog.tsx

Repository: raystack/apsara

Length of output: 709


🌐 Web query:

base-ui react AlertDialog Trigger props api documentation

💡 Result:

AlertDialog.Trigger (Base UI React) — props / API

<AlertDialog.Trigger /> is “a button that opens the alert dialog” and it renders a native <button> by default. (base-ui.com)

Props (from the docs):

  • handle?: DialogHandle<Payload> – associates the trigger with an alert dialog handle created via AlertDialog.createHandle() (for detached/external triggers). (base-ui.com)
  • nativeButton?: boolean (default: true) – when you replace the element via render, this controls whether Base UI should treat it as a native <button>; set false if your rendered element is not a button (e.g. a <div>). (base-ui.com)
  • payload?: Payload – payload passed to the dialog when opened (useful with multiple triggers). (base-ui.com)
  • id?: string – forwarded to the rendered element; also used to identify the active trigger in controlled mode (AlertDialog.Root triggerId). (base-ui.com)
  • className?: string | (state) => string | undefined (base-ui.com)
  • style?: CSSProperties | (state) => CSSProperties | undefined (base-ui.com)
  • render?: ReactElement | (props, state) => ReactElement – replace/compose the underlying element. (base-ui.com)

Data attributes:

  • data-popup-open – present when the corresponding dialog is open.
  • data-disabled – present when the trigger is disabled. (base-ui.com)

Citations:


🏁 Script executed:

#!/bin/bash
# Verify the exact file structure and check what props are actually documented
cat -n apps/www/src/content/docs/components/alert-dialog/props.ts | head -80

Repository: raystack/apsara

Length of output: 2408


Update AlertDialogTriggerProps to match the actual base-ui API.

The interface documents asChild (Radix UI's composition pattern) instead of render (base-ui's composition pattern). Since AlertDialog.Trigger directly re-exports AlertDialogPrimitive.Trigger from @base-ui/react, it should expose base-ui's actual props: render, handle, nativeButton, payload, id, style, and className. Replace asChild with the correct base-ui props, or if only a subset is intentionally exposed by this library, add render as the composition mechanism and update the JSDoc accordingly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/www/src/content/docs/components/alert-dialog/props.ts` around lines 63 -
69, The AlertDialogTriggerProps interface is using Radix's asChild prop but
should match base-ui's API; update AlertDialogTriggerProps so it replaces
asChild with base-ui composition prop render and include the other base-ui props
exposed by AlertDialog.Trigger (e.g., render, handle, nativeButton, payload, id,
style, className) to mirror the re-export of AlertDialogPrimitive.Trigger from
`@base-ui/react`; if you intend to expose a subset, at minimum add render (with
updated JSDoc) and remove asChild so the interface matches the actual base-ui
prop surface.

Comment on lines +69 to +75
it('renders in portal', async () => {
renderAndOpenAlertDialog(<BasicAlertDialog />);

await waitFor(() => {
const dialog = screen.getByRole('alertdialog');
expect(dialog.closest('body')).toBe(document.body);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Portal assertion is a false positive right now.

dialog.closest('body') === document.body also passes when the popup is rendered inside RTL's container, so this test won't catch a broken portal implementation. Assert that the dialog is in document.body but not inside the render container.

🧪 Suggested assertion
     it('renders in portal', async () => {
-      renderAndOpenAlertDialog(<BasicAlertDialog />);
+      const { container } = render(<BasicAlertDialog />);
+      fireEvent.click(screen.getByText(TRIGGER_TEXT));
 
       await waitFor(() => {
         const dialog = screen.getByRole('alertdialog');
-        expect(dialog.closest('body')).toBe(document.body);
+        expect(document.body).toContainElement(dialog);
+        expect(container).not.toContainElement(dialog);
       });
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/raystack/components/alert-dialog/__tests__/alert-dialog.test.tsx`
around lines 69 - 75, The current test 'renders in portal' uses
dialog.closest('body') which can be a false positive; update the test that calls
renderAndOpenAlertDialog(<BasicAlertDialog />) to capture the RTL render result
(container) and then assert the dialog is actually attached to document.body and
not inside the render container: e.g., use getByRole('alertdialog') and assert
document.body.contains(dialog) (or document.body toContainElement(dialog)) and
container not toContainElement(dialog). Ensure you reference the existing test
name 'renders in portal', the helper 'renderAndOpenAlertDialog', and component
'BasicAlertDialog' when making the change.

@rohanchkrabrty rohanchkrabrty self-assigned this Mar 12, 2026
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