Skip to content
NewService Map: 30 components for hosts, ports and routes
<hf-dialog>Custom elementSurfacesFree

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.

View as Markdown
<hf-dialog>

Tryopen it, then press Escape.

Playground

Change a prop and the component updates. Props marked live animate to the new value; the others rebuild the element.

Loading <hf-dialog>
Props
labelremounts
headingremounts
descriptionremounts
<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-dialog
First 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}.json

Or skip the setup and install by URL:

npx shadcn@latest add https://elements.lumesec.ai/r/hf-dialog.json

Usage

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 teammates

Text of the trigger button. Read once on connect.

headingReact propheadingTypestringDefaultInvite teammates

Dialog 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

KeysAction
EscapeClose the dialog with returnValue cancel.
EnterIn 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 with showModal() 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-hidden canvas.
  • 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, heading and description can be changed.
  • The element is not form-associated and its inner form is not sent anywhere; read the values from the close event.
  • The panel is up to 420px wide and centred in the viewport.

Was this page helpful?