UI Kit

Composed primitives from Components + Tokens. Use when the shape fits; reach for underlying primitives when it doesn't.

SectionHead

Section header — title uses .label-caps; optional actions snippet sits right-aligned on the title row; optional hint renders as supporting copy below.

Props
  • title — heading text (rendered as .label-caps).
  • hint? — supporting copy, always rendered below the title row.
  • actions? — snippet for right-aligned buttons/controls on the title row.
Title + hint

Projects

Changes save automatically

Title + actions

Active sessions

Title + actions + hint

Projects

Changes save automatically

StatCard

KPI label/value/sub triplet. align="start" = standalone glass card; align="center" = bare text block for dashboard grids.

Props
  • value and sub accept strings or snippets (▲▼ deltas, inline markup).
  • progress={{ pct, color }} adds an animated fill bar below sub.
  • barKey — change to replay the bar animation without remounting the card.
  • valueColor — inline color override for the value text.
Start-aligned (admin KPI grid)
Users 248 ▲ 12 new · 4 admin
Active in range 97 39% of users
Hours tracked 1,420 h ▼ 32 h vs prior
With progress bar + value tint
Synced to Tripletex 67% 42 / 63 entries
Center-aligned (dashboard)
Last Month 124 h (81%) 98 h billable 42,500 NOK
This Month 76 h (54%) 62 h billable 26,800 NOK
This Week 14 h 12 h billable 5,200 NOK

EmptyState

Centred no-data/loading placeholder. size: sm inline, md row gap, lg full-section.

Slots
  • icon — Lucide icon above the message.
  • action snippet — CTA below the message.
Plain message (sm)

Loading…

With icon (lg)

No commits yet.

With action snippet

Nothing to sync this week.

ConfirmDialog

Modal with Cancel/Confirm footer. Parent owns open; dialog owns its pending state.

Props & when to use
  • Default is destructive (danger button). Pass danger={false} for non-destructive confirms.
  • confirmLabel overrides "Confirm". message for plain body, body snippet for rich content.
  • Use InlineConfirm instead for row-level quick confirms that don't need explanation.
Variants

Delete project?

This action cannot be undone. All entries on this project will become unassigned.

Apply changes?

Mappings will be saved and synced on the next push.

Project Appearance Picker

Color + optional icon picker. Trigger: ProjectIcon with pencil-on-hover.

Details
  • Color-only: omit onIconChange.
  • With icons: 21 curated Lucide icons + URL input. Selecting the active icon again clears it.
  • Icons stored as lucide:name; image URLs render via <img>.
Color only
Color
#FF6384
Color + icon
Color
Icon
lucide:tree-palm
Color + image URL
Color
Icon
/images/deno-logo.webp

AI Assist

Floating sparkle button for AI rewrites on textareas. Click → preview suggestion → Accept/Reject.

Setup & gates
  • Parent needs position: relative; add padding-right to the textarea.
  • kind — server-side prompt: "project-description" or "user-bio".
  • Gated to admin + GEMINI_API_KEY (or ANTHROPIC_API_KEY).
  • Pink/purple shimmer distinguishes AI affordances from accent-blue UI.
In a textarea
Improve with AI
Disabled
Improve with AI

InlineConfirm

Inline question + Cancel/Confirm pair. Use instead of ConfirmDialog for row-level quick confirms.

Usage
  • Caller owns the trigger — toggle an open boolean, render <InlineConfirm> in its place.
  • busy disables both buttons while onConfirm resolves.
  • confirmLabel overrides "Confirm".
Default
Busy state
Apply changes?

Manage Projects

Delete project?

Delete this project? This cannot be undone.

Import Data

Edit Entry (NaNh NaNm)

Details

Duration

Delete entry?

This cannot be undone.

Manual Entry