Headless React components for Swiss UI design system.
npm install @swiss-ui/reactyarn add @swiss-ui/reactpnpm add @swiss-ui/reactAll components are exported from the root entry with no default styles attached. You provide all styling yourself.
import { Button, Input, Modal } from '@swiss-ui/react'You can also import individual components from their own sub-paths to enable more granular code splitting:
import { Button } from '@swiss-ui/react/button'
import { Input } from '@swiss-ui/react/input'The @swiss-ui/react/styled entry re-exports every component with a swiss-* CSS class pre-applied. Apply the swiss-ui CSS token sheet and component stylesheet alongside this entry to get themed components out of the box.
import { Button, Input, Stack } from '@swiss-ui/react/styled'| Component | Description | Key props |
|---|---|---|
| Box | Generic polymorphic container | as |
| Text | Inline or block text | as, size, weight, align, truncate |
| Container | Centered max-width wrapper | size (sm / md / lg / xl / full) |
| Stack | Vertical flex container | gap, align, justify |
| Grid | CSS grid container | cols, gap, align |
| GridItem | Grid child with span support | colSpan, rowSpan |
| Heading | Semantic heading h1-h6 | level, size, weight, align, as |
| Button | Polymorphic action trigger | variant, size, loading, leftIcon, rightIcon, as |
| Input | Text input with addons | size, invalid, leftAddon, rightAddon, describedBy |
| Textarea | Multi-line text input | size, invalid, resize, autoResize, describedBy |
| Select | Native select element | size, invalid, placeholder, describedBy |
| Checkbox | Checkbox with indeterminate state | indeterminate, invalid |
| Radio | Radio button | invalid |
| RadioGroup | Radio group context provider | name, value, onChange, orientation |
| Switch | Toggle switch | checked, defaultChecked, onChange |
| Badge | Inline status indicator | variant, color |
| Alert | Contextual message block | variant, icon, title, description, actions |
| Spinner | Loading indicator | size, color, label |
| Modal | Accessible dialog | isOpen, onClose |
| ModalOverlay | Modal backdrop | |
| ModalContent | Dialog container with focus trap | |
| ModalHeader | Header slot | |
| ModalBody | Body slot, provides aria-describedby | |
| ModalFooter | Footer slot | |
| ModalCloseButton | Pre-wired close button | |
| Tooltip | Hover/focus tooltip | content, placement, delay, disabled |
| Dropdown | Menu dropdown container | |
| DropdownTrigger | Menu trigger button | |
| DropdownContent | Menu panel | |
| DropdownItem | Menu action item | disabled |
| DropdownSeparator | Visual separator | |
| DropdownLabel | Non-interactive group label |
The following accessibility features are implemented out of the box:
- All interactive elements use native HTML elements or appropriate ARIA roles.
- Button supports polymorphic rendering; when rendered as a non-button element,
aria-disabledis set instead of thedisabledattribute. - Input, Textarea, and Select expose
aria-invalidandaria-describedbyprops. - Checkbox supports the
indeterminatestate via the DOM property. - RadioGroup renders a
radiogrouprole; Radio buttons share a name from context. - Switch uses
role="switch"witharia-checked. - Alert maps
infoandsuccessvariants torole="status"andwarning/errortorole="alert". - Spinner exposes
role="status"with a configurablearia-label. - Modal locks body scroll, traps focus inside ModalContent, and closes on Escape.
- Tooltip renders
role="tooltip"inside a portal and links to the trigger viaaria-describedby. - Dropdown follows the ARIA menu button pattern:
aria-haspopup,aria-expanded,aria-controls, and full keyboard navigation (ArrowUp / ArrowDown / Home / End / Escape / Tab).
Components use CSS custom properties for all design tokens. Override them on :root or any ancestor element:
:root {
--swiss-font-size-md: 1rem;
--swiss-spacing-4: 1rem;
--swiss-color-primary: #0055cc;
}The data-variant, data-size, data-color, and data-component attributes on every element give you CSS attribute selectors without any class naming convention:
[data-component="button"][data-variant="solid"] {
background: var(--swiss-color-primary);
}All portal-based components (Modal, Tooltip, Dropdown) guard against document access with typeof document !== 'undefined' checks, making them safe to render in server environments. They hydrate correctly on the client without any additional configuration.