# Nana UI — complete documentation > Source: https://design.nanatec.co.ke > 72 pages, generated 2026-08-17. > Index of individual pages: https://design.nanatec.co.ke/llms.txt --- # Nana UI > Source: https://design.nanatec.co.ke/ > A framework-agnostic web component library built with Lit — consistent APIs, dark mode, and full accessibility across React, Vue, Svelte, or vanilla JS. ## Designed to compose Real components, composed into a real interface — themed, responsive, and accessible out of the box. ## Why Nana UI

Framework-agnostic

Standards-based custom elements that work anywhere — React, Vue, Svelte, or plain HTML. Typed wrappers ship for all four.

Tree-shakeable

Import the barrel for convenience, or a single component subpath for the smallest possible bundle.

Themeable tokens

A design-token system built on CSS custom properties, with first-class dark mode via one data-theme attribute.

Accessible

Keyboard navigation, ARIA semantics, and focus management are build constraints, not an afterthought.

60+
Components
4
Framework wrappers
0
Runtime dependencies
AA
WCAG 2.2
## Get started in seconds ```bash npm install @nana-tec/ui-components ``` ```js import "@nana-tec/ui-components/button"; ``` ```html Save changes ```

Ready to build?

Drop 60+ accessible, themeable components into your stack today — in any framework.

