Skip to content

React Components

Pre-built React components that encapsulate the design system styles.

Installation

Import components from the package:

import {
  NeuCard,
  NeuButton,
  NeuInput,
  NeuSelect,
  NeuCheckbox,
  NeuRadio,
  NeuToggle,
  NeuTabNav,
  NeuAlert,
  Button,
  Pill,
  StatusPill,
  StatusDot,
  IconActionButton,
  InfraCard,
  DetailScreenHeader,
  GraphViewLayout,
  ThemeLifecyclePill,
  ThemeVersionPill,
} from '@bast/shared-styles/components';

NeuCard

Neumorphic card component with multiple variants.

Props

Prop Type Default Description
variant 'raised' \| 'inset' \| 'flat' \| 'glow' 'raised' Visual variant
interactive boolean false Enable hover effect
radius 'small' \| 'default' \| 'large' 'default' Border radius
className string '' Additional classes
children ReactNode - Card content

Examples

// Basic raised card
<NeuCard className="p-4">
  <h3>Card Title</h3>
  <p>Card content</p>
</NeuCard>

// Interactive card
<NeuCard variant="raised" interactive className="p-4">
  <h3>Click me</h3>
</NeuCard>

// Inset card
<NeuCard variant="inset" className="p-4">
  <p>Recessed content</p>
</NeuCard>

// AI glow effect
<NeuCard variant="glow" className="p-4">
  <p>AI-powered feature</p>
</NeuCard>

GraphViewLayout

Shared two-panel graph shell used by admin graph screens.

Props

Prop Type Default Description
treePanel ReactNode - Left graph tree content (required)
detailPanel ReactNode - Right detail panel content (required)
minHeightClass string 'min-h-[400px]' Left panel minimum height utility class
detailWidthClass string 'w-80' Right panel width utility class
detailPanelRole AriaRole - Optional semantic role for detail panel
detailPanelAriaLabel string - Optional aria-label for detail panel

Example

import { GraphViewLayout } from '@bast/shared-styles/components';

<GraphViewLayout
  minHeightClass="min-h-[400px]"
  detailWidthClass="w-[380px]"
  detailPanelRole="complementary"
  detailPanelAriaLabel="Graph node details"
  treePanel={<div>Tree content</div>}
  detailPanel={<div>Detail content</div>}
/>

NeuButton

Button component with built-in variants and states.

Props

Prop Type Default Description
variant 'primary' \| 'success' \| 'warning' \| 'error' 'primary' Color variant
size 'small' \| 'default' \| 'large' 'default' Button size
fullWidth boolean false Full width button
icon ReactNode - Icon before label
disabled boolean false Disabled state

Examples

// Basic button
<NeuButton>Click me</NeuButton>

// Success button with icon
<NeuButton variant="success" icon={<CheckIcon />}>
  Save Changes
</NeuButton>

// Large error button
<NeuButton variant="error" size="large" fullWidth>
  Delete Account
</NeuButton>

// Disabled button
<NeuButton disabled>Disabled</NeuButton>

Action Button Groups (Design System Rule)

When rendering a group of action buttons (Save/Cancel, Confirm/Dismiss, etc.), follow these rules:

  1. Right-align the button group to its container (justify-end)
  2. Pin to bottom of the container/card (mt-auto, with a border-t separator)
  3. Primary action rightmost — Save, Confirm, Submit go on the far right
  4. Secondary/cancel action left — Cancel, Dismiss go to the left of the primary action

This applies universally to all edit panels, modals, forms, and dialogs.

// Correct — Cancel left, Save right, right-aligned, pinned to bottom
<div className="mt-auto flex items-center justify-end gap-2 border-t border-[var(--border)] pt-4">
  <NeuButton size="sm" variant="secondary" onClick={onCancel}>Cancel</NeuButton>
  <NeuButton size="sm" variant="primary" onClick={onSave}>Save</NeuButton>
</div>

// Also correct for destructive actions — Cancel left, Delete right
<div className="mt-auto flex items-center justify-end gap-2 border-t border-[var(--border)] pt-4">
  <NeuButton variant="secondary" onClick={onCancel}>Cancel</NeuButton>
  <NeuButton variant="error" onClick={onDelete}>Delete</NeuButton>
</div>

NeuInput

Text input with label, helper text, and error states.

Props

Prop Type Default Description
label string - Input label
helperText string - Helper text below input
error string - Error message (triggers error state)
size 'small' \| 'default' \| 'large' 'default' Input size
wrapperClassName string '' Wrapper element classes

Examples

// Basic input
<NeuInput placeholder="Enter text..." />

