# Agent skill

Install with:

```sh
npx skills add mielsense/mielui --skill mielui
```

For whole pages, apps, and websites, also install the design skill. Its instructions are at /docs/design-skill.md.

```sh
npx skills add mielsense/mielui --skill mielui-design
```

Use /llms.txt for the index and /llms-full.txt for the complete reference.

# Mielui

Build Svelte interfaces using Mielui's documented APIs, tokens, and composition.

Mielui began from Sivir UI and is maintained independently, with its own components, behavior, themes, documentation, and releases. Use Mielui sources for implementation decisions. Sivir examples and version numbers do not establish Mielui compatibility. Preserve the upstream copyright and license notices when copying or redistributing source. The CLI stores them in `notices/mielui/` inside the configured source directory; the repository's UPSTREAM.md records its origins.

## Step 1: Establish the project state

Inspect the project before changing code:

1. Confirm the installed Mielui release's peer requirements. Mielui 0.4.0 requires Svelte 5.56 or newer within Svelte 5 and Tailwind CSS v4.
2. Read the package manifest, lockfile, global CSS entry, and nearby Svelte components.
3. Detect the integration mode:
   - Package mode: `@mielui/svelte` is a dependency and components import from it.
   - Source-copy mode: `mielui.json` and a local Mielui directory exist.
   - Not installed: neither mode is present.
4. Identify the installed Mielui package version or the component versions recorded in `mielui.json`.
5. Preserve the project's package manager, import style, aliases, theme, and local component conventions.

Do not silently switch an existing project between package and source-copy modes.

## Step 2: Load current Mielui sources

Fetch `https://ui.miel.my/llms.txt` at the start of each Mielui task. Treat it as the index for the current catalog, installation guide, theming guide, changelog, and generated component references.

Load documentation progressively:

