Design System

Data Display Atoms

ImportCC

Available via @stackmates/ui-interactive/atoms

PriceDisplay

Formatted currency display with preset support (USD, EUR, GBP, AUD, JPY) and compact notation.

$125.0099,99EUR£45.99
$(75.00)$12.3K$0.00

PriceDisplayProps

PropTypeDefaultDescription
amount*number | bigintAmount in smallest currency unit (cents for USD/EUR)
currencystring | CurrencyConfig'USD'Currency preset code or custom config
showSymbolbooleantrueShow currency symbol
showCodebooleanfalseShow currency code after amount
compactbooleanfalseUse compact notation for large numbers
size'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl''md'Text size variant
variant'default' | 'muted' | 'success' | 'danger' | 'primary''default'Color variant (negative amounts auto-switch to danger)

Installation

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

Usage

Basic (cents)

tsx
<PriceDisplay amount={12500} />  {/* $125.00 */}

Compact large values

tsx
<PriceDisplay amount={1234567} compact size="xl" />

Accessibility

  • Renders as <span> with tabular-nums for consistent digit width
  • Currency symbol is visible text, not icon-only
  • Negative values indicated by parentheses and red color (not color alone)

AIConfidenceScore

AI confidence badge with HITL color coding: green (>=80%), yellow (60-79%), red (<60%).

HITL color coding

92%68%35%
85%50%

AIConfidenceScoreProps

PropTypeDefaultDescription
score*numberConfidence score (0-100 or 0-1, auto-normalized)
size'sm' | 'md' | 'lg''md'Size variant
showIconbooleantrueShow the AI sparkle icon
showLabelbooleantrueShow the confidence level label
labelstringCustom label (overrides default level label)

Installation

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

Usage

Percentage input

tsx
<AIConfidenceScore score={92} />

Decimal input (auto-normalized)

tsx
<AIConfidenceScore score={0.85} size="sm" />

Accessibility

  • Color + text label convey confidence level (not color alone)
  • Title attribute provides full "AI Confidence: N%" tooltip
  • Sparkle icon is aria-hidden, decorative only

AISuggestedBadge

Badge labeling AI-generated, suggested, enhanced, or auto-filled content.

AI GeneratedAI SuggestedAI EnhancedAuto-filledCustom Label

AISuggestedBadgeProps

PropTypeDefaultDescription
variant'generated' | 'suggested' | 'enhanced' | 'auto-filled''generated'Type of AI suggestion
size'sm' | 'md''sm'Size variant
labelstringCustom label (overrides default)

Installation

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

Usage

Default (generated)

tsx
<AISuggestedBadge />

Enhanced variant

tsx
<AISuggestedBadge variant="enhanced" size="md" />

Accessibility

  • Icon + text label convey AI origin (not icon alone)
  • Each variant uses distinct icon for additional differentiation
  • data-variant attribute available for test selectors

AIConfidenceScoreCompact

Compact inline variant showing just score percentage with HITL color indicator. Use for tight layouts like table cells.

Inline usage alongside text

95%72%38%

In context

Suggested price: $12,50087%

AIConfidenceScoreCompactProps

PropTypeDefaultDescription
score*numberConfidence score (0-100 or 0-1, auto-normalized)
classNamestringAdditional CSS classes

Installation

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

Usage

Inline with content

tsx
<span>Suggested price: $12,500 <AIConfidenceScoreCompact score={87} /></span>

In a table cell

tsx
<AIConfidenceScoreCompact score={0.92} />

Accessibility

  • Title attribute provides "AI Confidence: N%" tooltip on hover
  • Sparkle icon is aria-hidden as decorative, score text conveys information
  • Color-coded text matches HITL thresholds (green >= 80%, yellow 60-79%, red < 60%)

AISuggestedIcon

Icon-only variant of AISuggestedBadge for inline use where space is limited. Shows tooltip on hover.

Inline with text

Deal summary

AISuggestedIconProps

PropTypeDefaultDescription
variant'generated' | 'suggested' | 'enhanced' | 'auto-filled''generated'Type of AI suggestion (determines icon and tooltip)
classNamestringAdditional CSS classes

Installation

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

Usage

Inline indicator

tsx
<span>Deal summary <AISuggestedIcon variant="generated" /></span>

Different variants

tsx
<AISuggestedIcon variant="suggested" />
<AISuggestedIcon variant="enhanced" />

Accessibility

  • Title attribute provides variant label (e.g. "AI Generated") as tooltip
  • Icon-only display relies on title for screen reader context
  • Each variant uses a distinct Lucide icon for visual differentiation beyond color

ProgressStateful

State-aware progress bar with idle/active/complete/error states and customizable labels.

In progress...45%
Complete!100%
Upload failed72%

ProgressStatefulProps

PropTypeDefaultDescription
state*'idle' | 'active' | 'complete' | 'error'Current progress state (idle renders nothing)
progress*numberProgress percentage (0-100)
labelsPartial<Record<'active' | 'complete' | 'error', string>>Custom labels per state

