Dialog
Modal invite dialog on the native dialog element: focus is trapped, Escape closes it, and pixels fly from the trigger to build the panel.
Playground
Change a prop and the component updates. Props marked live animate to the new value; the others rebuild the element.
<HfDialog label="Invite teammates" heading="Invite teammates" description="They’ll get an email with a link to join the workspace." />
Installation
pnpm dlx shadcn@latest add @lumesec/hf-dialogFirst timeRegister the @lumesec registry once, or install by URL+
Adds @lumesec to your components.json:
pnpm dlx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.jsonOr skip the setup and install by URL:
npx shadcn@latest add https://elements.lumesec.ai/r/hf-dialog.jsonUsage
import { HfDialog } from "@/components/lumesec/hf-dialog";
export function Example() {
return (
<HfDialog label="Invite teammates" heading="Invite teammates" />
);
}Behaviour
A real modal dialog: it traps focus, closes on Escape and returns focus. Opening it, its pixels fly out of the button and assemble the panel over a dithered backdrop; closing sends them back.
API reference
Attributes
labelReact proplabelTypestringDefaultInvite teammatesText of the trigger button. Read once on connect.
headingReact propheadingTypestringDefaultInvite teammatesDialog title, which also labels the dialog. Read once on connect.
descriptionReact propdescriptionTypestringDefaultThey’ll get an email with a link to join the workspace.Text under the title. Read once on connect.
Events
Events bubble and cross the shadow boundary unless the description says otherwise.
openReact proponOpenDetail{}Fires when the dialog opens.
closeReact proponCloseDetail{ returnValue: string | undefined, emails?: string, role?: string }Fires after the dialog closes. returnValue is send with the form's emails and role, cancel for Cancel, Escape or a backdrop click, an empty string for the close button, or the argument passed to hide(); it is undefined when hide() is called without one.
Methods
Call them on the element, for example through a React ref.
show()Opens the dialog. Ignored unless it is closed.
hide(returnValue?: string)Closes the dialog, returns focus to the trigger and passes returnValue to close. Ignored unless the dialog is open or opening.
Keyboard
| Keys | Action |
|---|---|
| Escape | Close the dialog with returnValue cancel. |
| Enter | In the email field: submit the form and close with returnValue send. |
Accessibility
- The trigger button has
aria-haspopup="dialog". - The panel is a native
<dialog>opened withshowModal()and labelled by its heading, so the browser traps focus and makes the rest of the page inert. - Focus moves to the email field when the panel appears and returns to the trigger after closing.
- The close button has
aria-label="Close", and the form fields are wrapped in<label>elements. - The backdrop and flying pixels are drawn on an
aria-hiddencanvas. - Reduced motion: no pixels fly between the button and the panel, the dithered backdrop appears at full strength at once, and the panel appears and disappears at once, without the delay or its fade and scale transition.
Theming
The element reads your shadcn theme tokens through its shadow root, so light and dark follow your theme. The accent comes from --lumesec. See Theming.
This component reads --border, --card, --foreground, --lumesec, --lumesec-foreground, --muted and --muted-foreground.
To restyle only LumeSec elements, set the matching --ui-* overrides: --ui-accent, --ui-border, --ui-fg, --ui-muted, --ui-on-accent, --ui-raised and --ui-surface.
Notes
- The content is a fixed invite form with an email field and a Member, Admin or Viewer role; only
label,headinganddescriptioncan be changed. - The element is not form-associated and its inner form is not sent anywhere; read the values from the
closeevent. - The panel is up to 420px wide and centred in the viewport.
Related
Was this page helpful?