Get started →
--- # Design Tokens > Source: https://design.nanatec.co.ke/guides/design-tokens/ > The color, spacing, radius, shadow, typography, z-index, and transition scales that every Nana UI component is built from. Every component is built from a shared set of **design tokens** — CSS custom properties (prefixed `--nana-`) for color, spacing, radius, shadow, typography, z-index, and transition. Override them at any scope to re-theme without touching component internals. Import the token foundation once in your app's global stylesheet: ```css @import "@nana-tec/ui-themes/base"; ``` This pulls in `@nana-tec/ui-tokens/css` (the raw scales below) plus the surface semantics and dark-mode overrides. ## Using tokens Reference any token directly, or scope an override to re-theme a subtree: ```css .checkout { --nana-color-primary-600: #2563eb; --nana-radius-md: 9999px; } ``` See [Theming](/guides/theming/) for surface semantics (`--nana-surface-*`) and dark mode. --- # Getting Started > Source: https://design.nanatec.co.ke/guides/getting-started/ > Install @nana-tec/ui-components and render your first web component in any framework. Nana UI is a professional design system built with [Lit](https://lit.dev) web components. The components are standards-based custom elements, so they work across any framework — React, Vue, Svelte, or vanilla JavaScript — with consistent APIs, events, and slots. ## Installation ```bash # npm npm install @nana-tec/ui-components # bun bun add @nana-tec/ui-components ``` ## Importing components Import the barrel to register every component at once: ```js import "@nana-tec/ui-components"; ``` Or import a single component's subpath for the smallest bundle — this registers only that element: ```js import "@nana-tec/ui-components/button"; import "@nana-tec/ui-components/color-picker"; ``` Once imported, use the custom element anywhere in your markup: ```html Save changes ``` ## Framework usage Because these are native custom elements, they drop into any template. ### Vanilla / HTML ```html Click me ``` ### React Typed React wrappers ship alongside the elements: ```jsx import { NanaButton } from "@nana-tec/ui-components/react"; export function Save() { return Save; } ``` ### Vue & Svelte Vanilla tags work directly; the package augments the framework's template types so `` tags type-check: ```js // vue: nuxt.config or main.ts import "@nana-tec/ui-components"; ``` ```svelte Click me ``` ## Next steps - [Theming](/guides/theming/) — design tokens, CSS custom properties, and dark mode. - [Reusability & Composition](/guides/reusability/) — slots, parts, and events. - Browse the [components](/components/button/) for API references and live examples. --- # Docs for LLMs > Source: https://design.nanatec.co.ke/guides/llms/ > Every page of these docs is available as clean Markdown — one file per component, an llms.txt index, or the whole site in a single download. Coding assistants read these docs badly when they scrape HTML: the live examples are rendered custom elements, the source sits behind a "Show code" toggle, and the navigation chrome comes along for the ride. So every page also exists as plain Markdown, generated from the same source the page itself renders. Examples become fenced code blocks; nothing else is lost. ## One page Append `.md` to any docs URL: ``` https://design.nanatec.co.ke/components/button.md https://design.nanatec.co.ke/guides/theming.md ``` Every page carries a **Copy as Markdown** button under its title, alongside **View .md** and **Download** — pick whichever fits how you work. ## The whole library | File | What it is | Use it when | | --- | --- | --- | | [`/llms.txt`](/llms.txt) | An [llmstxt.org](https://llmstxt.org) index: the install snippet plus a titled, described link to every page's Markdown. | The assistant can fetch URLs and should pull only the pages it needs. | | [`/llms-full.txt`](/llms-full.txt) | Every page concatenated into one Markdown document. | You want the whole design system in context, or you're seeding a retrieval index in a single request. | > **Which one?** > > Start with `llms.txt`. It costs a few hundred tokens and lets the model choose > what to read, whereas `llms-full.txt` spends the budget up front — worth it > only when the assistant can't fetch URLs on its own. ## Recipes **Point an assistant at one component** ``` Read https://design.nanatec.co.ke/components/combobox.md and build me a country picker with async filtering. ``` **Give a CLI agent the whole library** ```bash curl -sL https://design.nanatec.co.ke/llms-full.txt -o nana-ui.md ``` Then reference `nana-ui.md` in your prompt, or drop it where your agent picks up project context. **Vendor only the components you use** ```bash for c in button input dialog table; do curl -sL "https://design.nanatec.co.ke/components/$c.md" -o "docs/nana-$c.md" done ``` - docs - nana-button.md - nana-input.md - nana-dialog.md - nana-table.md - src/ - package.json Checking these into the repo keeps the guidance versioned alongside your code. > **Pin your version** > > The Markdown always reflects the latest release. If you pin an older > `@nana-tec/ui-components`, vendor the files rather than fetching at runtime — > otherwise an assistant will happily suggest APIs your version doesn't have. ## What the Markdown contains For each page: the title, a source link, the description, and — where the frontmatter declares them — lifecycle status and the version the component landed in. Then the body, with every example inlined as an `html` code block, so an assistant sees the exact markup the page demonstrates. ## Finding things quickly The sidebar filter (press /) narrows the navigation as you type; matching a group name like "forms" reveals that whole section. For full-text search across page bodies, press Ctrl / + K — and the filter's empty state links straight to it. --- # Reusability & Composition > Source: https://design.nanatec.co.ke/guides/reusability/ > Consume Nana components through attributes, slots, and events — theme once, reuse everywhere. Nana components are designed to be consumed through one stable contract — attributes, slots, and events — and themed through design tokens, CSS variables, and `::part()`. Stay on that surface and the same component drops into any screen, in any framework, with no forking and no shadow-DOM hacks. ## How it flows Tokens flow in, the component exposes a public API, your app composes it — and you theme once at the edges. ``` design tokens component (public API) your app ┌──────────────┐ ┌───────────────────────────┐ ┌──────────────┐ │ --nana-color │ │ attributes variant/size │ │ │ │ --nana-space │ ───▶ │ slots header/body │ ───▶ │ │ │ --nana-radius│ │ events nana-change │ │ │ └──────────────┘ └───────────────────────────┘ └──────────────┘ ▲ ▲ style via ::part / CSS vars │ └────────────────────┴─── theme once, reuse everywhere ──┘ ``` ## 1 · One component, many uses (attributes) Behaviour and appearance are props. No variant means no new component, no copy-paste, no custom CSS. ```html Primary Secondary Ghost Delete Saving… ``` ## 2 · Compose with slots Structure comes from slotted children, so you assemble layouts from primitives instead of reaching inside them. ```html Monthly statement June 2026 Your balance increased by 4.2%. ``` ## 3 · Theme once, reuse everywhere Restyle through the three supported layers below — never by targeting shadow-DOM internals directly. A token change re-skins every instance at once. ```css :root { --nana-color-primary-600: #0f1f1d; --nana-radius-md: 8px; } nana-table { --nana-table-pad-x: 1rem; --nana-table-pad-y: .5rem; } nana-dialog::part(panel) { box-shadow: 0 20px 60px rgb(0 0 0 / .2); } ``` ## 4 · Reusable icon registry The icon set is a shared registry: register a glyph once and every `` can use it by name. The bundled glyphs are code-split — they load on demand, so apps that register only their own icons never ship the full set. ```ts import { registerIcons } from "@nana-tec/ui-components"; registerIcons({ github: { viewBox: "0 0 24 24", paths: ["M12 .5C5.37.5 …"] }, }); ``` ## 5 · Stay clean If you find yourself writing `!important` or piercing the shadow DOM, there's almost always a prop, slot, or part for it. ```html ``` ```html ``` | Need | Reach for | Not | |---|---|---| | Different look / state | `variant`, `size`, `loading` attributes | Cloning the component | | Custom structure | Slots (`header` / `body` / `footer`) | Wrapper divs around internals | | Brand colours / spacing | Design tokens + documented CSS vars | `!important` overrides | | Style an internal part | `::part()` | Piercing the shadow DOM | | A new glyph | `registerIcon()` once, reuse by name | Inline one-off SVGs everywhere | --- # Theming > Source: https://design.nanatec.co.ke/guides/theming/ > Customize Nana UI with design tokens, CSS custom properties, and dark mode. Every component is styled from a shared set of **design tokens** exposed as CSS custom properties (all prefixed `--nana-`). Override them at any scope — the `:root`, a subtree, or a single element — to re-theme without touching component internals. ## Token foundation Import the token base once in your app's global stylesheet: ```css @import "@nana-tec/ui-themes/base"; ``` This defines the full token set: color scales, surface semantics, spacing, radii, typography, shadows, z-index, and transitions. ## Common tokens | Token | Role | |---|---| | `--nana-surface-bg` | Component background | | `--nana-surface-text` | Primary text color | | `--nana-surface-text-muted` | Secondary text color | | `--nana-surface-border` | Borders and separators | | `--nana-surface-subtle` | Subtle fills / hover backgrounds | | `--nana-color-primary-600` | Brand accent | | `--nana-radius-md` | Default corner radius | | `--nana-focus-ring` | Focus outline | ## Overriding tokens Scope overrides to re-theme a subtree: ```css .checkout { --nana-color-primary-600: #2563eb; --nana-radius-md: 9999px; } ``` Many components also expose component-scoped variables and `::part()` hooks for finer control — see each component's **CSS Custom Properties** section. ```html Buy now ``` ## Dark mode Dark mode is driven by a single attribute on the document root: ```js document.documentElement.setAttribute("data-theme", "dark"); ``` The token base ships `:root[data-theme="dark"]` overrides, so every component switches together. In these docs, Starlight's theme toggle sets the same attribute, which is why the live examples follow the site theme. --- # Alert > Source: https://design.nanatec.co.ke/components/alert/ > A contextual message banner for feedback, status and important notices. Supports an optional title, a leading status icon, action buttons and a dismiss control. A contextual message banner for feedback, status and important notices. Supports an optional title, a leading status icon, action buttons and a dismiss control. ## Preview ```html Heads up — this is an informational alert. ``` ## Installation ```bash npm install @nana-tec/ui-components ``` ## Import ```js import "@nana-tec/ui-components/alert"; ``` ## Basic usage ```html Heads up — this is an informational alert. ``` ## Variants ```html Info alert Success alert Warning alert Danger alert Neutral alert ``` ## API ## Events | Event | Type | Description | |---|---|---| | `nana-close` | `CustomEvent` | Dispatched when the alert is dismissed | ## Slots | Slot | Description | |---|---| | `(default)` | The alert message / body content | | `icon` | Custom leading icon (overrides the default variant icon) | | `actions` | Action buttons shown beneath the message | ## CSS Variables | Variable | Default | Description | |---|---|---| | `--nana-alert-bg` | — | Custom background colour | | `--nana-alert-color` | — | Custom text colour | | `--nana-alert-border` | — | Custom border colour | ## CSS Parts | Part | Description | |---|---| | `base` | The alert container | | `icon` | The leading status icon | | `title` | The alert title | | `message` | The alert message body | | `actions` | The action buttons container | | `close-button` | The dismiss button | ## Related components ## Storybook See every state and prop interactively in Storybook: https://storybook.nanatec.co.ke/?path=/docs/components-alert--docs --- # Animated Icon > Source: https://design.nanatec.co.ke/components/animated-icon/ > A motion wrapper around Icon. It renders a real `` — inheriting the entire built-in glyph set, the shared icon registry and the accessibility wiring — and layers a CSS-driven animation on top, started by a trigger. A motion wrapper around Icon. It renders a real `` — inheriting the entire built-in glyph set, the shared icon registry and the accessibility wiring — and layers a CSS-driven animation on top, started by a trigger. Because it composes the existing Icon component, any name you can render with `` — including glyphs you register yourself — works here too. It also honours `prefers-reduced-motion`: looping motion is suspended, and deliberate hover/click/manual motion is slowed. ## Preview ```html ``` ## Installation ```bash npm install @nana-tec/ui-components ``` ## Import ```js import "@nana-tec/ui-components/animated-icon"; ``` ## Basic usage ```html ``` ## Animations Ten built-in presets. Looping here so the gallery is self-demonstrating. ```html ``` ## Triggers Control when the animation runs. ```html ``` ```html ``` ## Programmatic control With `trigger="manual"` you drive motion from JavaScript using `play()`, `pause()` and `toggle()`, and react to the `nana-animation-start` / `nana-animation-end` events. ```ts const el = document.getElementById("loader"); el.play(); // start (restarts cleanly if already running) el.pause(); // stop and reset to the resting frame el.toggle(); // play if paused, pause if playing el.addEventListener("nana-animation-start", () => console.log("started")); el.addEventListener("nana-animation-end", () => console.log("one cycle done")); ``` ## Customization Six ways to make it yours — from a quick colour swap to a fully bespoke animation. ### 1. Colour & size Colour follows `currentColor`, so set `color`. Size via the `size` preset or any `font-size`. ```html ``` ```html ``` ### 2. Speed & duration Pick a preset with `speed`, or set an exact duration with `--nana-animated-icon-duration`. ```html ``` ```html ``` ### 3. Your own glyphs It shares the Icon registry — register a glyph once and animate it like any built-in. ```ts import { registerIcons } from "@nana-tec/ui-components"; // Same registry the built-in icons use — register once, animate anywhere. registerIcons({ rocket: { viewBox: "0 0 24 24", paths: ["M12 2C8 6 8 10 8 14l4 4 4-4c0-4 0-8-4-12z"] }, }); ``` ```html ``` ### 4. Inline SVG No registration needed for a one-off — drop SVG into the default slot. ```html ``` ### 5. Bespoke motion Need a motion that isn't built in? Define your own `@keyframes` and apply them to the exposed `::part(icon)`. ```html ``` ```css @keyframes swing { 20% { transform: rotate(15deg); } 40% { transform: rotate(-10deg); } 60% { transform: rotate(5deg); } 80% { transform: rotate(-5deg); } 100% { transform: rotate(0deg); } } .bell::part(icon) { animation: swing 1s ease-in-out infinite; transform-origin: top center; } ``` ### 6. Drop into other components It's just an inline element that inherits colour — slot it into buttons, menus, alerts, anywhere. ```html Sync ``` ## Accessibility Pass `label` for a meaningful icon — it forwards to the inner icon's `aria-label`. Leave it empty for decorative icons, which are marked `aria-hidden`. `prefers-reduced-motion` is honoured automatically: loop motion is suspended, and deliberate hover/click/manual motion is slowed to a calm 2s. ## API ## Methods | Method | Description | |---|---| | `play()` | Start the animation; restarts cleanly if already running. | | `pause()` | Stop and reset to the resting frame. | | `toggle()` | Play if paused, pause if playing. | ## Events | Event | Description | |---|---| | `nana-animation-start` | Fired when a play cycle begins. | | `nana-animation-end` | Fired when a one-shot (click/manual) cycle ends. | ## CSS custom properties & parts | Name | Kind | Description | |---|---|---| | `--nana-animated-icon-duration` | custom property | Override the animation duration | | `icon` | `::part` | The composed `` — target it to apply a fully custom animation | | `(default)` | slot | Custom SVG content, used when `name` is not set | ## Related components ## Storybook See every state and prop interactively in Storybook: https://storybook.nanatec.co.ke/?path=/docs/components-animated-icon--docs --- # Badge > Source: https://design.nanatec.co.ke/components/badge/ > A small status indicator label with clean, modern design. A small status indicator label with clean, modern design. ## Preview ```html New ``` ## Installation ```bash npm install @nana-tec/ui-components ``` ## Import ```js import "@nana-tec/ui-components/badge"; ``` ## Basic usage ```html New ``` ## Variants ```html Primary Success Warning Danger Info Neutral ``` ## API ## Events | Event | Type | Description | |---|---|---| | `remove` | `CustomEvent` | — | ## Slots | Slot | Description | |---|---| | `(default)` | Badge text content | ## CSS Variables | Variable | Default | Description | |---|---|---| | `--nana-badge-bg` | — | Custom background color | | `--nana-badge-color` | — | Custom text color | | `--nana-badge-border` | — | Custom border color | ## CSS Parts | Part | Description | |---|---| | `badge` | The badge label | | `remove-button` | The remove button (when `removable`) | ## Related components ## Storybook See every state and prop interactively in Storybook: https://storybook.nanatec.co.ke/?path=/docs/components-badge--docs --- # Breadcrumb > Source: https://design.nanatec.co.ke/components/breadcrumb/ > A navigation trail showing the user's location in a hierarchy. Compose it from `nana-breadcrumb-item` children; the last item is usually `current`. One element covers the common professional patterns through orthogonal attributes: - **Standard / Chevron / Path** — `separator` (`slash` · `chevron` · `arrow` · `dot`, or any custom glyph) and `variant="path"`. - **Pill · Card · Step** — `variant`. - **Truncated / Dropdown** — `max-items` collapses the middle into a `…`, either inline (`collapse="expand"`) or into a menu (`collapse="dropdown"`). - **Mobile compact / back-nav** — `responsive` collapses to `← Parent` below `compact-width`. - **Underlined** — `underline` emphasises the current page (composes with any variant). A navigation trail showing the user's location in a hierarchy. Compose it from `nana-breadcrumb-item` children; the last item is usually `current`. One element covers the common professional patterns through orthogonal attributes: - **Standard / Chevron / Path** — `separator` (`slash` · `chevron` · `arrow` · `dot`, or any custom glyph) and `variant="path"`. - **Pill · Card · Step** — `variant`. - **Truncated / Dropdown** — `max-items` collapses the middle into a `…`, either inline (`collapse="expand"`) or into a menu (`collapse="dropdown"`). - **Mobile compact / back-nav** — `responsive` collapses to `← Parent` below `compact-width`. - **Underlined** — `underline` emphasises the current page (composes with any variant). ## Preview ```html Home Components Breadcrumb ``` ## Installation ```bash npm install @nana-tec/ui-components ``` ## Import ```js import "@nana-tec/ui-components/breadcrumb"; ``` ## Basic usage ```html Home Components Breadcrumb ``` ## Item states `current` marks the active page; `disabled` dims a crumb. ```html Home Restricted Current ``` ## Variants The `variant` attribute restyles the trail — `default`, `path`, `pill`, `card`, or `step`. ```html Home Library Data Cart Shipping Payment Home Docs Guide ``` ## API ## Events | Event | Type | Description | |---|---|---| | `nana-expand` | `CustomEvent` | Fired when a truncated trail is expanded inline | ## Slots | Slot | Description | |---|---| | `(default)` | One or more `nana-breadcrumb-item` elements | ## CSS Variables | Variable | Default | Description | |---|---|---| | `--nana-breadcrumb-separator` | — | Separator glyph between items | | `--nana-breadcrumb-gap` | — | Space around each separator | ## CSS Parts | Part | Description | |---|---| | `base` | The `