Components
The @azmr/ui component library, built on Base UI primitives and the Azmara design tokens.
View as Markdown for coding assistants, or see llms.txt.
@azmr/ui is a component library for React 18 and 19, built on Base UI primitives, styled with Tailwind v4 and a small set of design tokens. Every component page has live demos you can preview in light and dark and at each density, the source of each demo, a props table generated from the TypeScript types, and an accessibility section with the keyboard map.
Using Vue, Svelte or another framework?
The components are React-only today. These parts have no React dependency:
@azmr/core (signals), @azmr/query,
@azmr/security, the database packages
(@azmr/db and
@azmr/db-core-interface), and the design tokens in
@azmr/ui/tokens.css, which are plain CSS for any Tailwind v4 project.
All components
Grouped by purpose. Each badge shows the component's maturity: stable, new or beta.
30 components
Layout
Inputs
ButtonStable
Triggers an action. Six variants, density-aware sizes, a loading state that keeps keyboard focus, and an icon-only form the types force you to name.
FieldNew
A label, description, error and required marker around any control, with the ids and aria attributes wired for you.
Field arrayNew
FieldArray repeats a group of fields, such as invoice lines, contacts or addresses, with add, remove and reorder by drag or keyboard, minimum and maximum rows, an empty state and totals.
Form layoutNew
Fieldset, FormSection and ErrorSummary structure long forms and help people fix every error after a failed submit.
InputStable
Text inputs and a textarea whose ref is the real element, so react-hook-form works without a Controller.
Input groupNew
Text, icons and buttons inside an input's border, such as a currency, a unit, a search icon or a clear or copy button.
Number fieldNew
NumberField and MoneyField format numbers and currency for the locale, clamp to min and max, and report real numbers, never formatted strings.
Password inputNew
A password field with a show/hide toggle, and an optional strength meter and requirement checklist for new passwords.
SplitButtonStable
A primary action with a menu of related actions attached. Button plus DropdownMenu.
ToggleStable
Toggle and ToggleGroup. A button that stays pressed, and a group of them that acts as one control with arrow-key navigation. Built on Base UI.
Data display
AvatarStable
A person or entity as an image with initials as the fallback, plus a group with a labelled overflow count. Built on Base UI.
DisclosureStable
Accordion, Collapsible and Tabs. Show and hide content with the keyboard maps users expect. Built on Base UI.
DisplayStable
Card, Badge, Alert, Skeleton and EmptyState. Server Components with status colours checked for contrast in both themes.
IconStable
Renders Lucide, Tabler or your own SVG with consistent size, stroke, motion and accessibility. A Server Component.
TableStable
A semantic, non-interactive table with a caption, sticky header, striping and a named scroll region. Server-safe.
TypographyStable
A type scale where the variant picks the semantic element, with Heading, Text, Link, Code and Kbd. All Server Components.
Feedback
LoadingStable
Spinners, loading messages, logo loaders, overlays for refetching data and a top-of-page loading bar. The message and spinner are Server Components and fine in loading.tsx.
ProgressStable
A linear or circular progress indicator with a required name, a determinate and an indeterminate state, and tones that stay visible against the track.
SpinnerStable
An indeterminate progress indicator that is a Server Component and keeps spinning under reduced motion.
State viewStable
One layout for a region's loading, empty and error states, and an error boundary that reports errors, recovers and never shows error details to users.
ToastStable
Short notifications raised from anywhere with toast.success(), toast.error() and toast.promise(). Stacked, pausable, swipeable and announced to screen readers. Built on Base UI.
Overlays
FloatingStable
Tooltip, Popover and HoverCard. Surfaces anchored to a trigger, collision-aware, portalled, and animated with the motion tokens. Built on Base UI.
MenuStable
DropdownMenu and ContextMenu. Menus of actions with items, checkbox and radio items, groups and submenus. Built on Base UI.
ModalStable
Dialog, AlertDialog and Drawer. Surfaces that take over the screen, with a focus trap, an inert page, scroll lock and focus return. Built on Base UI.
Navigation
BreadcrumbStable
A trail showing where you are and the way back up. Built from parts or from data, collapsible, router-friendly. Server-safe.
PaginationStable
A page control that is real links on the server or buttons for client state, with a stable-width page range the data grid reuses. Server-safe.
StepperStable
Shows where someone is in a fixed sequence of steps. A status display with each state said in text, horizontal or vertical. Server-safe.
Utils
Set up
/* global.css */
@import "tailwindcss";
@import "@azmr/ui/styles.css";
@import "@azmr/ui/classes.css"; /* or one list per component: @azmr/ui/classes/button.css */Use @azmr/ui/tokens.css instead of styles.css if the app already has global styles. Importing only the class lists for the components you use keeps the CSS small; Tailwind CSS setup explains them. See the package page for the tokens, theming and locale.
Or copy the source with the shadcn CLI
If you would rather own the code than import a package, the same components are published to a shadcn-compatible registry. Add the namespace to your components.json:
{
"registries": {
"@azmr": "https://platform.azmara.io/r/{name}.json"
}
}Then, in a project that has run npx shadcn@latest init:
npx shadcn@latest add @azmr/buttonThis copies button.tsx and the components it needs (spinner.tsx) into components/ui, installs @base-ui/react and class-variance-authority, and adds a small tokens item to your globals.css: density, motion and elevation tokens, plus colours a standard shadcn setup lacks (--destructive-foreground, --success, --warning, --info). It never changes the tokens you already have, so your palette stays yours. The copied source is generated from the package source with only the import paths rewritten, so it behaves identically. Available now: button, spinner, tokens; more arrive with each component. The shadcn CLI guide has the details.
What every component guarantees
- Tokens only. No raw colours; a test enforces it, so a theme change reaches every component.
- Accessible by default. Each component is tested with axe, by keyboard, and under reduced motion.
- Server-safe where it can be. Stateless components such as
SpinnerandIconare Server Components; the rest carry"use client"on their own entry only. - Tree-shakeable, with budgets. Each entry has a size budget checked in CI.
classNamemerges last, andrefis the real DOM element.