Skip to content

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

bash
pnpm add @vellira-ui/react

Import the stylesheet once in your application entry point.

tsx
import '@vellira-ui/react/styles';

Quick Example

tsx
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.

ComponentCore APIState model
Buttonappearance, color, shape, icons, loading, links, DOM propsdisabled or loading
Checkboxchecked, defaultChecked, onCheckedChange, label, description, error, indeterminatecontrolled or uncontrolled
Inputlabel, value, type, size, variant, validation, masks, formattingcontrolled or uncontrolled
FormFieldlabel, description, messages, error, required, disabled, childrenfield composition
Radiovalue, label, checked state, size, color, error, custom iconcontrolled or uncontrolled
RadioGroupname, value, orientation, size, color, childrencontrolled or uncontrolled
Selectvalue, options, compound items, search, multiple selection, open statecontrolled or uncontrolled
Dropdowncompound menu sections, open state, placement, color, command behaviorcontrolled or uncontrolled
Tabsstable values, orientation, variants, mounting policycontrolled or uncontrolled
Popoveropen state, positioning, alignment, offsets, compound sectionscontrolled or uncontrolled
Tooltipopen state, placement, delay, trigger and contentcontrolled or uncontrolled
Portalchildren, direct container, PortalProviderrender target
Modalopen state, outside and Escape dismissal, compound dialog sectionscontrolled or uncontrolled
ThemeProvideractive theme, default theme, theme updatescontrolled or uncontrolled

API Conventions

Controlled And Uncontrolled State

Components with user-owned state support controlled values.

tsx
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.

tsx
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.

tsx
<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.

tsx
<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.

tsx
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-label or aria-labelledby for 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.

tsx
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.

css
.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.

Open Storybook

Development

bash
pnpm --filter @vellira-ui/react typecheck
pnpm --filter @vellira-ui/react build
pnpm --filter @vellira-ui/react test
pnpm --filter @vellira-ui/react-storybook dev

Browser 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.

Built for Vellira Design System.