React Components
@vellira-ui/react contains the React DOM implementation of Vellira.
It owns DOM structure, CSS modules, browser events, accessibility ids, and web overlay behavior while reusing shared tokens, types, and core hooks.
Installation
pnpm add @vellira-ui/reactImport the stylesheet once in your application entry point.
import '@vellira-ui/react/styles';Quick Example
import { Button, Input, Select, Tabs } from '@vellira-ui/react';
import { useState } from 'react';
export function AccountPanel() {
const [displayName, setDisplayName] = useState('');
const [role, setRole] = useState<string | null>('editor');
return (
<Tabs defaultValue='profile'>
<Tabs.List>
<Tabs.Trigger value='profile'>Profile</Tabs.Trigger>
<Tabs.Trigger value='security'>Security</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value='profile'>
<Input
label='Display name'
value={displayName}
onValueChange={setDisplayName}
placeholder='Roman Bakurov'
/>
<Select
label='Role'
value={role}
onValueChange={setRole}
placeholder='Choose role'
>
<Select.Item value='admin' label='Admin' />
<Select.Item value='editor' label='Editor' />
<Select.Item value='viewer' label='Viewer' />
</Select>
<Button
color='primary'
appearance='solid'
onClick={() => saveAccount({ displayName, role })}
>
Save changes
</Button>
</Tabs.Content>
<Tabs.Content value='security'>Security settings</Tabs.Content>
</Tabs>
);
}Component Library
Available Components
Every public component exports TypeScript props from the package root. The generated reference lives in packages/react/API.md.
| Component | Core API | State model |
|---|---|---|
Button | appearance, color, shape, icons, loading, links, DOM props | disabled or loading |
Checkbox | checked, defaultChecked, onCheckedChange, label, description, error, indeterminate | controlled or uncontrolled |
Input | label, value, type, size, variant, validation, masks, formatting | controlled or uncontrolled |
FormField | label, description, messages, error, required, disabled, children | field composition |
Radio | value, label, checked state, size, color, error, custom icon | controlled or uncontrolled |
RadioGroup | name, value, orientation, size, color, children | controlled or uncontrolled |
Select | value, options, compound items, search, multiple selection, open state | controlled or uncontrolled |
Dropdown | compound menu sections, open state, placement, color, command behavior | controlled or uncontrolled |
Tabs | stable values, orientation, variants, mounting policy | controlled or uncontrolled |
Popover | open state, positioning, alignment, offsets, compound sections | controlled or uncontrolled |
Tooltip | open state, placement, delay, trigger and content | controlled or uncontrolled |
Portal | children, direct container, PortalProvider | render target |
Modal | open state, outside and Escape dismissal, compound dialog sections | controlled or uncontrolled |
ThemeProvider | active theme, default theme, theme updates | controlled or uncontrolled |
API Conventions
Controlled And Uncontrolled State
Components with user-owned state support controlled values.
import { Checkbox, Select } from '@vellira-ui/react';
import { useState } from 'react';
export function ControlledSettings() {
const [enabled, setEnabled] = useState(false);
const [role, setRole] = useState<string | null>('editor');
return (
<>
<Checkbox
checked={enabled}
onCheckedChange={setEnabled}
label='Enable notifications'
/>
<Select label='Role' value={role} onValueChange={setRole}>
<Select.Item value='admin' label='Admin' />
<Select.Item value='editor' label='Editor' />
<Select.Item value='viewer' label='Viewer' />
</Select>
</>
);
}Use default props when the component can own its initial state.
import { Checkbox, Radio, RadioGroup, Tabs } from '@vellira-ui/react';
export function UncontrolledPreferences() {
return (
<>
<Checkbox defaultChecked label='Remember this device' />
<RadioGroup name='theme' label='Theme' defaultValue='system'>
<Radio value='system' label='System' />
<Radio value='light' label='Light' />
<Radio value='dark' label='Dark' />
</RadioGroup>
<Tabs defaultValue='profile'>
<Tabs.List>
<Tabs.Trigger value='profile'>Profile</Tabs.Trigger>
<Tabs.Trigger value='security'>Security</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value='profile'>Profile settings</Tabs.Content>
<Tabs.Content value='security'>Security settings</Tabs.Content>
</Tabs>
</>
);
}DOM And Browser Props
Web components use browser-native props and events.
<Button className='save-button' aria-label='Save project' onClick={saveProject}>
Save
</Button>Use onClick, className, and standard ARIA attributes in the React package. React Native uses platform-specific props such as onPress, style, and accessibilityLabel.
Compound APIs
Overlay and navigation components expose compound sections.
<Popover>
<Popover.Trigger asChild>
<Button>Open details</Button>
</Popover.Trigger>
<Portal>
<Popover.Content>
<Popover.Title>Project details</Popover.Title>
<Popover.Description>
Review metadata for the current project.
</Popover.Description>
<Popover.Close />
</Popover.Content>
</Portal>
</Popover>Compound APIs keep semantic structure explicit while allowing custom layout and composition.
Validation
Validation rules remain in the application.
const emailError = email.includes('@') ? undefined : 'Enter a valid email.';
<Input
label='Work email'
type='email'
value={email}
onValueChange={setEmail}
error={emailError}
/>;Components render invalid state and connect supporting text, but they do not decide whether application data is valid.
Accessibility
Vellira Web components implement browser-specific accessibility behavior.
- Use
aria-labeloraria-labelledbyfor icon-only or visually unlabeled controls. - Input, Checkbox, Select, and RadioGroup connect labels, descriptions, required state, disabled state, and errors.
- FormField provides field layout for custom controls; the child still owns its ARIA attributes and interaction state.
- RadioGroup, Tabs, menus, tooltips, popovers, and modals provide role-appropriate keyboard behavior.
- Portal changes DOM placement but does not add semantics, labels, focus management, or dismissal behavior.
- Consumers remain responsible for meaningful copy, validation timing, post-submit focus, and product-specific announcements.
Test important workflows with keyboard navigation and browser screen readers.
Theming
Import the stylesheet once for base component styles.
import '@vellira-ui/react/styles';
import { ThemeProvider } from '@vellira-ui/react';
export function Root() {
return (
<ThemeProvider defaultTheme='light'>
<App />
</ThemeProvider>
);
}Theme values come from @vellira-ui/tokens and are exposed through CSS variables.
.account-shell {
color: var(--text-primary);
background: var(--surface-default);
border: 1px solid var(--border-default);
}ThemeProvider supports light, dark, and high-contrast themes, plus controlled application-level switching.
Storybook
Explore interactive states, accessibility behavior, and component composition in Storybook.
Development
pnpm --filter @vellira-ui/react typecheck
pnpm --filter @vellira-ui/react build
pnpm --filter @vellira-ui/react test
pnpm --filter @vellira-ui/react-storybook devBrowser Support
Vellira targets modern evergreen browsers supported by React.
The package relies on standard browser APIs and does not require additional polyfills in modern environments.