# TheUI Svelte - full documentation > theui-svelte is an accessible, customizable component library for Svelte 5 and Tailwind CSS v4: 70 components covering forms, navigation, overlays, data display and feedback, each with a typed prop API, dark mode and RTL support. Source: https://www.theui.dev. This file is generated from the documentation, so it carries the same content as the individual pages. ## Install ```bash npm i theui-svelte ``` Then in the consumer's `src/app.css`: ```css @import 'tailwindcss'; @import 'theui-svelte/style'; ``` Those two lines are the whole setup. The stylesheet registers the package's own markup for Tailwind to scan, so there is no `@source` line to add. Versions before 3.1.0 needed `@source "../node_modules/theui-svelte";` as well; a project that still carries it is redundant, not broken. ## Agent setup ```bash npx theui ai ``` Run this once in the project root, after the install above. It writes a short pointer block into the instruction files the project already has - `AGENTS.md`, `CLAUDE.md`, Copilot, Cursor, Windsurf, Gemini - each naming `node_modules/theui-svelte/AGENTS.md`, which carries the full rules for the exact version installed. It points rather than copies, so it cannot overwrite rules the project already wrote, and re-running replaces the block in place - which makes it the right thing to do after an upgrade too. Nothing about how the library works depends on this. It only decides how much an agent gets right on the first attempt. ## Writing code with this library - Svelte 5 runes only. Props are `let { x } = $props()`, state is `$state`, derived values are `$derived`. Never `export let`, `on:click`, ``, `createEventDispatcher` or stores. - Content holes are Snippet props rendered with `{@render children?.()}`. - Import from the barrel: `import { Button, Card } from "theui-svelte"`. Deep import paths are flat and always `theui-svelte/.svelte`, whatever folder the component lives in: `theui-svelte/AccordionItem.svelte`, not `theui-svelte/Accordion/AccordionItem.svelte`. - Types and helpers: `import type { ROUNDED } from "theui-svelte/type"` and `import { notify } from "theui-svelte/function"`. - `class` is merged with `twMerge`, so a class you pass wins over the library default for the same property. - Rest props spread onto the root element, so any HTML attribute, `data-*` or event handler passes through. - Build with the semantic tokens - `bg-primary`, `bg-secondary`, `text-default`, `text-muted`, `brand-50..950`, `error-*`, `info-*`, `success-*`, `warning-*` - rather than raw palette colors, so themes and dark mode keep working. - Pair every color with a `dark:` counterpart. Dark mode is class based: `.dark` on ``, toggled by `` and persisted to `localStorage["theui-theme"]`. - Use logical properties for RTL - `ms-*`, `me-*`, `ps-*`, `pe-*`, `start`, `end` - never `left`, `right`, `ml-*` or `mr-*`. - Boolean props are written bare: ``, ``, ``, ``, ``, ``, ``. ## Things that are easy to get wrong - `Accordion.standalone` reads backwards: `true` (the default) means only one item may be open at a time. Pass `standalone={false}` to let several stay open. - `Tabs.variant` defaults to `"pills"`, not `"tabs"`. - `Tab` and `TabPanel` pair by matching `value`, not by document order, and `value` is required on both. - There is no `Textarea` component. Use ``. - `Tooltip` and `Notification` are page-level singletons. Render each once, in `+layout.svelte`. A second instance doubles up listeners. - `Popover.trigger` is a DOM element `id` string, not a Snippet, and fails silently when the id does not resolve at mount. - `Table` with `Record` rows needs `keys` to fix column order, or it renders no cells at all - silently. - `DropdownItem` belongs inside `Dropdown`. Inside `NavDropdown` use `NavLink`: they are two different context systems and mixing them throws. - `Slide` must be a direct child of `Slider`, and does not deregister on destroy, so build the slide list up front. - These throw at runtime outside their parent: `Tab`, `TabPanel` (need `Tabs`), `Slide` (needs `Slider`), `DropdownItem` (needs `Dropdown`), and `NavBrand`, `NavCollapse`, `NavLinkGroup`, `NavLink`, `NavDropdown` (need `Navbar`). - `notify()` is browser only - it returns `""` and does nothing during SSR - and its per-call `position` is ignored. Set placement on ``. - Form config cascades `Fieldset` over `Form`, and an explicit prop over both. - Floating labels need the label after the input, because the CSS uses Tailwind's `peer` modifier. Do not reorder the markup inside `Input` or `Select`. - The z-index ladder is fixed and should not be overridden: Navbar 100, Dropdown 200, Drawer 300, Modal 400, Popup 500, Tooltip 600, Notification 700. --- Source: https://www.theui.dev/docs/accessibility # Accessibility Guide What **theui-svelte** handles for you, what is left to you, and the keys every component answers to. Every component ships with its roles, its keyboard behavior and its focus handling already in place, so a modal traps focus and a tab list answers to the arrow keys without any work from you. What the library cannot know is your content: the name of an icon-only button, the text of a label, the colors you pick. That part is yours, and this page marks the line between the two. ## Why Accessibility Matters Accessible pages let people understand, navigate and use your site whether they see it, hear it, or drive it from the keyboard alone. Much of it is also plain good practice: a page that works without a mouse works on a broken trackpad too, and a field with a real label is easier for everyone to fill in. ## What the Components Handle These behaviors come with the components. You do not have to add them, and you should not need to work around them. - **Roles and structure**: `Modal` is a dialog, `Tabs` renders a real tab list, `Dropdown` items carry `menuitem`, `Progress` is a progress bar, `Rating` is a group of radio buttons, and `Breadcrumb`, `Pagination` and `NavLink` mark the current page with `aria-current`. - **Keyboard**: arrow keys, `Home` and `End` work inside tabs, sliders, menus, the calendar, the time fields, one-time-code boxes and pagination. The table below lists them all. - **Focus**: a `Modal` moves focus into itself, keeps `Tab` inside while it is open, and hands focus back to whatever opened it. `Escape` closes the modal on top, not all of them. Closed modals and drawers are `inert`, so the keyboard skips what is hidden behind them. - **Descriptions**: `helperText` is tied to its field with `aria-describedby`, so a screen reader reads the hint along with the label. `Tooltip` and `Popover` describe the element they belong to. - **Announcements**: a notification announces itself as an alert, the calendar announces the month you move into, and a slider announces slide changes once its autoplay is paused. - **Tables**: header cells carry `scope`, so a screen reader ties every cell to its column, and a table too wide for its container becomes a named region you can scroll with the keyboard. - **Motion**: when the system asks for reduced motion, a slider stops playing by itself. Setting `animationSpeed="none"` turns transitions off wherever the prop exists. ## Keyboard Reference Beyond `Tab` and `Shift + Tab`, which move between the controls on the page, the components answer to these keys. | Component | Keys | | --- | --- | | Tabs | `←` `→` move between tabs, `Home` first, `End` last | | Slider | Arrow keys move one slide, `Home` first slide, `End` last slide | | Dropdown, NavDropdown | `↑` `↓` open the menu, `Escape` closes it and returns focus to the trigger, `Enter` follows a link, `Space` presses a button | | Combobox | Type to filter, `↑` `↓` move, `Home` and `End` jump, `Enter` picks, `Escape` closes, `Backspace` removes the last chip | | DatePicker | `↓` opens the calendar, arrow keys move by day and week, `Home` and `End` jump to the ends of the week, `PageUp` and `PageDown` change month (with `Shift`, year), `Escape` closes | | TimePicker | `↑` `↓` change the part you are on, `←` `→` move between hour, minute and AM/PM, `Home` and `End` jump to the lowest and highest value | | OtpInput | `←` `→` move between boxes, `Backspace` and `Delete` clear, `Home` and `End` jump to the first and last box, and a paste fills the boxes | | Pagination | `←` `→` move between page links | | Rating | Arrow keys pick a value, as in any radio group | | Modal, Drawer, Popup | `Escape` closes the one on top, and `Tab` stays inside an open modal | | Accordion, Collapse | `Enter` or `Space` on the heading opens and closes it | ## What You Still Have to Do The library never invents words for your interface. These are the pieces only you can supply. - **Name icon-only controls.** A button with nothing but an icon has no name to read out. Give it `ariaLabel`. From version 3 the library no longer guesses a name for `Button`, `QabItem` or `NavBrand`, because a guessed name read over the visible text is worse than none. - **Label every field.** Write the label as the content of the field, and keep `helperText` for the hint. Both are tied to the input for you. - **Describe images.** A `Slide` with `src` and an `Avatar` with a picture both take `alt`. Leave it empty only when the image says nothing the text does not already say. - **Mark the current page.** Set `active` on the `NavLink` of the page you are on, and it gets `aria-current="page"`. - **Name what has no text of its own.** A `Table` takes `ariaLabel` or a ``, and a `Close` button takes `ariaLabel` to say what it closes. Name a `Container` only when the area is somewhere people would want to jump to, since a named `Container` becomes a landmark. - **Keep the focus ring.** The components draw a visible ring when a control is focused from the keyboard. If your own CSS removes outlines, put a visible replacement back. - **Check your colors.** Components take their colors from your theme, so contrast depends on the palette you choose. Aim for 4.5:1 on normal text and 3:1 on large text, icons and borders. **Name an icon-only button** ```svelte ``` ## Motion and Animation People who ask their system for reduced motion get less of it: a `Slider` will not play on its own, and its timer bar stays still. The choice is theirs, not a prop, so test it by turning reduced motion on in your operating system. Where you want an element calm for everyone, `animationSpeed="none"` removes its transition. ## Color and Contrast The components inherit your brand colors, so they are exactly as readable as the palette behind them. Check the shades you picked on the [colors page](https://www.theui.dev/docs/colors) against the background they sit on, in both light and dark mode, and remember that a color alone should never be the only thing carrying a meaning: pair it with text, an icon or a shape. ## Testing Your Pages Automatic checks catch perhaps a third of what matters. Do the first item on this list before the others. - **Put the mouse away**: reach every control with `Tab`, use it, and make sure you can always see where you are and can get out of anything you opened. - **axe DevTools** or **WAVE**: browser extensions that report missing names, bad contrast and broken structure. - **Lighthouse**: built into Chrome DevTools, useful as a quick pass over a whole page. - **A screen reader**: VoiceOver on macOS and iOS, NVDA or JAWS on Windows, TalkBack on Android. Listening to one page end to end teaches more than any report. ## Per-Component Notes Every component page ends with its own **Accessibility** section, covering what that component does, the props that affect it and anything it needs from you. See [Modal](https://www.theui.dev/docs/modal#accessibility), [Tabs](https://www.theui.dev/docs/tabs#accessibility) or [Combobox](https://www.theui.dev/docs/combobox#accessibility) for the shape of it. ## Further Support and Feedback If something here does not hold up in practice, that is a bug worth reporting. Open an issue on [GitHub](https://github.com/mbparvezme/theui-svelte/issues) with the component and how you were using it, and it will be looked at. --- Source: https://www.theui.dev/docs/ai-assistants # AI Coding Assistants A coding agent that has never seen **theui-svelte** guesses at the API, and the guesses fail quietly rather than loudly. The package ships the rules it cannot guess, and one command hands them to your agent — the difference between an agent that invents props and one that writes working components. ## What Comes With The Package Everything an agent needs is inside the installed package. The pages on this site are a convenience for tools that fetch URLs, not a dependency — an agent working offline has the whole contract locally. - `node_modules/theui-svelte/AGENTS.md` — the composition rules, the shared prop contract, which children throw outside their parent, and the behaviours that are easy to get wrong. - `node_modules/theui-svelte/dist/**/*.d.ts` — every prop name and type, for the exact version installed. These cannot drift from the code, so they are the better answer to *what props does this take*. - The same documentation as Markdown over HTTP, for tools that would rather read a URL. See [further down](#markdown). Because the rules travel with the package, they describe the version you installed rather than whatever is newest, and they keep working when a future library is published under its own name. ## Setting It Up Agents look for instructions in a **project root**, and none of them promise to read anything from inside `node_modules`. So the rules that ship with the package have to be connected to the files your tools already read. One command does that: **Run this once, in your project root** ```bash npx theui ai ``` It writes a short block into whichever instruction files your project already has — `AGENTS.md`, `CLAUDE.md`, Copilot, Cursor, Windsurf, Gemini — each naming the path to the rules inside the package, then prints back which files it touched. The [CLI reference](https://www.theui.dev/docs/cli) covers every option and the exact block it writes. It writes a **pointer rather than a copy**, which matters twice. It cannot overwrite rules you wrote yourself, because it only ever adds its own block between two markers. And it cannot go stale: upgrading the library upgrades what your agent reads, with nothing to refresh. To do it by hand instead, add one line to your `AGENTS.md`, creating the file if you have none. That is the whole setup for every tool following the [AGENTS.md](https://agents.md) convention, which is now a Linux Foundation standard rather than any one vendor's format: **AGENTS.md** ```md ## theui-svelte Before writing or changing code that uses a theui-svelte component, read `node_modules/theui-svelte/AGENTS.md`. ``` Commit whichever you choose, so everyone on the project works from the same rules. One tool needs a line of its own, and it is the one most Svelte developers use. That is next. ## Claude Code Claude Code reads `AGENTS.md` only as a **fallback**. If a `CLAUDE.md` exists in the directory or any directory above it, `AGENTS.md` is ignored completely — so a project that already has a `CLAUDE.md` never sees a root `AGENTS.md` at all. This is the one case convention does not cover, so the command writes an extra line into `CLAUDE.md` itself: an `@` import, which Claude Code resolves and pulls in rather than looking up later. By hand it is one line at the top, and nothing needs updating when you upgrade the library: **CLAUDE.md** ```md @node_modules/theui-svelte/AGENTS.md # My project ...your own notes... ``` > **Note:** If you have no `CLAUDE.md` at all, a root `AGENTS.md` is picked up on its own and there is nothing more to do — which is why the command creates that file but never creates a `CLAUDE.md` in a project that does not use Claude Code. ## Every Other Tool Most tools read the root `AGENTS.md` directly. The ones that keep their own instructions file do not need a second copy of the rules — a single line naming the path is enough, and it will not go stale. `npx theui ai` writes that line into each of the files below that your project already has, so this table is both what it does and what to do yourself if you would rather. | Tool | Where its instructions live | What to do | | --- | --- | --- | | Codex | `AGENTS.md` | Nothing. Reads the root file, and a nested one wins for files beside it. | | Cursor | `AGENTS.md` | Nothing. A root file carries the same weight as a project rule. | | GitHub Copilot | `AGENTS.md` | Nothing, in the editor and in the coding agent. | | VS Code, repository-wide | `.github/copilot-instructions.md` | Optional. VS Code already reads `AGENTS.md`; use this when you also want always-on rules of your own. | | Cursor, path-scoped rules | `.cursor/rules/*.mdc` | Optional. The extension must be `.mdc` — a plain `.md` in that folder is skipped. | | Claude Code | `CLAUDE.md` | Add `@node_modules/theui-svelte/AGENTS.md`. See [above](#claude-code). | | Gemini CLI | `GEMINI.md` | Add a line naming `node_modules/theui-svelte/AGENTS.md`. | | Aider | `.aider.conf.yml` | Add `node_modules/theui-svelte/AGENTS.md` under `read:`, since Aider needs the file named explicitly. | | Windsurf, Zed, Junie, Jules, Devin, Amp | `AGENTS.md` | Nothing. | For any file in the middle column, this is all it takes: **Pointing another instructions file at the rules** ```md Follow the conventions in node_modules/theui-svelte/AGENTS.md when writing theui-svelte components. ``` Tools change quickly, and this table will drift. The root `AGENTS.md` is the part that keeps working: it is a published standard, not a per-vendor setting. ## The Stylesheet Is Two Lines Tailwind CSS v4 finds classes by scanning files, and it skips `node_modules`. Until version 3.1.0 that meant a third line in your CSS pointing Tailwind back at the package, and forgetting it rendered every component unstyled with nothing logged — the single most common report that the library was broken. The package registers its own markup now, so there is nothing to remember: **./src/app.css** ```diff @import 'tailwindcss'; + @import 'theui-svelte/style'; ``` > **Note:** A project carrying the old `@source "../node_modules/theui-svelte";` line is fine — it is redundant now rather than harmful, and can be deleted whenever convenient. If components still render unstyled, the thing to check is that `@import 'theui-svelte/style'` is there at all, because that import is how Tailwind reaches the library. ## Fetch The Documentation As Markdown Rendered HTML costs an agent a great deal of context for very little content, so every page here is published as Markdown too. These addresses are per library, which leaves room for others to be published beside this one. - [`/svelte/llms.txt`](https://www.theui.dev/svelte/llms.txt) — the index. Every page with a one-line description, preceded by the install steps and the rules most often got wrong. Small enough to paste into a prompt. - [`/svelte/llms-full.txt`](https://www.theui.dev/svelte/llms-full.txt) — the whole set in one file. Thorough, and large: for a tool that indexes the library once rather than on every request. - `/docs/.md` — a single page. Append `.md` to any documentation address, as in [`/docs/button.md`](https://www.theui.dev/docs/button.md). This is the one to reach for when an agent needs one component, because it is a single request. - [`/llms.txt`](https://www.theui.dev/llms.txt) — the root index, which only says which libraries exist and where each one's index is. Every page also advertises its Markdown twin with an `alternate` link tag, so a crawler finds it without being told. The props table survives the conversion, so a twin carries the same API reference as the page you are reading rather than a summary of it. ## What The Rules Actually Say These are the things a model gets wrong when it reasons from component names alone. They are in `AGENTS.md` and in [the index](https://www.theui.dev/svelte/llms.txt), and they are worth knowing yourself. - Deep import paths are flat. `AccordionItem` sits in the `Accordion` folder but imports from `theui-svelte/AccordionItem.svelte`, never from a nested path. - Content holes are Svelte 5 snippets. There are no slots, no `export let`, no `createEventDispatcher` and no stores anywhere in the library. - The `standalone` prop of [`Accordion`](https://www.theui.dev/docs/accordion) reads backwards. Its default of `true` means only one panel opens at a time; it does not mean an item works on its own. - [`Tabs`](https://www.theui.dev/docs/tabs) defaults to `pills` rather than `tabs`, and a `Tab` pairs with its `TabPanel` by matching `value` instead of by order. - There is no `Textarea` component. It is an [`Input`](https://www.theui.dev/docs/input) whose `type` is `textarea`. - [`Tooltip`](https://www.theui.dev/docs/tooltip) and [`Notification`](https://www.theui.dev/docs/notification) are page-level singletons. Render each once in your layout; a second instance doubles the listeners. - [`Popover`](https://www.theui.dev/docs/popover) takes the `id` of its trigger as a string, not a snippet, and stays silent when that id does not resolve. - A [`Table`](https://www.theui.dev/docs/table) built from objects needs `keys` to fix the column order. Without it the rows render no cells, and nothing is logged. - `DropdownItem` belongs to [`Dropdown`](https://www.theui.dev/docs/dropdown). Inside a `NavDropdown` use `NavLink`: they are two separate context systems, and mixing them throws. - Some children throw outside their parent rather than falling back: `Tab`, `TabPanel`, `Slide`, `DropdownItem`, and the whole [`Navbar`](https://www.theui.dev/docs/navbar) family. Build with the [semantic color tokens](https://www.theui.dev/docs/colors) and pair every color with a `dark:` counterpart, and generated pages follow your theme instead of hard-coding one. --- Source: https://www.theui.dev/docs/cli # CLI The library ships a command line tool with one job: hand your coding assistant the rules it cannot guess. It is a single command, it writes a pointer rather than a copy, and everything it does can be undone by deleting a few lines. ## The Command Run it in your project root, after `theui-svelte` is installed: **Your project root** ```bash npx theui ai ``` It reports what it touched, so you can see exactly what changed: **Output** ```bash theui-svelte · AI rules ✓ AGENTS.md created the AGENTS.md standard ✓ CLAUDE.md updated Claude Code ✓ .github/copilot-instructions.md updated GitHub Copilot Your agent now reads node_modules/theui-svelte/AGENTS.md. Start a new agent session to pick it up. ``` Start a new session in your assistant afterwards. Instruction files are read when a session begins, so one already running will not see the change. ## Why A Command At All The rules themselves ship inside the package, at `node_modules/theui-svelte/AGENTS.md`. The problem is that no coding agent reads them from there. Every one of them looks for instructions in a **project root**, and none promises to look inside `node_modules`. So something has to connect the two. The command writes that connection into the files your tools already read — which is work you can also do by hand in about a minute, and [AI coding assistants](https://www.theui.dev/docs/ai-assistants#tools) shows how. ## What It Writes A short block, between two HTML comment markers, naming the path to the rules: **AGENTS.md** ```md ## theui-svelte v3.1.0 This project builds its UI with **theui-svelte**, a Svelte 5 component library on Tailwind CSS v4. Before writing or changing any code that uses one of its components, read: `node_modules/theui-svelte/AGENTS.md` That file carries what the type definitions cannot - which component to reach for, how the compound families compose, which children throw without their parent, and the gotchas that fail silently rather than erroring. Prop names and types are in the bundled `.d.ts` files, so trust those for the shape of a component and the file above for the intent behind it. Documentation as Markdown: https://www.theui.dev/svelte/llms.txt ``` A pointer, not a copy, for two reasons. It cannot overwrite rules you wrote yourself, because it only ever adds its own block to the end of a file. And it cannot go stale: upgrading the library upgrades what your assistant reads, with nothing to refresh. In a `CLAUDE.md` the block carries one extra line, `@node_modules/theui-svelte/AGENTS.md`, because Claude Code resolves that as a real import and pulls the rules in rather than looking them up later. ## Which Files It Touches Only the tools your project shows a sign of. A `CLAUDE.md` written into a project that does not use Claude Code would be noise, so the command does not create one. | File | Tool | When | | --- | --- | --- | | `AGENTS.md` | Codex, Cursor, Copilot, Zed, Aider, Jules | Always. Created if missing, since one file has to carry the pointer. | | `CLAUDE.md` | Claude Code | If the file already exists. | | `.github/copilot-instructions.md` | GitHub Copilot in VS Code | If the file already exists. | | `.cursor/rules/theui-svelte.mdc` | Cursor | If a `.cursor` folder exists. | | `.windsurf/rules/theui-svelte.md` | Windsurf | If a `.windsurf` folder exists. | | `GEMINI.md` | Gemini CLI | If the file or a `.gemini` folder exists. | `AGENTS.md` alone covers most of the ecosystem: it is a published convention rather than one vendor's format, and Claude Code falls back to it when a project has no `CLAUDE.md`. The rest of the table is for the tools that keep their own file. ## Options | Option | What it does | | --- | --- | | *none* | Writes the pointer. This is the normal choice. | | `--copy` | Copies the rules to `.theui-svelte/AGENTS.md` and points there instead. For a project that would rather commit the rules, or one whose agents run before anyone has installed anything. | | `--dry` | Prints what would change and writes nothing. Works with either of the above. | | `-h`, `--help` | The usage summary. | | `-v`, `--version` | The installed library version. | Look before you leap, if you would rather: **See the changes without making them** ```bash npx theui ai --dry ``` The command is also published as `npx theui-svelte ai`, which is the same tool under the package's own name. Use whichever reads better; `theui` is the one these pages use. ## Running It Again, And Undoing It Re-running is safe and is the right thing to do after an upgrade. The block names the version it was written for, so the command replaces the old one in place rather than adding a second copy, and tells you nothing changed when nothing needed to: **Already current** ```bash theui-svelte · AI rules · AGENTS.md unchanged the AGENTS.md standard · CLAUDE.md unchanged Claude Code Everything was already current for v3.1.0. ``` To undo it, delete the block between `` and ``. Nothing else in the file is ever touched, and the two files the command owns outright — the Cursor and Windsurf rules — can simply be deleted. ## When It Cannot Find The Library The command points at the installed package, so it needs the package to be there. If it is not, it says so rather than writing a path that leads nowhere: **Nothing installed yet** ```bash theui-svelte is not installed here. Run npm i theui-svelte first. Or pass --copy to write the rules into the project rather than pointing at the installed package. ``` > **Note:** `npx theui ai` resolves the tool from your own `node_modules`, which is why the library has to be installed first. In a workspace it looks upwards as well, so a dependency hoisted to the repository root is found from a package inside it. It also stops if there is no `package.json` beside you, which almost always means the terminal is in the wrong folder. --- Source: https://www.theui.dev/docs/colors # Colors and Branding One of the main features of theui-svelte components library is its customizable color options, allowing you to maintain brand identity and ensure consistent theming efficiently. On top of Tailwind's own palette, the library defines a set of brand and status colors in a `@theme` block. They behave exactly like Tailwind's native color classes, shades included, and every component reads from them, so changing one variable restyles the whole library. ## Available Color Classes The library exposes these colors as utility classes you can use in your own markup. Here is the full list: #### Shaded Colors 50 100 200 300 400 500 600 700 800 900 950 > **Note:** **[T]** = **Type** (e.g., `bg`, `text`, `border`, `fill`, etc.) **[S]** = **Shade** (e.g., 50, 100-900, 950) **Class example**: `bg-brand-500`, `text-brand-600`, `bg-error-400` The foreground colors have no shades: `text-on-brand`, `text-default`, `text-muted`. #### Non-shaded Colors | | Light mode | Dark mode | | | --- | --- | --- | --- | | {colorData.propertyName} | {color.title} ({color.className}) {color.variable} | | | ## What Each Color Controls Before changing anything, it helps to know which token does what. Most of the library runs on a handful of them. | Token | Where you see it | | --- | --- | | `--color-brand-*` | Primary buttons, the active tab, the selected day of a calendar, the filled part of a range, wizard steps, links and every focus ring. Shade `500` carries most of it, with `600` for hover and `300` for lighter accents. | | `--text-color-on-brand` | The text and icons that sit on top of a brand background. It is one value, not a scale. | | `--color-error-*`, `info`, `success`, `warning` | Alerts, badges, notifications, and the states of a form field. | | `--background-color-*` | Surfaces: the page (`primary`), cards, menus and panels (`secondary`), the layer above those (`tertiary`), and the inverted one (`alt`). | | `--text-color-*` | Body text (`default`), secondary text such as helper text and placeholders (`muted`), and text on the inverted surface (`alt`). | So a rebrand is usually two things: the brand scale, and the foreground that goes on top of it. Everything else follows. ## Rebrand In One Step The library's own brand scale is nothing but aliases of Tailwind's rose palette. Point those eleven variables at another Tailwind palette and every component moves with it. **./src/app.css** ```css @import 'tailwindcss'; @import 'theui-svelte/style'; @theme { --color-brand-50: var(--color-indigo-50); --color-brand-100: var(--color-indigo-100); --color-brand-200: var(--color-indigo-200); --color-brand-300: var(--color-indigo-300); --color-brand-400: var(--color-indigo-400); --color-brand-500: var(--color-indigo-500); --color-brand-600: var(--color-indigo-600); --color-brand-700: var(--color-indigo-700); --color-brand-800: var(--color-indigo-800); --color-brand-900: var(--color-indigo-900); --color-brand-950: var(--color-indigo-950); } ``` Your own palette works the same way, with values in place of the aliases. Any CSS color will do, though `oklch` is what Tailwind itself uses, and it keeps the steps between shades even. **./src/app.css** ```css @theme { --color-brand-500: oklch(0.62 0.19 264); --color-brand-600: oklch(0.55 0.19 264); /* ... and the rest of the scale */ } ``` **Where you put this matters.** The override has to come after `@import 'theui-svelte/style'`. Both declarations land in the same layer, so the later one wins; put it above the import and nothing changes. **Check the contrast while you are here.** `--text-color-on-brand` is white, which suits a mid or dark brand color. Pick a light one, such as amber or lime, and every primary button becomes white on light, which nobody can read. Set the foreground with the brand, aiming for at least 4.5:1 against shade `500`; the [accessibility guide](https://www.theui.dev/docs/accessibility) covers the targets. **./src/app.css** ```css @theme { --color-brand-500: var(--color-amber-400); --text-color-on-brand: #16161D; /* dark text on a light brand */ } ``` ## Colors In Dark Mode Surfaces and text colors are declared twice: once for light mode in `@theme`, and again inside `.dark` in the base layer. The base layer comes after the theme layer, so the dark values win whenever the `dark` class is on the page. An override in `@theme` alone therefore changes light mode only, and the change appears to vanish the moment you switch to dark. To change both, write both. Surfaces and text go in two places; the brand and status scales are not re-declared for dark mode, so those need the `@theme` block only. **./src/app.css** ```css @import 'tailwindcss'; @import 'theui-svelte/style'; @theme { /* light mode, and the brand scale for both modes */ --color-brand-500: var(--color-indigo-500); --background-color-primary: #ffffff; --background-color-secondary: #f4f4f7; --text-color-muted: #5a5a63; } @layer base { .dark { /* dark mode only */ --background-color-primary: #0b0b10; --background-color-secondary: #14141b; --text-color-muted: #9b9ba3; } } ``` The `dark` class itself belongs on the `` element. The [DarkMode](https://www.theui.dev/docs/dark-mode) component puts it there and remembers the choice. ## Reskin Every Surface At Once Behind the surface and text tokens sit eight raw values. Six are the surfaces, three for light and three for dark: every `bg-*` token is built from those, and `text-default` and `text-alt` borrow from them too. That makes them the shortest way to change the feel of a whole app without touching a single component. The other two are `--text-muted-on-light` and `--text-muted-on-dark`, which feed `--text-color-muted`, the color of the `text-muted` class: helper text, placeholders, timestamps and other secondary text. They stand apart from the six because muted text is not a surface. It has to stay readable against the page while still sitting back from the body text, and the value that does that in light mode is not the one that does it in dark mode. The library picks the right one for the current mode, so you set both and think no further about it. **./src/app.css** ```css :root { --theui-light1: #FFFFFF; /* the page */ --theui-light2: #F4F4F7; /* cards, menus, panels */ --theui-light3: #E8E8EE; /* the layer above those */ --theui-dark1: #0B0B10; /* the page, in dark mode */ --theui-dark2: #14141B; --theui-dark3: #1C1C26; --text-muted-on-light: #5A5A63; --text-muted-on-dark: #9B9BA3; } ``` These are plain CSS variables rather than theme tokens, so they build no utilities of their own; they only feed the tokens above. That also makes them simpler to override than a theme token: they live on `:root`, so a `:root` block of your own in `app.css` replaces them, with no `@theme` and no separate rule for dark mode. Redefine them after the import, as with everything else on this page. Set only the ones you want to move. Anything you leave out keeps the library's value, so changing `--text-muted-on-dark` alone is a perfectly good edit. ## Modify Existing Colors You can override the library's default colors by assigning new values to the corresponding CSS theme variables: **./src/app.css** ```css @theme { /* Modify brand primary colors */ --color-brand-50: #f0f9ff; --color-brand-100: #e0f2fe; --color-brand-200: #bae6fd; --color-brand-300: #7dd3fc; --color-brand-400: #38bdf8; --color-brand-500: #0ea5e9; --color-brand-600: #0284c7; --color-brand-700: #0369a1; --color-brand-800: #075985; --color-brand-900: #0c4a6e; --color-brand-950: #082f49; /* Modify background colors */ --background-color-primary: #ffffff; --background-color-secondary: #f8fafc; /* Modify text colors */ --text-color-default: #1e293b; --text-color-muted: #64748b; } ``` ## Add New Color Colors of your own go in the same `@theme` block, and the name you choose decides which utilities Tailwind builds from it. Get the prefix wrong and nothing is reported: the variable is defined, the class simply never exists. #### Add Shaded Colors A name under `--color-*` gives you the whole family of utilities for that color: background, text, border, ring, fill, and the rest. **./src/app.css** ```css @theme { --color-accent-50: #f0f9ff; --color-accent-100: #e0f2fe; /* ... add more shades as needed */ --color-accent-500: #0ea5e9; --color-accent-950: #082f49; } ``` Use them as `bg-accent-500`, `text-accent-300`, `border-accent-700`, `ring-accent-500`. #### Add Non-shaded Colors A single color for one purpose belongs under the namespace of the property it serves: `--background-color-*` for backgrounds and `--text-color-*` for text, the same namespaces this library uses for its own surfaces. `--background-*` and `--text-*` are **not** color namespaces, and `--text-*` in particular belongs to font sizes, so a color defined there quietly produces nothing. **./src/app.css** ```css @theme { /* Right: these build bg-surface and text-highlight */ --background-color-surface: #f8fafc; --text-color-highlight: #4338ca; /* Wrong: no utility comes out of either of these */ --background-surface: #f8fafc; --text-highlight: #4338ca; } ``` Then write `bg-surface` and `text-highlight` as you would any other utility. The same pattern holds for `--border-color-*`, `--fill-*` and `--ring-color-*`. ## Remove A Color To completely remove a color from your theme, set its namespace to initial: **./src/app.css** ```css @theme { /* Remove the warning color palette */ --color-warning-*: initial; /* Remove specific non-shaded colors */ --background-color-tertiary: initial; --text-color-alt: initial; } ``` This will remove all the `warning` color classes, `bg-tertiary` and `text-alt` class from the application! ## Available Color Palette This is what `theui-svelte/style.css` defines. The brand and status scales are aliases of Tailwind's own palettes, which is why pointing one at another palette takes a single line each. **theui-svelte/style.css** ```css :root { /* The raw surface values every light and dark background is built from */ --theui-light1: #FFFDFD; --theui-light2: #F5F3F3; --theui-light3: #EBE9E9; --theui-dark1: #16161D; --theui-dark2: #1E1E26; --theui-dark3: #26262F; --text-muted-on-light: #636369; --text-muted-on-dark: #A1A1AA; } @theme { /* Brand: 50 to 950, aliased to Tailwind's rose scale */ --color-brand-50: var(--color-rose-50); --color-brand-100: var(--color-rose-100); --color-brand-200: var(--color-rose-200); --color-brand-300: var(--color-rose-300); --color-brand-400: var(--color-rose-400); --color-brand-500: var(--color-rose-500); --color-brand-600: var(--color-rose-600); --color-brand-700: var(--color-rose-700); --color-brand-800: var(--color-rose-800); --color-brand-900: var(--color-rose-900); --color-brand-950: var(--color-rose-950); /* What text and icons use on top of a brand background */ --text-color-on-brand: #FFFFFF; /* Status colors, each aliased the same way across all 11 shades */ --color-error-50 ... --color-error-950: var(--color-red-*); --color-info-50 ... --color-info-950: var(--color-sky-*); --color-success-50 ... --color-success-950: var(--color-green-*); --color-warning-50 ... --color-warning-950: var(--color-yellow-*); /* Text */ --text-color-default: var(--theui-dark1); --text-color-muted: var(--text-muted-on-light); --text-color-alt: var(--theui-light1); /* Surfaces */ --background-color-primary: var(--theui-light1); --background-color-secondary: var(--theui-light2); --background-color-tertiary: var(--theui-light3); --background-color-alt: var(--theui-dark1); } /* Dark mode swaps the same names, so every component follows */ @layer base { .dark { --text-color-default: var(--theui-light2); --text-color-muted: var(--text-muted-on-dark); --text-color-alt: var(--theui-dark1); --background-color-primary: var(--theui-dark1); --background-color-secondary: var(--theui-dark2); --background-color-tertiary: var(--theui-dark3); --background-color-alt: var(--theui-light2); } } ``` The status scales are written out in full in the stylesheet; they are shortened here because every shade follows the same pattern. Read the file in the [GitHub repository](https://github.com/mbparvezme/theui-svelte) for the literal source. --- Source: https://www.theui.dev/docs/global-defaults # Global Defaults Square corners everywhere, or no animation anywhere, without repeating the same prop on every component. setTheuiDefaults sets the value once and every component falls back to it. ## Setting The Defaults Call `setTheuiDefaults` once with the values you want. Every component that has the matching prop uses it instead of its own built-in default. **src/routes/+layout.svelte** ```html {@render children()} ``` Keys you leave out keep their built-in value, so you only name what you want to change. Calling it again merges the new keys into the old ones rather than replacing them. ## Where To Call It Call it **once, at module scope**: a ` ``` Two more entry points come with the package: `theui-svelte/type` for the [TypeScript types](https://www.theui.dev/docs/types), and `theui-svelte/function` for helpers such as `notify` and `sanitize`. ## Dark Mode Dark mode is driven by a `dark` class on the `` element. The stylesheet you imported brings the variant with it, so there is nothing to add to your Tailwind setup, and every component already carries its dark styles. Put the [`DarkMode`](https://www.theui.dev/docs/dark-mode) component somewhere in your layout and it does the rest: it follows the operating system until someone chooses for themselves, then remembers that choice. ## Upgrading From Version 2 Version 3 is a break with version 2. These are the changes most likely to touch your code: - Svelte 5.57.1 or newer and Node.js 22.12 or newer are required. - The brand colors were renamed: `brand-primary-50` ... `brand-primary-950` are now `brand-50` ... `brand-950`, and `text-on-brand-primary` is now `text-on-brand`. Rename them in your markup, and rename `--color-brand-primary-*` and `--text-color-on-brand-primary` if you overrode them. - The second brand color is gone. `brand-secondary-*` and `text-on-brand-secondary` no longer exist; use any Tailwind color, or one of your own, in their place. - The raw surface values are prefixed now: `--light1` ... `--dark3` are `--theui-light1` ... `--theui-dark3`. This only matters if you overrode them; `bg-primary`, `bg-secondary` and `bg-tertiary` are unchanged. - String props such as `helperText`, a `title` or a `label` render as plain text now. Pass a snippet, or write the content inside the component, where you used to pass markup. - `Tab` and `TabPanel` each need a `value`, and a tab opens the panel that carries the same one. - `Toggle` uses `checked` for a checkbox and `group` for a radio; `value` is now only the value of the input. - The `reverse` attribute of `Checkbox`, `Radio` and `Toggle` is now `labelPosition`. - `Button`, `QabItem` and `NavBrand` no longer invent an `aria-label`, so give icon-only controls an `ariaLabel` of your own. - The `position` setting of `notify()` moved to the `position` prop of the `Notification` component. - `style.css` no longer loads `@tailwindcss/typography`. The changelog in the [GitHub repository](https://github.com/mbparvezme/theui-svelte) lists every change, including the rewritten `Slider` and the new components. --- Source: https://www.theui.dev/docs # theui-svelte: Svelte 5 Component Library theui-svelte is a component library for Svelte 5, built on Tailwind CSS v4. It covers the pieces most applications need, with the accessibility and the theming already done. ## Introduction **theui-svelte** is TheUI's component library for Svelte, built on Tailwind CSS. The components carry their own ARIA wiring and keyboard behavior, read your brand colors from your CSS, and merge any class you pass with tailwind-merge, so overriding a default does not mean fighting it. It needs Svelte 5.57.1 or newer, Tailwind CSS v4 and Node.js 22.12 or newer. The [installation guide](https://www.theui.dev/docs/installation) takes you from an empty project to your first component. ## Features The main features of the component library are: - **Written for Svelte 5** - components are built with runes, and take snippets wherever you need to pass markup rather than text. - **Accessible from the start** - roles and names, keyboard support, focus handling and reduced motion are part of each component. The [accessibility guide](https://www.theui.dev/docs/accessibility) sets out what is handled and what is left to you. - **Yours to style** - every component takes `class`, merged with [tailwind-merge](https://github.com/dcastil/tailwind-merge), so your own classes win instead of fighting the defaults. - **Your colors, not ours** - components read the [brand palette](https://www.theui.dev/docs/colors) from your CSS, in light and dark mode alike. - **Dark mode with nothing to configure** - the stylesheet brings its own dark variant, and the [DarkMode](https://www.theui.dev/docs/dark-mode) component remembers the choice. - **Right to left** - layouts use logical properties, so [RTL](https://www.theui.dev/docs/rtl) works without a second stylesheet. - **Typed throughout** - every prop has a type, listed on the [types page](https://www.theui.dev/docs/types). - **Safe to render on the server** - nothing reaches for the browser while a page is being rendered. ## Components components, form controls and utilities, each with its own page of examples, a full list of props and an accessibility section. ###### UI COMPONENTS - ###### FORM ELEMENTS - ###### UTILITIES - ## Where to Go Next - [Installation](https://www.theui.dev/docs/installation) - the starter template, or a step by step setup of your own. - [Colors and branding](https://www.theui.dev/docs/colors) - point the components at your palette. - [Accessibility](https://www.theui.dev/docs/accessibility) - what the components handle, the keys they answer to, and what is left to you. - [Types](https://www.theui.dev/docs/types) - every exported type, in alphabetical order. - [Right to left](https://www.theui.dev/docs/rtl) and [z-index](https://www.theui.dev/docs/z-index) - two things worth knowing before you build a layout. --- Source: https://www.theui.dev/docs/license # License MIT License ### Copyright TheUI Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --- Source: https://www.theui.dev/docs/rtl # RTL Turn on right to left support for the whole site, or for single components only. The **theui-svelte** components follow the direction of the page, so Arabic, Persian, Hebrew and Urdu layouts need no second stylesheet and no extra build. Set the direction and everything turns around with it: spacing, borders, icons that point somewhere, and the arrow keys inside the components that use them. ## RTL For The Entire Website To enable RTL across your entire site, set the `dir` attribute on the `` tag in `src/app.html`, next to the `lang` attribute for the language you are writing in. By default, **theui-svelte** components display in LTR (Left-to-Right) mode, but adding this attribute will switch all components and elements to RTL mode. Toggle Direction **src/app.html** ```html ``` Keep `lang` and `dir` in step. Screen readers pick the voice from the language, so a page marked Arabic that is left as `dir="ltr"` reads badly even when it looks fine. ## RTL For A Component If you want to apply RTL only to a part of the page, put `dir="rtl"` on an element around it. Components read the direction from where they sit, so anything inside that element turns around and the rest of the page is untouched. This is what you want for a quoted message, an address, or a form in another language. ```svelte
``` #### Accordion Example The accordion below is currently `dir="{demoDirection}"`. Press the button to turn it around, and watch the heading, the arrow and the padding all follow. Toggle Direction تتبع المكونات اتجاه الصفحة، لذلك لا تحتاج إلى ورقة أنماط ثانية. ```svelte

