Skip to content

Components

All components are imported from @nomadahq/sm-ui. Styles require the CSS imports:

js
import '@nomadahq/sm-ui/css'
import '@nomadahq/sm-ui/css/components'

Card / CardBody

A bordered, rounded card container.

jsx
import { Card, CardBody } from '@nomadahq/sm-ui'

<Card>
  <CardBody>Content here</CardBody>
</Card>

// Accent border (product color highlight)
<Card accent="#7947d1">
  <CardBody>Studios-accented card</CardBody>
</Card>

Props:

PropTypeDescription
accentstringCSS color for left/top accent border
classNamestringAdditional CSS class
styleobjectInline styles

Button

jsx
import { Button } from '@nomadahq/sm-ui'

<Button variant="primary" onClick={handleClick}>Save</Button>
<Button variant="secondary">Cancel</Button>
<Button variant="danger" size="sm">Delete</Button>
<Button href="/dashboard">Go to Dashboard</Button>
PropTypeValuesDescription
variantstringprimary, secondary, dangerVisual style. Default: secondary
sizestringsm, lgSize modifier
onClickfunctionClick handler
disabledbooleanDisabled state
hrefstringRenders as <a> instead of <button>

Badge / Pill

Inline status labels.

jsx
import { Badge, Pill } from '@nomadahq/sm-ui'

<Badge color="green">Active</Badge>
<Badge color="amber">Pending</Badge>
<Badge color="red">Overdue</Badge>
<Badge color="blue">Studios</Badge>
<Badge color="gray">Draft</Badge>

<Pill color="blue">New</Pill>

Colors: green, amber, red, blue, gray


StatCard / Stats

KPI display strip.

jsx
import { Stats, StatCard } from '@nomadahq/sm-ui'

<Stats>
  <StatCard label="MRR" value="$45,000" sub="+12% vs last month" />
  <StatCard label="Active Clients" value="12" />
  <StatCard
    label="Pipeline"
    value="$280k"
    valueColor="var(--blue)"
    valueSize="2rem"
  />
</Stats>
PropTypeDescription
labelstringMetric label (shown above value)
valuestring/numberMain value
substringSubtext below value
valueColorstringCSS color for value
valueSizestringCSS font-size for value

Progress

A simple percentage progress bar. Uses var(--accent) color by default.

jsx
import { Progress } from '@nomadahq/sm-ui'

<Progress value={72} />
<Progress value={45} color="#1fac6a" />

Tabs

Horizontal tab navigation.

jsx
import { Tabs } from '@nomadahq/sm-ui'
import { useState } from 'react'

const TABS = [
  { key: 'overview', label: 'Overview' },
  { key: 'engagements', label: 'Engagements' },
  { key: 'invoices', label: 'Invoices' },
]

function MyPage() {
  const [tab, setTab] = useState('overview')
  return (
    <>
      <Tabs tabs={TABS} active={tab} onChange={setTab} />
      {tab === 'overview' && <Overview />}
      {tab === 'engagements' && <Engagements />}
    </>
  )
}

Standardized page header with breadcrumb, title, and action slot.

jsx
import { PageHeader, Button } from '@nomadahq/sm-ui'

<PageHeader
  breadcrumb="Clients"
  breadcrumbProduct="Studios"
  title="Acme Corp"
  subtitle="Active client since Jan 2025"
>
  <Button variant="primary">New Invoice</Button>
</PageHeader>

Table

Data table with optional row click handler.

jsx
import { Table } from '@nomadahq/sm-ui'

<Table
  headers={['Name', 'Status', 'MRR']}
  rows={companies.map(c => ({
    cells: [c.name, <Badge color="green">Active</Badge>, `$${c.monthly_revenue}`]
  }))}
  onRowClick={(row, index) => navigate(`/clients/${companies[index].id}`)}
  empty={<Empty title="No clients yet" message="Add your first client to get started." />}
/>
PropTypeDescription
headersstring[]Column header labels
rows{ cells: ReactNode[] }[]Table rows — each row has a cells array
onRowClick(row, index) => voidOptional click handler
emptyReactNodeShown when rows is empty

Empty

Empty state with icon, title, and message.

jsx
import { Empty } from '@nomadahq/sm-ui'

<Empty
  icon="📋"
  title="No candidates yet"
  message="Import from Manatal or add candidates manually."
/>

Spinner

Full-width centered loading spinner.

jsx
import { Spinner } from '@nomadahq/sm-ui'

{loading && <Spinner />}

ScoreRing

SVG ring chart for displaying a 0–100 score (ICP score, health score, etc.).

jsx
import { ScoreRing } from '@nomadahq/sm-ui'

<ScoreRing score={82} label="ICP Score" />

Ring fill color uses var(--accent).

Sprint Mode LLC — Internal Platform Documentation