Keyboard
No component-specific keymap. Inherits standard browser focus / activation behaviour.
Svelte 5 {@attach} factories. Glue ARIA / keyboard / focus onto any DOM node you choose. **Best when you want full control over markup and styling.**
<script lang="ts">
import { createAlert } from '@kumiki/headless/alert';
const ctl = createAlert({});
</script>
<div {@attach ctl.root}>
<!-- your markup -->
</div>Compound components (<Root> / <Trigger> / …). Markup is fixed; styling is not. Same trade-off as a typical headless UI library.
pnpm add @kumiki/components<script lang="ts">
import { Alert } from '@kumiki/components/alert';
</script>
<Alert.Root severity="error">
<Alert.Title>Something went wrong</Alert.Title>
<Alert.Description>Please retry in a moment.</Alert.Description>
</Alert.Root><Alert.Root severity="info" dismissible onDismiss={() => (open = false)}>
<Alert.Title>Heads up</Alert.Title>
<Alert.Close>×</Alert.Close>
</Alert.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 Alert } from '@kumiki/atelier/alert';
let dismissed = $state(false);
</script>
{#if !dismissed}
<Alert.Root severity="warn" dismissible onDismiss={() => (dismissed = true)}>
<Alert.Title>Heads up</Alert.Title>
<Alert.Description>Your trial expires in 3 days.</Alert.Description>
<Alert.Close />
</Alert.Root>
{/if}/ accessibility
axe-core — run on every PR (LTR + RTL × every documented state).
No component-specific keymap. Inherits standard browser focus / activation behaviour.