Installation

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

Usage

Active state

tsx
<ProgressStateful state="active" progress={45} />

Error with custom label

tsx
<ProgressStateful state="error" progress={72} labels={{ error: 'Upload failed' }} />

Accessibility

  • State label is visible text, not color alone
  • Progress percentage displayed as numeric text
  • Idle state renders nothing (no empty container)

StarRating

Interactive 1-5 star rating with hover scale feedback and disabled read-only mode.

(3/5)
(4/5)
(2/10)

StarRatingProps

PropTypeDefaultDescription
value*numberCurrent rating value (1-max)
onChange(value: number) => voidChange handler for interactive mode
disabledbooleanfalseDisable interaction
maxnumber5Maximum number of stars
size'sm' | 'md' | 'lg''md'Star size variant

Installation

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

Usage

Interactive

tsx
const [rating, setRating] = useState(3);
<StarRating value={rating} onChange={setRating} />

Read-only

tsx
<StarRating value={4} disabled />

Accessibility

  • Each star is a <button> with aria-label "Rate N of M stars"
  • Disabled state uses cursor-not-allowed and muted styling
  • Numeric rating shown as text "(N/M)" alongside stars

ErrorMessage

Error text display with role="alert" for form validation feedback.

ErrorMessageProps

PropTypeDefaultDescription
messagestringError text to display (renders nothing when empty)
idstringHTML id for aria-describedby linking

Installation

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

Usage

Basic

tsx
<ErrorMessage message="This field is required." />

With aria linking

tsx
<ErrorMessage message="Invalid email" id="email-error" />
<input aria-describedby="email-error" />

Accessibility

  • Uses role="alert" for screen reader announcement
  • Supports id prop for aria-describedby linking to form inputs
  • Renders nothing when message is empty (no empty container)

Badge

General-purpose label/tag with 7 semantic variants. CVA-styled with Radix Slot support for polymorphism.

DefaultSecondaryOutlineDestructive
SuccessWarningDanger

BadgeProps

PropTypeDefaultDescription
variant'default' | 'secondary' | 'destructive' | 'outline' | 'success' | 'warning' | 'danger''default'Visual variant determining color scheme
asChildbooleanfalseMerge props onto child element via Radix Slot (e.g. render an <a> styled as Badge)
classNamestringAdditional CSS classes

Installation

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

Usage

Default variant

tsx
<Badge>New</Badge>

Semantic variants

tsx
<Badge variant="success">Active</Badge>
<Badge variant="warning">Pending</Badge>
<Badge variant="destructive">Overdue</Badge>

As link (Slot pattern)

tsx
<Badge asChild variant="outline">
  <a href="/deals">View Deals</a>
</Badge>

Accessibility

  • Renders as <span> by default with proper inline semantics
  • asChild merges props onto child element via Radix Slot
  • Focus-visible ring for keyboard navigation when used as link
  • aria-invalid triggers destructive ring styling for error states

TrendIndicator

Displays metric trend direction with percentage change or custom label. Auto-calculates direction from sign of change value.

Auto-direction from change value

+12.5%-3.8%0.0%

Custom label with explicit direction

GrowingDecliningFlat

TrendIndicatorProps

PropTypeDefaultDescription
changenumberPercentage change value (e.g. 5.2 for +5.2%). Direction auto-calculated from sign.
direction'up' | 'down' | 'stable'Trend direction. Auto-calculated from change, or required when using label.
labelstringCustom label text instead of percentage. When used, direction is required.
showPercentbooleantrueShow percentage sign after numeric change
size'sm' | 'md''md'Text and icon size variant

Installation

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

Usage

Numeric change (auto-direction)

tsx
<TrendIndicator change={5.2} />  {/* Green up arrow +5.2% */}
<TrendIndicator change={-3.1} /> {/* Red down arrow -3.1% */}

Custom label

tsx
<TrendIndicator direction="up" label="Growing fast" />

Accessibility

  • Icon + text convey direction (not color alone)
  • data-direction attribute for test selectors
  • data-testid="trend-indicator" for automated testing
  • Icons are aria-hidden, text content provides meaning

CostDisplay

Formatted USD cost display with optional input/output token counts. Designed for AI operation cost visibility.

$0.0042
$0.1523
$1.2000
$0.00871,250in / 340out

CostDisplayProps

PropTypeDefaultDescription
costUsd*numberCost amount in USD (displayed to 4 decimal places)
tokens{ input: number; output: number }Optional token counts shown alongside cost
classNamestringAdditional CSS classes

Installation

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

Usage

Cost only

tsx
<CostDisplay costUsd={0.0042} />

With token breakdown

tsx
<CostDisplay costUsd={0.0087} tokens={{ input: 1250, output: 340 }} />

Accessibility

  • Uses tabular-nums for consistent digit width alignment
  • Cost value displayed as text, not color-coded
  • Token counts provide additional context alongside cost