// Input with label and helper
<NeuInput
  label="Email"
  placeholder="you@example.com"
  helperText="We'll never share your email"
/>

// Error state
<NeuInput
  label="Password"
  type="password"
  error="Password must be at least 8 characters"
/>

// Controlled input
const [value, setValue] = useState('');
<NeuInput
  value={value}
  onChange={(e) => setValue(e.target.value)}
/>

NeuSelect

Raised dropdown select component with a styled popup menu.

Props

Prop Type Default Description
label string - Select label
helperText string - Helper text
error string - Error message
size 'small' \| 'default' \| 'large' 'default' Select size
onValueChange (value: string) => void - Direct value change callback
children ReactNode - Option elements

Examples

// Basic select
<NeuSelect>
  <option>Select an option</option>
  <option value="1">Option 1</option>
  <option value="2">Option 2</option>
</NeuSelect>

// With label
<NeuSelect label="Country">
  <option value="">Select country</option>
  <option value="us">United States</option>
  <option value="ca">Canada</option>
</NeuSelect>

// Error state
<NeuSelect
  label="Priority"
  error="Please select a priority level"
  onValueChange={(value) => console.log(value)}
>
  <option value="">Select priority</option>
  <option value="low">Low</option>
  <option value="high">High</option>
</NeuSelect>

NeuCheckbox

Styled checkbox component.

Props

Prop Type Default Description
label string - Checkbox label
disabled boolean false Disabled state
wrapperClassName string '' Wrapper classes

Examples

// Basic checkbox
<NeuCheckbox label="Accept terms and conditions" />

// Default checked
<NeuCheckbox label="Remember me" defaultChecked />

// Disabled
<NeuCheckbox label="Unavailable option" disabled />

// Controlled
const [checked, setChecked] = useState(false);
<NeuCheckbox
  label="Enable feature"
  checked={checked}
  onChange={(e) => setChecked(e.target.checked)}
/>

NeuToggle

Toggle/switch component.

Props

Prop Type Default Description
label string - Toggle label
labelPosition 'left' \| 'right' 'right' Label position
disabled boolean false Disabled state

Examples

// Basic toggle
<NeuToggle label="Enable notifications" />

// Label on left
<NeuToggle label="Dark mode" labelPosition="left" />

// Controlled
const [enabled, setEnabled] = useState(false);
<NeuToggle
  label="Feature flag"
  checked={enabled}
  onChange={(e) => setEnabled(e.target.checked)}
/>

NeuAlert

Alert/notification component.

Props

Prop Type Default Description
variant 'success' \| 'info' \| 'warning' \| 'error' - Alert type (required)
title string - Alert title (required)
message string - Alert message
icon ReactNode - Custom icon
dismissible boolean false Show close button
onDismiss () => void - Close callback

Examples

// Success alert
<NeuAlert
  variant="success"
  title="Success!"
  message="Your changes have been saved."
/>

// Error alert
<NeuAlert
  variant="error"
  title="Error"
  message="Something went wrong. Please try again."
/>

// Dismissible alert
const [show, setShow] = useState(true);
{show && (
  <NeuAlert
    variant="info"
    title="Notice"
    message="This is an important message."
    dismissible
    onDismiss={() => setShow(false)}
  />
)}

// Custom icon
<NeuAlert
  variant="warning"
  title="Heads up"
  message="This action cannot be undone."
  icon={<CustomWarningIcon />}
/>

TypeScript Support

All components export their prop types:

import type {
  NeuCardProps,
  NeuButtonProps,
  NeuInputProps,
  NeuSelectProps,
  NeuCheckboxProps,
  NeuToggleProps,
  NeuAlertProps,
} from '@bast/shared-styles/components';

Pill

Base pill/chip primitive for non-status labels with tokenized sizing.

Props

Prop Type Default Description
size 'sm' \| 'md' \| 'lg' 'sm' Size token (sm = 10px baseline)
label string - Optional text label
icon React.ElementType - Optional icon component
iconColor string - Optional icon color override
className string - Color/background/border classes

Example

import { Pill } from '@bast/shared-styles/components';

<Pill size="sm" className="bg-[var(--bg-elevated)] text-[var(--text-secondary)]">
  Using defaults
</Pill>

StatusPill

Semantic status pill built on top of Pill and tone tokens.

Props

Prop Type Default Description
tone StatusTone - Semantic tone token
label string - Optional label text
size 'sm' \| 'md' \| 'lg' 'sm' Shared pill size token
emphasis 'solid' \| 'soft' \| 'outline' 'solid' Visual emphasis
variant 'solid' \| 'soft' \| 'outline' - Alias for emphasis (compat)
icon React.ElementType - Optional icon component

