Keyboard
| Key | Effect |
|---|---|
| Click trigger | Toggle. |
| Escape | Dismiss (policy-aware). |
| Tab | Focus moves into content. |
Pure state machines (FSMs). No DOM. Run in server, Vitest, Worker. Reach for these when you only want the behavior.
Non-modal anchored panel.
pnpm add @kumiki/machinesimport { createPopoverMachine } from '@kumiki/machines/popover';
const m = createPopoverMachine({ closeOnEscape: true });
m.send({ type: 'OPEN' });
console.log(m.state); // 'open'
m.send({ type: 'ESCAPE' });
console.log(m.state); // 'closed'Svelte 5 {@attach} factories. Glue ARIA / keyboard / focus onto any DOM node you choose. **Best when you want full control over markup and styling.**
pnpm add @kumiki/headless<script lang="ts">
import { createPopover } from '@kumiki/headless/popover';
const p = createPopover();
</script>
<button {@attach p.trigger}>Share</button>
<div {@attach p.content}>
<h2 {@attach p.title}>Share this page</h2>
<button {@attach p.close}>Done</button>
</div>Compound components (<Root> / <Trigger> / …). Markup is fixed; styling is not. Same trade-off as a typical headless UI library.
pnpm add @kumiki/components/popover<script lang="ts">
import { Root, Trigger, Content, Title, Close } from '@kumiki/components/popover';
let open = $state(false);
</script>
<Root bind:open>
<Trigger>Share</Trigger>
<Content>
<Title>Share this page</Title>
<button>Copy link</button>
<Close>Done</Close>
</Content>
</Root>Styled, copy-paste presets (preview). Run pnpm kumiki add to drop the source into your project, then edit freely.
Live preview…
pnpm add @kumiki/atelier<script lang="ts">
import { Tailwind as Popover } from '@kumiki/atelier/popover';
</script>
<Popover.Root>
<Popover.Trigger>Notifications</Popover.Trigger>
<Popover.Content>
<Popover.Title>Inbox</Popover.Title>
<Popover.Description>You have 3 unread items.</Popover.Description>
<Popover.Close>Dismiss</Popover.Close>
</Popover.Content>
</Popover.Root>/ accessibility
axe-core — run on every PR (LTR + RTL × every documented state).
| Key | Effect |
|---|---|
| Click trigger | Toggle. |
| Escape | Dismiss (policy-aware). |
| Tab | Focus moves into content. |