Internal · Vera UI

Design system

Back to landing page

Vera, in pieces.

Every component, every state.

The whole design system on one page so the warm-fintech voice stays honest as the dashboard grows. Tokens, typography, primitives, charts, overlays — all live.

Foundations

Tokens, palette, typography, spacing

Color palette

Surfaces

bg-base

#f5efe6

Page background

bg-card

#fffcf7

Card surface

bg-elevated

#ffffff

Modal / popover

bg-subtle

#ece4d3

Hover / chrome

Text

text-primary

#1f1b16

Headlines, body

text-secondary

#6e6258

Supporting copy

text-muted

#9c8e80

Labels, hints

Lines & accents

border

#e8decf

Dividers, outlines

accent

#c8854e

Primary action

accent-soft

#e8c5a0

Accent on tint

success

#7a8f6f

Positive states

Heat bands

heat-cool

#7a8f6f

0–25 · Cool

heat-warm

#c9a05f

26–50 · Warm

heat-hot

#c8714c

51–75 · Hot

heat-critical

#a14535

76–100 · Critical

Typography

Display · 5xl

Where each install actually stands

Display · 4xl

Who I'd nudge today

Display · 2xl

606 McMackin Street

Body · lg

A thoughtful companion for accounts receivable in the roofing business.

Body · base

Insurance final check still missing — I'd nudge Brandon today.

Body · sm

Brandon Roberts · Dallas · Insurance · 47 days post-install

Caption · xs

Vera will draft a follow-up; nothing autosends.

Eyebrow · 0.65rem

Daily · job milestone tracking

Radii & shadows

0.75rem

radius-input

1.25rem

radius-card · soft shadow

9999px

pill / chip

Vera's voice

A thoughtful narrator, not a dashboard widget

Good morning. I'm watching three jobs more closely than usual today — Mike Ahrend's McMackin install crossed into the Hot band overnight.

Metric tiles

Headline numbers in three emphasis levels

Emphasis variants — default, accent, critical

Total AR

$1.42M

Across 130 installs

Critical

36

Need executive eyes

Hot

28

Vera will draft

Fell through

27

Weekly sweep

Tiles in the same row stretch to a uniform height. hint always reserves space (renders an invisible spacer when omitted).

Value type variants

Currency

$1,278,629

Total outstanding

Integer

130

Jobs in AR

Compact

$496K

Commissions YTD

Empty

No data yet

value accepts any ReactNode: strings, numbers, or inline elements (badges, icons, em-dashes for empty states).

Heat — meters & badges

Two presentations of the composite score

HeatMeter · default

Heat score
18/ 100
Coolhover for breakdown
Heat score
42/ 100
Warmhover for breakdown
Heat score
65/ 100
Hothover for breakdown
Heat score
88/ 100
Criticalhover for breakdown

HeatMeter · compact (table-row variant)

18Cool42Warm65Hot88Critical

HeatScoreBadge · two sizes

Heat18· CoolHeat42· WarmHeat65· HotHeat88· Critical
Heat18· CoolHeat42· WarmHeat65· HotHeat88· Critical

Charts

Pure SVG, no Recharts dep

BarChart · horizontal

New18 jobs
1–30d32 jobs·$72,400
31–60d44 jobs·$324,200
60–120d36 jobs·$754,000
120+d12 jobs·$210,500

DonutChart

Cool: 22 jobs (17%)Warm: 44 jobs (34%)Hot: 28 jobs (22%)Critical: 36 jobs (28%)
130In AR
  • Cool22 jobs17%
  • Warm44 jobs34%
  • Hot28 jobs22%
  • Critical36 jobs28%

Chips & tags

Aging buckets, missing milestones, anomaly flags

Aging buckets

New1–30d31–60d60–120d

Missing-step tags

missing:cert of completionmissing:final checkmissing:commission request

Anomaly tags · all 9 flags

Balance exceeds priceNo cert of completionFinal check stuckNo payments yetDuplicate addressNo commission requestImpossible paymentsArchived but owingWarranty voided

Buttons

Four variants, four sizes

Variants

Sizes

Cards

Plain, with header, and richly composed

Plain card

A plain Card just gives content the warm cream surface, the soft border, and the generous padding.

Card with header

Heat distribution

How the 130 active AR jobs split across the four heat bands today.

Cool 22 · Warm 44 · Hot 28 · Critical 36. Critical accounts for $711K of the $1.42M outstanding.

Job card · rich composition

606 McMackin Street

Brandon Roberts · Dallas · Insurance

31–60dmissing:final checkmissing:commission request
Heat score
72/ 100
Hothover for breakdown

$14,995 outstanding · install was 47 days ago. Insurance final check still missing — I'd nudge Brandon today.

Tables

TableShell, sticky head, footer slot

JobRepBalanceAgingHeat

606 McMackin Street

Dallas · Insurance

Brandon Roberts$14,99531–60d
72Hot

224 Roy Rogers Lane

Shreveport · Insurance

Clemente Mandujano$5,33360–120d
88Critical

1487 Streamside Drive

Dallas · Retail

Hernan Cubillos$6,2011–30d
42Warm

Pagination

TablePagination — rows-per-page dropdown, ellipsis, prev/next

Standalone — short list (≤5 pages)

1 of 3

With 5 or fewer pages, every page number renders. No ellipsis.

Standalone — long list (ellipsis kicks in)

1 of 172

Past 5 pages: 1 … (n−1) n (n+1) … last. The rows-per-page dropdown opens upward and supports 10 / 25 / 50 / 100.