تتبع المكونات اتجاه الصفحة.

``` ## Writing Classes That Turn Around The components are built with logical properties, the ones that talk about the start and the end of a line rather than left and right. Write your own classes the same way and they will follow the direction for free. - Use `ms-*` and `me-*` instead of `ml-*` and `mr-*`. - Use `ps-*` and `pe-*` instead of `pl-*` and `pr-*`. - Use `start-*` and `end-*` instead of `left-*` and `right-*`. - Use `text-start` and `text-end` instead of `text-left` and `text-right`. - Use `border-s-*` and `border-e-*` instead of `border-l-*` and `border-r-*`. **Both directions from one class** ```svelte
...
...
``` Left and right still have their uses. A logo, a chart or a video player that should never flip is better off with the physical class, and Tailwind also gives you the `rtl:` and `ltr:` prefixes when one case needs a rule of its own. ## What Turns Around By Itself Layout follows the direction through CSS, but a few components also change how they behave, because reading right to left changes what "next" means. - `DatePicker` and `TimePicker` swap their left and right arrow keys, so the keyboard moves with the reading order, and the month arrows of the calendar point the other way. - `Slider` moves and swipes the other way, and its arrow keys follow. - `Progress` fills from the right, and the track of a `Range` fills with it. - `Drawer` slides in from the side you asked for, read as start and end rather than left and right. - Smaller touches follow too: the dot on a `Badge`, and the way avatars overlap in an `AvatarGroup`. These components read the direction from the element they are in, so `dir` anywhere above them is enough. A `Slider` reads it as it appears on the page, so give the element its direction before the slider renders rather than switching it afterwards. Text you write yourself is still yours to mind. The default `Pagination` buttons read `"← Prev"` and `"Next →"`, and those arrows are characters rather than layout, so set `previousButton` and `nextButton` to the wording and the arrows your language expects. --- Source: https://www.theui.dev/docs/types # Types Every type **theui-svelte** exports, in alphabetical order, with what it is for and which components use it. ## Importing Types The types live in a subpath of their own, so you can pull in the ones you need without touching the components. **Typescript** ```ts import type { ANIMATE_SPEED, ROUNDED } from "theui-svelte/type" let speed: ANIMATE_SPEED = "fast" let corner: ROUNDED = "lg" ``` You rarely have to name them: passing a string straight to a prop is checked against these unions anyway. They earn their keep when you keep settings in a variable, take props of your own that you pass on to a component, or write a function that returns one. Types vanish when your app is built. They are there for your editor and for `svelte-check`, and cost nothing at runtime. ## Accordion Size Padding of an accordion heading and its body. Set on `Accordion`, where every `AccordionItem` inside picks it up. **Typescript** ```ts type ACCORDION_SIZE = "compact" | "default" | "large" ``` ## Animation Speed Type How long a transition takes. Nearly every component that moves takes it as `animationSpeed`, and `"none"` turns the transition off, which is the value to reach for when an element should not animate at all. **Typescript** ```ts type ANIMATE_SPEED = "none" | "slower" | "slow" | "normal" | "fast" | "faster" ``` ## Avatar Size Type Diameter of an `Avatar`. An `AvatarGroup` takes it too and hands it to every avatar inside, so the stack stays even. **Typescript** ```ts type AVATAR_SIZE = "xs" | "sm" | "md" | "lg" | "xl" | "2xl" ``` ## Avatar Status Type The dot on an `Avatar`. Leave `status` unset for no dot at all. **Typescript** ```ts type AVATAR_STATUS = "online" | "offline" | "busy" | "away" ``` ## Breadcrumb Data Type One entry in the `data` array of a `Breadcrumb`. An entry without a `url` is rendered as plain text, which is what you want for the page you are already on. **Typescript** ```ts type BREADCRUMB_DATA = { text: string; url?: string } ``` ## Button Size Type Padding and text size of a `Button`, and of a `ButtonGroup` or `Pagination` that passes it down. `"auto"` drops the padding so the button takes the size of what you put inside it. **Typescript** ```ts type BUTTON_SIZE = "xs" | "sm" | "md" | "lg" | "xl" | "auto" ``` ## Card Image Type The `img` prop of a `Card`. Anything else you add to the object, such as `loading` or `width`, is passed to the `` element. **Typescript** ```ts type CARD_IMAGE_TYPE = { class?: string src?: string alt?: string [key: string]: unknown } ``` ## Combobox Item Type What you put in the `items` array of a `Combobox`. A bare string or number is both the value and the text; an object splits the two and can disable an entry or file it under a group heading. **Typescript** ```ts type COMBOBOX_ITEM = string | number | { value?: unknown text?: string disabled?: boolean // Options with the same group name are shown together under its heading group?: string } ``` ## Combobox Option Type The same option once the component has filled in what you left out. This is the shape handed to the `option` snippet and to a `filter` function of your own, so every field is there to read. **Typescript** ```ts type COMBOBOX_OPTION = { value: unknown text: string disabled: boolean group?: string } ``` ## Core Type The library wide defaults you pass to `setTheuiDefaults`. Every key is optional. `animationSpeed`, `shadow` and `reset` are fallbacks, so anything you set on a component, a [Form](https://www.theui.dev/docs/form) or a [Fieldset](https://www.theui.dev/docs/fieldset) beats them. `rounded` is an off switch instead: `false` squares off every component whatever its `rounded` prop says. See [Global defaults](https://www.theui.dev/docs/global-defaults). **Typescript** ```ts type CORE = { rounded?: boolean animationSpeed?: ANIMATE_SPEED reset?: boolean shadow?: SHADOW } ``` ## Divider Align Type Where the label of a `Divider` sits along the line. **Typescript** ```ts type DIVIDER_ALIGN = "start" | "center" | "end" ``` ## Divider Orientation Type Which way a `Divider` runs. A vertical one needs a parent with a height, since it stretches to fill it. **Typescript** ```ts type DIVIDER_ORIENTATION = "horizontal" | "vertical" ``` ## Divider Variant Type The line style of a `Divider`. **Typescript** ```ts type DIVIDER_VARIANT = "solid" | "dashed" | "dotted" ``` ## Dropdown Preload Type When SvelteKit should start fetching the page behind a `DropdownItem` link: as the pointer arrives, as it is pressed, or not at all. **Typescript** ```ts type PRELOAD = false | "off" | "tap" | "hover" ``` ## Dropzone Rejection Type What `FileDropzone` hands to `onreject` for each file it turned away, with the reason it did. Remember that these checks run in the browser, so the server has to make them again. **Typescript** ```ts type DROPZONE_REJECTION = { file: File // Why the file was not accepted reason: "type" | "size" | "count" } ``` A rejection is a good moment to tell people what went wrong, rather than letting the file disappear without a word. ```svelte files.forEach((f) => notify(`${f.file.name}: ${f.reason}`))} /> ``` ## Input Size Type Height and text size of a form control. Set it on one field, or on the `Form` or `Fieldset` around a group of them, and every field inside follows. **Typescript** ```ts type INPUT_SIZE = "sm" | "md" | "lg" | "xl" ``` ## Input Type The `type` of an `Input`. `"textarea"` is in the list because the component renders a `