You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/uix/soma/components/dialog/README.md

5.7 KiB

Dialog

A modal or non-modal window overlaid on the primary content. Supports focus trapping, scroll lock, nested dialogs, and an alertdialog variant.

Anatomy

<Dialog.Provider bind:open>
	<Dialog.Trigger>Open</Dialog.Trigger>

	<Dialog.Overlay />
	<Dialog.Content>
		<Dialog.Title>Title</Dialog.Title>
		<Dialog.Description>Description text.</Dialog.Description>
		<Dialog.Close>Close</Dialog.Close>
	</Dialog.Content>
</Dialog.Provider>

Content and Overlay render where placed. Wrap in a Portal component for body-level rendering if needed for z-index stacking.

Parts

Part Element Description
Provider none Root context. Manages open state, no DOM of its own.
Trigger <button> Opens the dialog on click.
Content <div> Dialog container. Focus trap, scroll lock, dismissal layers integrated.
Overlay <div> Backdrop behind the dialog.
Title <div> Dialog heading. Linked via aria-labelledby.
Description <div> Dialog description. Linked via aria-describedby.
Close <button> Closes the dialog on click.

ARIA

Part Attribute Value
Trigger aria-haspopup dialog
Trigger aria-expanded true | false
Trigger aria-controls ID of Content
Trigger aria-label Translated label
Content role dialog | alertdialog
Content aria-modal true
Content aria-labelledby ID of Title
Content aria-describedby ID of Description
Content aria-roledescription Optional custom description
Overlay aria-hidden true
Title role heading
Title aria-level Number (default 2)
Close aria-label Translated label

Data Attributes

Part Attribute Values
Trigger data-dialog-trigger Always present
Trigger data-state open | closed
Content data-dialog-content Always present
Content data-state open | closed
Content data-nested Present when this is a nested dialog
Content data-nested-open Present when a child dialog is open
Content data-starting-style Present during open animation (1 frame)
Content data-ending-style Present during close animation
Overlay data-dialog-overlay Always present
Overlay data-state open | closed
Overlay data-nested Present when nested
Overlay data-nested-open Present when a child dialog is open
Overlay data-starting-style Present during open animation
Overlay data-ending-style Present during close animation

CSS Variables

Variable Part Description
--soma-dialog-depth Content, Overlay Nesting depth (0 for first dialog)
--soma-dialog-nested-count Content, Overlay Number of nested dialogs open

Keyboard

Key Action
Escape Close the dialog (configurable via escapeKeydownBehavior)
Tab Cycle focus within the dialog (focus is trapped)
Shift+Tab Cycle focus backwards within the dialog

Focus is automatically moved to the first focusable element on open. On close, focus returns to the trigger.

Usage

Basic modal

<script>
	import { Dialog } from '$soma/components';

	let open = $state(false);
</script>

<Dialog.Provider bind:open>
	<Dialog.Trigger>Open Dialog</Dialog.Trigger>

	<Dialog.Overlay />
	<Dialog.Content>
		<Dialog.Title>Confirm Action</Dialog.Title>
		<Dialog.Description>Are you sure?</Dialog.Description>
		<Dialog.Close>Cancel</Dialog.Close>
	</Dialog.Content>
</Dialog.Provider>

Alert dialog

<Dialog.Provider bind:open variant="alertdialog">
	<!-- role="alertdialog" on Content, cannot dismiss by clicking outside -->
</Dialog.Provider>

Non-modal

<Dialog.Provider bind:open modal={false}>
	<!-- No overlay, no focus trap, no scroll lock -->
</Dialog.Provider>

Nested dialogs

<Dialog.Provider bind:open={outer}>
	<Dialog.Content>
		<Dialog.Provider bind:open={inner}>
			<Dialog.Trigger>Open Nested</Dialog.Trigger>
			<Dialog.Content>
				<!-- data-nested, --soma-dialog-depth: 1 -->
			</Dialog.Content>
		</Dialog.Provider>
	</Dialog.Content>
</Dialog.Provider>

Powered by TurnKey Linux.