Integrated — TableShell footer slot

JobRepBalanceAgingHeat

606 McMackin Street

Dallas · Insurance

Brandon Roberts$14,99531–60d
72Hot

224 Roy Rogers Lane

Shreveport · Insurance

Clemente Mandujano$5,33360–120d
88Critical

1487 Streamside Drive

Dallas · Retail

Hernan Cubillos$6,2011–30d
42Warm

1320 Raleigh Path

Dallas · Insurance

Brent Crutchfield$4,3021–30d
58Hot

1011 Thomas Ave

Shreveport · Insurance

Fushia McFashion$3,71060–120d
81Critical
1 of 6

Pass a TablePagination into TableShell.footer to get the unified card chrome. Used on Aging, Milestones, Reconciliation, and Rep Leaderboard.

Filter menu

FilterMenu + TableToolbar — chip groups and searchable dropdowns

Live — open and try it

By job — 130 rows

Click Filter to try it

No filters applied.

Both the popover and the inner Rep dropdown render to document.body so they escape every overflow / stacking trap. Marked with data-filter-popover so the click-outside handler keeps them grouped.

Trigger states

Default · with active filter count.

Tabs

Shared underline-style tabs · used on Scheduler + Follow-ups

Hot-band jobs Vera will draft for today (51–75).

Use Tabs / TabsList / Tab / TabsContent from @vera/ui. Controlled (pass value + onValueChange — e.g. wired to a useQueryState) or uncontrolled (just defaultValue). Underline is border-accent with primary text on the active tab; idle tabs are secondary. ARIA roles wired correctly — keyboard navigation works.

Toasts & confirm modals

Transient feedback + replacement for window.confirm()

toast() and useConfirm() from @vera/ui. Sonner-backed, themed in globals.css under [data-sonner-toaster] with Vera tokens. Five toast states share the modal chrome but use distinct silhouettes (filled circle / octagon / triangle / rounded square / arc) so users tell info vs error apart by shape, not just color. Info is the one cool tone in the palette — slate blue --color-info.

Two modal flavors share visual chrome (centered, bg-card, rounded card radius, p-7, shadow) but differ in layout:

  • <Modal> — content surface, no icon. Big font-display title, body owns the layout. Use for chat (Ask Vera), info dialogs, custom forms. See Modals & sheets below for the canonical example.
  • <ConfirmDialog> — action confirmation, with icon. Same display-serif title as <Modal>; what signals "confirmation" is the tinted icon blockto the left (accent or heat-critical). Title is imperative, not a question — "Cancel this run", not "Cancel this run?". Description as the body, left-aligned. Close X hidden — user must pick a button. Use via useConfirm().

Infinite scroll

Card-list pagination via IntersectionObserver

606 McMackin Street

Brandon Roberts · Dallas · Insurance

31–60dmissing:cert of completion

224 Roy Rogers Lane

Clemente Mandujano · Shreveport · Insurance

60–120dmissing:cert of completion

1487 Streamside Drive

Hernan Cubillos · Dallas · Retail

1–30dmissing:cert of completion

1320 Raleigh Path

Brent Crutchfield · Dallas · Insurance

1–30dmissing:cert of completion

1011 Thomas Ave

Fushia McFashion · Shreveport · Insurance

60–120dmissing:cert of completion

7101 GR 571

David Jones · Dallas · Retail

Newmissing:cert of completion

Showing 6 of 28 · scroll to load more

Sentinel below the list with IntersectionObserver(rootMargin: 320px) bumps a local visibleCountby chunk size as it scrolls into view. Footer reads "Showing X of Y · scroll to load more" while loading, "All N loaded" once done.

Empty states

What we show when filters or queries return nothing

No filter matches

No jobs match the current filters.

Queue is clear

Executive queue is clear in this view. Nothing has crossed the Critical threshold. Try clearing filters.

Reconciliation — clean board

Nothing fell through this week. Every completed install has at least one fresh signal — paperwork, an endorsed check, a commission request, or a recent edit.

Tooltips

Portaled — escape every overflow / stacking trap

Hover me · topHover me · bottom

Modals & sheets

Right-side sheet and centered modal

Both overlays render via createPortal to document.body so they escape any ancestor overflow/z-index trap.

Iconography

lucide-react · sized at h-4 / h-3.5

Home
AlertTriangle
ListChecks
GaugeCircle
Trophy
ClipboardCheck
Filter
Search
ChevronDown
ArrowLeft
ArrowRight
Check
X

Conventions: h-4 w-4 in nav and tile chrome, h-3.5 w-3.5 for inline button icons, h-3 w-3 for tiny chip glyphs. Icon color usually inherits from the surrounding text color.

Animations

Entrance and attention utilities

Entrance

vera-rise

Fade + 8px translateY on load. The default for hero, headers, sections.

vera-rise-delay-1 / -2 / -3

Same as vera-rise with 80 / 160 / 240ms stagger.

vera-modal-in

translateY 8px + scale 0.96 → 1, 220ms. Used by the centered modal.

vera-sheet-in / vera-backdrop-in

Slide-from-right + cross-fade for right-side sheets and the backdrop.

Attention

vera-fab-pulse

Continuous box-shadow pulse on the Ask Vera FAB.

vera-callout-in

Tooltip-callout for the FAB on first appearance.

All animations honor prefers-reduced-motion — if the user has reduced motion enabled, entrance and attention animations are suppressed.

That's every public component. Add new ones to shared/ui/src/components and surface a section here.