Repo

Usage approaches

Plain CSS classes

Every component is usable with any HTML element by applying the right class names. This works in any framework or with no framework at all.

<button class="zui-button zui-button-variant-outline">Click me</button>

React

React wrappers accept typed props instead of class strings. Import from @mrmartineau/zui/react.

import { Button } from '@mrmartineau/zui/react'

<Button variant="outline">Click me</Button>

Astro

Astro wrappers work the same way. Import from @mrmartineau/zui/astro.

---
import { Button } from '@mrmartineau/zui/astro'
---

<Button variant="outline">Click me</Button>

Solid

Solid wrappers use class instead of className. Import from @mrmartineau/zui/solid.

import { Button } from '@mrmartineau/zui/solid'

<Button variant="outline">Click me</Button>

Svelte

Svelte wrappers are Svelte 5 SFCs that use runes and snippets. Import from @mrmartineau/zui/svelte.

<script lang="ts">
  import { Button } from '@mrmartineau/zui/svelte'
</script>

<Button variant="outline">Click me</Button>

Vue

Vue wrappers are SFC components. Import from @mrmartineau/zui/vue.

<template>
  <Button variant="outline">Click me</Button>
</template>

<script setup>
import { Button } from '@mrmartineau/zui/vue'
</script>

See Using with React, Using with Astro, Using with Solid, Using with Svelte, and Using with Vue for setup instructions.

CSS layer

Component styles live in the zui.components layer, below zui.utilities. This means utility classes always override component styles when both apply, without needing !important.

@layer zui.base, zui.components, zui.utilities;

CSS custom properties

Every component has CSS custom properties (variables) for its colours, radius, padding, font sizes, shadow, and more. Each component page lists them with their defaults.

Set them on :root to change every instance, on a wrapper to change one part of the page, or in a style attribute to change one element:

:root {
  --zui-card-radius: var(--radius-sm);
  --zui-card-padding: var(--space-lg);
}

.my-sidebar {
  --zui-btn-radius: 0;
}
<div class="zui-card" style="--zui-card-padding: var(--space-lg);">…</div>

See Component custom properties in the theming guide for how variants work, and what to avoid. This live CodePen example shows three cards side by side: one with default styles, one customised via inline style attributes, and one themed via scoped CSS classes.

Components

Accordion

A stacked set of disclosure panels using the native details/summary elements.

App Shell

Application layout primitive — collapsible sidebar, top header, scrollable main content.

Avatar

A circular image with a fallback for when the image fails to load or no source is provided.

Badge

Small status indicators and labels. Supports colour variants and size modifiers.

Button

A flexible button with five variants, three accent colours, five sizes, four shapes, and icon-only mode.

Card

A container for grouping related content, with optional header, body, and footer sections.

Checkbox

Custom-styled checkboxes with list layout.

Collapsible

A single disclosure widget using the native details/summary elements.

Dialog

Modal dialogs built on the native dialog element with a styled backdrop. Requires minimal JavaScript to open.

Field

Composable form-field primitives for consistent spacing, descriptions, errors, legends and orientation.

Flex

A layout component for flexbox-based arrangements. Controls direction, alignment, justification, wrapping, and gap spacing via props.

Input

A styled text input for forms.

Kbd

Keyboard key hints. Render a single key with Kbd, or combine keys into a shortcut with KbdGroup.

Label

Form labels with optional required indicator and description text.

Menu

A strict action menu with managed focus, keyboard navigation, and menu button semantics.

Number Field

A number input with decrease and increase buttons on each side.

Password Input

A password field with a button that shows or hides the password.

Popover

Floating panels built on the native HTML Popover API and CSS Anchor Positioning. No JavaScript required.

Radio

Custom-styled radio buttons with list layout.

Select

A styled native select dropdown.

Table

A styled table for displaying tabular data.

Tabs

Accessible tabs with horizontal and vertical orientations.

Textarea

A multi-line text input with auto-sizing via field-sizing: content.

Tooltip

Small contextual labels on hover or focus, using the Popover API and CSS Anchor Positioning.

Theme

Copy this CSS to your project: