import { ExpandDialog } from "@elabs-ai/components-ui";npm install @elabs-ai/components-tokens @elabs-ai/components-uiPaste it into Claude Code, Cursor, Codex or any other coding agent. Text in [brackets] is yours to fill in.
Add the brand-ui ExpandDialog component (from @elabs-ai/components-ui) to this project. 1. Read https://elabs-ai.com/llms.txt first: it maps every package and the rules. If you can use MCP servers, connect https://elabs-ai.com/mcp and use its search, docs and tokens tools. If not, run the same lookups in the terminal: `npx -y @elabs-ai/components-cli search "<what you need>"` and `npx -y @elabs-ai/components-cli docs <Component>`. 2. Look ExpandDialog up before writing code: `npx -y @elabs-ai/components-cli docs ExpandDialog` prints its real props, variants, what it pairs with and what to avoid. 3. If @elabs-ai/components-ui is not installed yet: `pnpm add @elabs-ai/components-tokens @elabs-ai/components-ui` (or `npm install @elabs-ai/components-tokens @elabs-ai/components-ui`). If this is the first brand-ui package in the project, wire it once: import `@elabs-ai/components-tokens/styles.css` plus the `themes/light.css` and `themes/dark.css` stylesheets in the CSS entry, add one Tailwind `@source` line per installed @elabs-ai package (Tailwind does not scan node_modules, so without it everything renders unstyled), and wrap the app root in `ThemeProvider` from `@elabs-ai/components-tokens`. 4. Use it here: [the screen or file, and what it should show] 5. Rules: use only @elabs-ai/components-* components and the semantic tokens — no raw colours, no raw font sizes, no arbitrary Tailwind values. Look up each component's real props with the docs tool before you use it; never guess a prop. 6. Done means: the typecheck passes, `npx -y @elabs-ai/components-cli audit src --strict` reports nothing, and you have opened the app and looked at every screen you touched in the light and the dark theme.
Examples
With Description
A description gives the dialog its `aria-describedby`; without one it opts out.
With Actions
Header actions sit on the title row — never in a second toolbar strip above it.
No Detail
No `detail` → one full-width track and no region wrapper at all. The optional pane costs nothing when it is not asked for.
Detail Bottom
Context below rather than beside — for wide content that needs the full width.
Stack Below Sm
`stackBelow` re-runs the placement decision at a breakpoint: a 2.5fr/1fr split on a phone leaves the context pane about 107px wide — present, unreadable. All three breakpoints render here; resize the preview to see them swap.
Stack Below Md
Stack Below Lg
Stack Never
Explicit `never` — the default, spelled out.
Detail Side
`detailPlacement="side"` spelled out, for the same reason.
Long Content
Both panes overflow. Each is its own scroll owner and its own tab stop — a scroll container with no focusable child is unreachable by keyboard (WCAG 2.1.1; axe `scrollable-region-focusable`).
Controlled
Controlled open state, for an app that drives it from a menu or a route.
API
ExpandDialog
| Prop | Type | Description |
|---|---|---|
panesClassName | string | Class on the panes grid. |
fieldClassName | string | Class on the recessed field the panes sit in. |
titlerequired | ReactNode | Names the dialog. Rendered as the `<h2>` Radix labels the dialog by. |
description | ReactNode | One line of supporting context under the title. |
actions | ReactNode | Controls aligned to the inline end of the title row. |
childrenrequired | ReactNode | The enlarged content — the reason the dialog opened. |
detail | ReactNode | Context for what is in the view pane. Omit for a single-pane dialog: the grid then renders one full-width track and no region wrapper at all. |
detailLabel | string | Accessible name for the detail region. @default `t("ui.expandDialog.detail")` |
viewSize | string | View track size (any CSS length). @default `"minmax(0, 2.5fr)"` |
detailSize | string | Detail track size (any CSS length). @default `"minmax(0, 1fr)"` |
viewClassName | string | Class on the view pane. |
detailClassName | string | Class on the detail pane. |
viewTabIndex | number | Tab index for the view pane. Pass `-1` when it owns focusable content. |
detailTabIndex | number | Tab index for the detail pane. Pass `-1` when it owns focusable content. |
ExpandDialogContent
ExpandDialogHeader
| Prop | Type | Description |
|---|---|---|
titlerequired | ReactNode | Names the dialog. Rendered as the `<h2>` Radix labels the dialog by. |
description | ReactNode | One line of supporting context under the title. |
actions | ReactNode | Controls aligned to the inline end of the title row. |
ExpandDialogPanes
| Prop | Type | Description |
|---|---|---|
childrenrequired | ReactNode | The enlarged content — the reason the dialog opened. |
detail | ReactNode | Context for what is in the view pane. Omit for a single-pane dialog: the grid then renders one full-width track and no region wrapper at all. |
detailLabel | string | Accessible name for the detail region. @default `t("ui.expandDialog.detail")` |
viewSize | string | View track size (any CSS length). @default `"minmax(0, 2.5fr)"` |
detailSize | string | Detail track size (any CSS length). @default `"minmax(0, 1fr)"` |
viewClassName | string | Class on the view pane. |
detailClassName | string | Class on the detail pane. |
viewTabIndex | number | Tab index for the view pane. Pass `-1` when it owns focusable content. |
detailTabIndex | number | Tab index for the detail pane. Pass `-1` when it owns focusable content. |