Compose with the toolkit
Applications import public Svelte components from @dg/ui and load @dg/ui/styles.css once in the root layout. The package exports Svelte source, CSS and assets directly; it has no separate build or category entry points.
01State and content
Use Svelte 5 runes for application state and derived values. Components receive ordinary callback props such as onclick, onsend and onselect. DOM callbacks receive their native event; conversation callbacks document when they receive a string. Do not use Svelte 4 event directives or assume a CustomEvent wrapper.
Content goes through children or named snippets. A supplied snippet replaces the corresponding text fallback; Card.title and Button.icon accept either text or a snippet. Only an explicitly bindable prop supports two-way state: currently ChatComposer.value and Tabs.value. A component reference from bind:this is available after mounting and exposes only documented instance methods.
<script>
import { Button, Card, Section } from "@dg/ui";
let count = $state(0);
</script>
<Section>
<Card title="Collection">
{#snippet header()}<span>Archive</span>{/snippet}
<p>Explore the collection and its documents.</p>
{#snippet footer()}<span>{count} selections</span>{/snippet}
</Card>
<Button label="Select" icon="+" onclick={() => count++} />
</Section>
Every component forwards native attributes, DOM callbacks, class and style to its root element, except the names it owns itself; each reference's Notes name that root. Do not target a component's private markup with global selectors.
Forwarded attributes use the native types from svelte/elements, not an unrestricted property map. Use string class names, CSS text for style, native callbacks and appropriate aria-* or data-* attributes. A forwarded attribute does not add toolkit behavior: passing a loading attribute cannot implement a request lifecycle. Button and Card change their native root when href is supplied; choose attributes for that root. Header, Footer and Tabs do not render arbitrary children. Heading forwards Section's padding and crosses but owns its children and fixes gap to 0.
Type checks catch misspelled props and invalid values in typed consumers; they do not validate every JavaScript spread, CSS expression, accessible name or semantic combination. Check the actual composition and its state transitions as well.
02Composition constraints
The quick reference maps each need to its component or class, and its rules apply everywhere. Composition adds these specific constraints:
GridandCardskeep jointive tracks: add no gap between their cells and never repair their lines with overlapping borders..formattedalready spaces its blocks; do not also wrap its paragraphs in a stack.- A linked
Cardis one link: use an articleCardwhen its content includes links or buttons. Never nestChatComposer's form in another form. - Keep small screens free of horizontal page overflow: let text wrap, keep control targets and check long labels, empty content and large text.
03State contract
Implement states only where they apply. A static heading does not need loading, and a disabled action is not the same as a read-only value. Appearance uses the interaction and feedback tokens; semantics remain with the native element, component or application.
| State | Required behavior | Owner |
|---|---|---|
| Rest, hover and keyboard focus | Clear affordance, visible keyboard focus in either theme; hover is not the only route to information. | Native element and shared component. |
| Disabled or unavailable | Prevent activation and communicate why when needed. Native disabled controls leave the tab order; ARIA-disabled controls need an activation guard. | Component for documented disabled behavior; app for availability. |
| Read-only | Keep the value readable, selectable and focusable; do not imply the control is unavailable. | Native field. |
| Pending | Prevent duplicate requests, announce progress, retain cancellation when useful, then restore an actionable state. | App request lifecycle; ChatComposer exposes pending and stop. |
| Invalid or failed | Explain the problem in text and associate field errors; offer recovery without discarding useful input. | App validation and requests. |
| Empty or successful | Distinguish no content, no results and a completed action; provide a next action where useful. | App content; shared components supply presentation. |
| Open, closed or selected | Keep ARIA state synchronized, define Escape and arrow-key behavior where applicable, and restore focus on dismissal. | Documented navigation, Dialog, Tabs and ChatWindow behavior. |
Reduced motion, forced colors, narrow layouts and both themes are verification conditions across these states, not additional business states. Use the native field contract and chat lifecycle for complete examples. Test state transitions, not just a static screenshot of each state.
04Ownership
The application owns domain data, routing, requests, sanitization, persistence and app-specific components; the toolkit supplies presentation and the documented interaction behavior. The reference index is the complete public inventory.