Example

import { StatusPill } from '@bast/shared-styles/components';

<StatusPill tone="success" variant="soft">Enabled</StatusPill>

ThemeLifecyclePill

Theme lifecycle status primitive for CAT Builder and version-management screens.

Props

Prop Type Default Description
status 'draft' \| 'pending' \| 'active' \| 'archived' - Lifecycle status value
size 'sm' \| 'md' \| 'lg' 'md' Shared pill size token
labelOverride string - Optional custom display label

Example

import { ThemeLifecyclePill } from '@bast/shared-styles/components';

<ThemeLifecyclePill status="active" />

ThemeVersionPill

Version label primitive for versioned table/list rows.

Props

Prop Type Default Description
version number \| string - Version identifier
size 'sm' \| 'md' \| 'lg' 'md' Shared pill size token
prefix string 'v' Prefix for rendered value

Example

import { ThemeVersionPill } from '@bast/shared-styles/components';

<ThemeVersionPill version={3} />

IconActionButton

Compact circular icon button for dense row actions in management tables.

Props

Prop Type Default Description
icon ReactNode - Icon element to render
tone 'neutral' \| 'success' \| 'warning' \| 'danger' 'neutral' Semantic action tone
disabled boolean false Disable interaction

Example

import { IconActionButton } from '@bast/shared-styles/components';
import { Pencil } from 'lucide-react';

<IconActionButton icon={<Pencil className="h-4 w-4" />} aria-label="Edit theme" />

Accessibility

All components are built with accessibility in mind:

  • Proper ARIA attributes
  • Keyboard navigation support
  • Focus states with visible outlines
  • Screen reader compatible labels
  • Color contrast compliant (WCAG 2.1)

Combining Components

import { NeuCard, NeuButton, NeuInput, NeuAlert } from '@bast/shared-styles/components';

function LoginForm() {
  const [error, setError] = useState<string | null>(null);

  return (
    <NeuCard className="p-6 max-w-md mx-auto">
      <h2 className="text-xl font-medium text-[var(--primary-text)] mb-4">
        Sign In
      </h2>

      {error && (
        <NeuAlert
          variant="error"
          title="Login Failed"
          message={error}
          className="mb-4"
          dismissible
          onDismiss={() => setError(null)}
        />
      )}

      <form className="space-y-4">
        <NeuInput
          label="Email"
          type="email"
          placeholder="you@example.com"
        />

        <NeuInput
          label="Password"
          type="password"
          placeholder="••••••••"
        />

        <NeuButton variant="success" fullWidth type="submit">
          Sign In
        </NeuButton>
      </form>
    </NeuCard>
  );
}

Additional Components (March 2026)

The following components were added or promoted to shared-styles as part of the Tailwind-to-CSS migration. All use CSS classes from src/utilities/*.css — no Tailwind utility classes.

NeuTabNav

Tab bar container for navigation tabs.

<NeuTabNav>
  <button className="neu-tab active">Overview</button>
  <button className="neu-tab">Settings</button>
</NeuTabNav>

StatusDot

Small colored dot indicating status, using the statusTone system.

Prop Type Default Description
tone StatusTone - Color tone from the status tone palette
size 'sm' \| 'md' \| 'lg' 'sm' Dot diameter (8px / 12px / 16px)
<StatusDot tone="success" />
<StatusDot tone="warning" size="md" />

DetailScreenHeader

Sticky header for detail/edit screens with back button, title (optionally as a dropdown switcher), badges, and right-side actions.

Prop Type Default Description
onBack () => void - Navigate back handler
title string - Screen title
dropdownContent ReactNode - If provided, title becomes a dropdown trigger
dropdownAriaLabel string 'Select item' Accessible label for dropdown
badges ReactNode - Status badges next to title
actions ReactNode - Right-side action buttons
<DetailScreenHeader
  onBack={() => navigate(-1)}
  title="Knowledge Base"
  badges={<StatusPill label="Active" tone="success" />}
  actions={<Button variant="neu-secondary">Edit</Button>}
/>

IconActionButton

Small circular icon button with tone variants.

Prop Type Default Description
icon ReactNode - Icon element to render
tone 'neutral' \| 'success' \| 'warning' \| 'danger' 'neutral' Color tone
aria-label string - Required accessible label
<IconActionButton icon={<EditIcon />} tone="neutral" aria-label="Edit" />

CSS-only rule: All shared-styles components use CSS classes from src/utilities/ or inline styles with CSS variable tokens. See packages/shared-styles/CONTRIBUTING.md for details.