| Task | Read from the `llms.txt` index |
| --- | --- |
| First Mielui integration | Introduction, Installation, and Theming |
| Choosing components | Components index, then candidate component pages |
| Implementing a component | That component's Markdown page and every Mielui dependency needed for custom composition |
| AI or coding-agent UI | Candidate AI component pages plus [component selection](https://ui.miel.my/docs/component-selection.md) |
| Upgrading or resolving an API mismatch | Installed version, the compiled changelog, the LLM changelog page when linked, and component pages |
| Visual design or review | [design language](https://ui.miel.my/docs/design-language.md) |
| Laying out a whole page, app, or website | The `mielui-design` skill, when it is installed |

Each generated component page contains its current version, dependencies, install command, prop tables for exported parts, public `index.ts` API, and runnable examples. `/llms-full.txt` combines the full reference; prefer individual pages for focused tasks. Read the exact page before using a component that is new to the project. Never invent a part, prop, event, variant, slot/snippet contract, or import path.

Use this authority order when sources disagree:

1. Local source-copied components define source-copy behavior.
2. The installed package and its declarations define package behavior at the locked version.
3. The live Mielui Markdown defines the latest released API and examples.
4. The rendered documentation is visual context, not a substitute for the typed API.

If the project is behind the live release, adapt to the installed API or ask before upgrading. Do not paste latest-only syntax into an older installation.

If web access is unavailable, inspect local Mielui source or installed declarations. State that the live reference could not be checked rather than guessing.

## Step 3: Model the interface

State the user's job, the dominant content or action, and the important empty, loading, success, and error states. For substantial pages, compare at least two materially different compositions and choose the one that makes the task clearest.

Read [design language](https://ui.miel.my/docs/design-language.md) before creating or substantially reshaping an interface. Follow the host application's established visual system when it is more specific than Mielui's defaults.

Choose geometry before components. Mielui is a set of purposeful primitives, not a requirement to wrap every region in a component.

## Step 4: Select and verify components

Read [component selection](https://ui.miel.my/docs/component-selection.md) when selecting new primitives or composing an AI interface.

Prefer the highest-level Mielui component that matches the interaction semantics. Use native Svelte and semantic HTML for layout and content where Mielui adds no behavior. Avoid recreating focus management, keyboard navigation, overlays, live regions, loading behavior, or controlled state already supplied by a component.

Before implementation:

1. List the selected component slugs.
2. Fetch each selected component page from the links in `llms.txt`.
3. Confirm exports, required props, bindable state, event signatures, dependencies, and examples.
4. Reject removed components listed in the current components index and follow its migration guidance.
5. Keep compound components in their documented namespace shape, such as `Dialog.Root` and `Dialog.Content`.

Examples are API evidence, not page templates. Adapt their state model and composition to the user's real content.

## Step 5: Install consistently

When Mielui is absent, choose with the user unless the requested mode is already clear:

| Mode | Choose when |
| --- | --- |
| Package | The project wants dependency-managed updates and imports from `@mielui/svelte`. |
| Source copy | The project wants to own and modify component source. |

Use the project's package manager. Translate the documentation's pnpm examples when needed.

For package mode:

```sh
pnpm add @mielui/svelte
```

Import the token sheet once in the application's global CSS:

```css
@import '@mielui/svelte/ui.css';
```

Ignore the `mielui add` command in a component page when using package mode. That command is only for source-copy projects; package components are already available through the installed dependency.

For source-copy mode:

```sh
pnpm dlx @mielui/svelte init -y
pnpm dlx @mielui/svelte add <component-slug>
```

Import the generated token sheet once and use the aliases recorded in `mielui.json`; do not assume the default path if configuration already exists. Let the CLI resolve transitive Mielui dependencies. Add only components required by the design.

Treat `mielui add` as an operation for missing source, not a safe update command. It skips existing files unless `--overwrite` is passed but can still advance recorded versions in `mielui.json`. Before updating copied components, inspect local modifications and the upstream change, then ask before using `--overwrite` because it replaces owned source.

## Step 6: Implement with Mielui

Use Svelte 5 state and binding patterns that match the project's code. Preserve native semantics and use the component's typed callbacks and bindable props as documented.

Use Mielui semantic tokens and Tailwind utilities before custom values. Let typography, alignment, spacing, and content hierarchy do most of the visual work. Add surfaces, borders, radii, color, and motion only when they communicate grouping, interaction, state, or continuity.

For AI interfaces, compose transcript behavior, message roles, response content, reasoning, tools, questions, progress, attachments, and the composer as separate stateful concerns. Do not make every assistant event look like a chat bubble, and do not animate already-live network chunks merely for decoration.

Implement real states, not only the ideal screenshot:

- Empty content gives a useful next action.
- Loading preserves layout and communicates what is pending.
- Errors explain what failed and how to recover.
- Success confirms the user's action without unnecessary ceremony.
- Long content wraps or scrolls in the correct local region.

## Step 7: Verify the result

Run the project's normal lightweight formatting and lint checks. Run broader checks only when requested or required by the host repository.

Inspect the rendered interface at desktop and narrow widths, in every supported theme. Exercise keyboard focus, overlays, escape and outside-click behavior, form submission, disabled and pending states, transcript following, and long content where applicable. Check the browser console for runtime and accessibility errors.

Before finishing, confirm:

- Every Mielui API used matches the installed version.
- The stylesheet or local token sheet is imported exactly once.
- The first viewport makes the task and dominant action or content clear.
- Responsive behavior recomposes rather than merely shrinking.
- No decorative container, label, icon, color, or motion can be removed without losing meaning.
- The implementation uses real product content and covers relevant non-happy states.

Report the Mielui components added, integration mode, verification performed, and any version or documentation limitation.

## Current composition contracts

The catalog separates Components, Blocks, AI components, Chart components, and Actions. Public component imports remain under `@mielui/svelte/components/<slug>` even when source folders use another category. Chart, PieChart, Gauge, and Heatmap are charts. Actions use `@mielui/svelte/actions/<slug>`: morph, number-shuffle, and shimmer.

Use Dialog instead of Modal, Kbd instead of Shortcut, and HugeiconsIcon with Hugeicons glyph data. Group connects real Button, Input, and trigger components; include Group.Separator between controls. Tag Input renders its tags as secondary badges.

Toast is composable through Root, Content, Footer, Title, Icon, Actions, Action, and Close. The icon, title, and description sit together in Content; Footer appears only for actions. The toast helpers render these same parts. Overlay surfaces accept `surface="solid" | "glass"` on the documented owning part; do not apply glass independently to nested surfaces.

Surfaces are solid by default. Glass is opt-in: set `--mielui-surface: glass` on `:root` for the whole app, or pass `surface="glass"` to one component. Do not add blur classes by hand.

Card is solid unless you pass `surface="glass"` to Card.Root. It does not follow the theme's glass setting the way overlays do. On inset and panel cards the frame frosts and the content surface stays close to opaque.

Frames are two layers: a white frame holding a recessed inset in the stage color (`--color-background`), with header, toolbar and footer strips on the frame. They follow the theme's border setting. With single borders, the default, the inset meets the frame's border, and with double borders a gutter separates them. This applies to inset cards, dialogs, sheets, data tables, composers, toasts and code blocks. Never give a frame a fixed `--mielui-modal-inset`. Multiply by `--mielui-border-inset-scale`, which is 0 for single and 1 for double.

Composer.Toolbar joins the input on one surface by default. Set `variant="inset"` to keep the input on its own inset surface with the toolbar in the frame under it, like an inset Card and its footer. There is no `chrome` variant.

DataTable.ColumnHeader is a button. Each click moves the column to its next sort state, and Shift-click adds it to a multi-column sort. With `variant="inset"`, DataTable.Root frames the table and its footer and lifts DataTable.Toolbar above the frame. Use DataTable.Sort for an explicit field-and-direction menu.

Menu rows and options render buttons and do not take `href`. This covers DropdownMenu.Item, ContextMenu.Item, ContextMenu.CheckboxItem, Select.Item and Combobox.Item. Navigate from `callback`.

Drawer.Content is a floating panel with a fixed width, not a full-width sheet. Size it with a width class on Drawer.Content and leave Header, Body and Footer unconstrained.

FolderCard.Root is a link with `href`, a button with `onclick` and no `href`, and a static article with neither. Keep a FolderCard.Title in the button form, because it names the button.

The default sans font is Inter Tight and the mono font is Geist Mono, loaded by `ui.css` from `@fontsource/inter-tight` and `@fontsource/geist-mono` at weights up to 500. `font-semibold` and `font-bold` resolve to 500, so build hierarchy from size and color. A project that wants another font installs it and sets `--font-sans` after importing `ui.css`.

Heatmap.Root accepts `animation="rows" | "columns" | "live" | "none"`, defaulting to rows. Reduced motion disables entrances. Slider range mode binds a pair of numbers, accepts thumbLabels, and supports dir="rtl". Slider `variant="field"` is one bar with its label and value inside, for panels that stack many numeric settings. It holds a single value, so it cannot combine with `range`. Read each page before using these APIs, particularly when the locked package predates the unreleased changelog.

Bind a component's DOM node with `bind:element`. Every part uses that name, including the Calendar, RangeCalendar, DatePicker, DateRangePicker and OTPField parts, which used `bind:ref` before 0.3.0. HugeiconsIcon follows the same rule.

Names that changed in 0.3.0, and still type-check when misspelled because Svelte passes unknown props through:
- **Alert Dialog** cancels with `AlertDialog.Close`. `Exit` is gone.
- **Sheet** hides its corner close button with `<Sheet.Header showClose={false}>`, the same prop name `Dialog.Content` uses.
- **Tag Input** takes `invalid` and `issues={[{ message }]}`, like `Field.Root`, instead of `error="..."`.
- **Hover Card** sets `placement` (for example `bottom-start`) and `delay` on `HoverCard.Root`. Content no longer takes `side` or `align`.
- **Dialog and Alert Dialog** set their width with `size` (`xs` to `xl`) alone. There is no `orientation`.
- **Checkbox** uses `variant="card"` for the bordered row.
- **Spinner** uses `eased` for its eased rotation.

Translate or reword built-in text with the `labels` prop on the root. It is an object of optional keys with English fallbacks, and keys that insert a value are functions: `<Toaster labels={{ dismiss: 'Fermer', position: (position, total) => `${position} sur ${total}` }} />`. Roots that take it: Attachment, Button, Chart, CodeBlock, ColorPicker, Combobox, Command, CopyButton, DataTable, DatePicker, DateRangePicker, Dialog, FileDiff, FileUpload, FolderCard, Form.ErrorSummary, Gauge, Heatmap, Kbd, Markdown, Message, Notch, NumberField, Pagination, PieChart, Question, Reasoning, ReorderList, Sheet, ShowMore, SkeletonSwap, Slider, TagInput, TaskSteps, Toaster and Tool. Read the component's reference for its keys. Do not add one prop per string.

A part used outside its root throws `<Name> components must be used within <Name.Root>.` Tabs, CodeBlock and FileDiff parts also render on their own.

## Tables, native selects, and loading placeholders

Compose Table.Root with Header, Body, Row, Head, and Cell. Caption, Footer, and ScrollArea are optional. Use variant="inset" for a recessed table. Sorting and selection remain application state; use native aria-sort and existing Button or Checkbox controls.

NativeSelect.Root renders a native select. Bind a string for single selection or a string array with multiple. Its size prop is the native number of visible options. Compose Option and OptGroup inside it.

Apply use:shimmer from @mielui/svelte/actions/shimmer to a loading container, or set variant="shimmer" on Skeleton. Shimmer takes no options and disables itself for reduced motion. Label the loading region; the visual highlight is hidden from assistive technology.

## Selection, uploads, and motion

Select.Root and Combobox.Root use a string value by default. Set `type="multiple"` and bind a `string[]` for multiple selection. Keep the documented Trigger, Content, and Item composition; multiple selection leaves the menu open. Do not add a second selection store around the binding.

FileUpload.Root owns validation and upload state. Use `maxFiles={1}` for single-file picking. Its children snippet exposes the summary for composing the empty dropzone and selected file states. `onUpload` is required; implement the upload there and resolve it only after server confirmation. A local-only demo should explicitly say that it does not upload files. Keep cancellation and retry connected to the documented upload context.

Notch provides nonmodal edge content through Root and Content, with optional Header, Peek, SideAction, and other documented parts. Use `<Toaster variant="notch" />` for notifications instead of adding a second notification host.

Gauge distinguishes `value={null}` from a valid zero measurement. Gauge and Heatmap accept loading states and handle their own placeholder presentation. Use their documented animation options instead of adding timers around examples.

Apply `use:numberShuffle={{ value }}` to a text-only element containing the final number. Keep icons and controls outside it. The action preserves accessible source text and honors reduced motion and disabled theme motion.
