Design System

Display Atoms

ImportCC

Available via @stackmates/ui-interactive/atoms

Avatar

Compound component for user avatars with image and initials fallback. Built on Radix Avatar.

CNJDSM

AvatarRx / AvatarRxImage / AvatarRxFallback

PropTypeDefaultDescription
classNamestringOverride size/shape via Tailwind classes (default: h-10 w-10 rounded-full)

Installation

typescript
import { AvatarRx, AvatarRxImage, AvatarRxFallback } from '@stackmates/ui-interactive/atoms';

Usage

With image and fallback

tsx
<AvatarRx>
  <AvatarRxImage src="/avatar.png" alt="Jane Doe" />
  <AvatarRxFallback>JD</AvatarRxFallback>
</AvatarRx>

Accessibility

  • AvatarRxImage requires alt text for screen readers
  • AvatarRxFallback displays when image fails to load
  • Built on Radix Avatar primitive with proper aria attributes
Related:

StatusBadge

Status indicator with icon and color mapping. 7 semantic variants for workflow states.

idlependingprocessingsuccesswarningerrorinfo
processing (pulse)smno icon

StatusBadgeProps

PropTypeDefaultDescription
status*'idle' | 'pending' | 'processing' | 'success' | 'warning' | 'error' | 'info'Status variant that determines icon and color
pulsebooleanfalseShow animated pulse dot in top-right corner
showIconbooleantrueShow the status icon
size'sm' | 'md''md'Badge size variant

Installation

typescript
import { StatusBadge } from '@stackmates/ui-interactive/atoms';

Usage

Basic status

tsx
<StatusBadge status="success">Completed</StatusBadge>

With pulse indicator

tsx
<StatusBadge status="processing" pulse>Running</StatusBadge>

Accessibility

  • Uses icon + text (not color alone) to convey status
  • Processing status uses spinning icon for animation
  • Pulse dot is decorative and supplementary

SimpleBadge

Minimal status indicator for data tables and lists. Semantic colors without icons or animations.

ActivePendingOverdueNewDraft

SimpleBadgeProps

PropTypeDefaultDescription
variant*'success' | 'warning' | 'error' | 'info' | 'neutral'Semantic color variant
children*ReactNodeBadge content

Installation

typescript
import { SimpleBadge } from '@stackmates/ui-interactive/atoms';

Accessibility

  • Text content provides meaning independent of color
  • Uses ring-inset for visible boundary in all themes

Spinner

Animated SVG loading spinner with 3 size variants and sr-only "Loading" text.

Loading...
sm
Loading...
md
Loading...
lg

SpinnerProps

PropTypeDefaultDescription
size'sm' | 'md' | 'lg''md'Spinner diameter (sm=16px, md=24px, lg=32px)
classNamestringAdditional CSS classes

Installation

typescript
import { Spinner } from '@stackmates/ui-interactive/atoms';

Accessibility

  • role="status" on the container for assistive technology
  • Includes sr-only "Loading..." text
  • Uses CSS animation (respects prefers-reduced-motion)

Skeleton

Animated pulse placeholder for loading states. Size and shape controlled entirely via className.

SkeletonProps

PropTypeDefaultDescription
classNamestringWidth, height, and border-radius via Tailwind classes

Installation

typescript
import { Skeleton } from '@stackmates/ui-interactive/atoms';
// Note: also re-exported via LoadingSkeletons molecule

Accessibility

  • Decorative element — pair with aria-busy on the loading container
  • Uses animate-pulse (respects prefers-reduced-motion via Tailwind)

SeparatorRx

Visual divider line built on Radix Separator. Supports horizontal and vertical orientation.

Content above

Content below

Left
Center
Right

SeparatorProps

PropTypeDefaultDescription
orientation'horizontal' | 'vertical''horizontal'Direction of the divider line
decorativebooleantrueWhen true, hides from screen readers via aria-hidden

Installation

typescript
import { SeparatorRx } from '@stackmates/ui-interactive/atoms';
// Exported as SeparatorRx to avoid naming conflicts

Accessibility

  • decorative=true hides from screen readers (default)
  • Set decorative=false when separator conveys meaningful grouping
  • Built on Radix Separator with proper role="separator"

EmptyStateIllustration

Professional SVG illustrations for empty data states. 6 domain-specific variants.

$
deals
contacts
generic (24)

EmptyStateIllustrationProps

PropTypeDefaultDescription
variant*'contacts' | 'deals' | 'activities' | 'notes' | 'tasks' | 'generic'Illustration type matching the empty entity
classNamestringOverride size (default: h-32 w-32)

Installation

typescript
import { EmptyStateIllustration } from '@stackmates/ui-interactive/atoms';

Usage

In an empty table state

tsx
<div className="flex flex-col items-center py-12">
  <EmptyStateIllustration variant="deals" />
  <p className="mt-4 text-muted-foreground">No deals yet</p>
  <Button className="mt-2">Create Deal</Button>
</div>

Accessibility

  • Illustrations are decorative — pair with descriptive text
  • Uses data-testid for test targeting
Related:

ThemeToggle

Dropdown button to switch between light, dark, and system themes. Uses next-themes.

Click to switch between light, dark, and system themes

ThemeToggleProps

PropTypeDefaultDescription

Installation

typescript
import { ThemeToggle } from '@stackmates/ui-interactive/atoms';

Accessibility

  • Button has sr-only "Toggle theme" label
  • Dropdown menu is keyboard navigable
  • Prevents hydration mismatch with mounted check