Tollerud

Tollerud UI/Components / Empty state

Components

Components

Core primitives — button, card, badge, status. Layout, form controls, overlays, data views, and full-screen examples live on their own pages.

More components

This page covers primitives only. Everything else has a canonical home.

Nine variants, three sizes with fixed height per size — text and icon-only buttons align in the same row. Primary and terminal support a pointer-following glow when you call initButtonGlow() once at the app root (see Foundations → Motion). Terminal carries the ❯ prefix for technical actions. Ghost semantic variants (ghost-destructive, ghost-success, ghost-warning, ghost-info) stay muted at rest and tint on hover — use in dense toolbars and ButtonGroups.

PropsButtonProps
PropType
asChild?boolean
loading?boolean
buttons
button-sizes
button-icons
button-ghost-semantic
button-loading

Fused action buttons for independent clicks — not a toggle. Wrap text or icon-only Button children; the group shares borders and height. Use Segmented when one option should stay selected.

PropsButtonGroupProps
PropType
size?ButtonGroupSize
orientation?ButtonGroupOrientation
button-group

Single-select toggle for views, sort modes, or filters. Pass collapseMobile to show only the active option on narrow viewports — tap to open a dropdown overlay, select to collapse.

PropsSegmentedProps
PropType
optionsSegmentedOption[]
valuestring
onChange(value: string) => void
size?'sm' | 'md'
collapseMobile?boolean

Resize below 768px to see collapseMobile — selected option only; tap opens a dropdown.

segmented

The default surface. accent={true} adds a yellow border tint. accent='filled' adds a yellow border + subtle yellow fill. Optional CardHeader / CardContent / CardFooter compound parts. CardHeader accepts an actions slot — use CardChange for StatCard-style up/down deltas. Each of CardHeader/CardContent/CardFooter also takes its own accent to override the parent Card's accent for just that region.

PropsCardProps
PropType
* `true` — yellow border tint (`border-tollerud-yellow/25`), no fill.
* `"filled"` — yellow border + subtle yellow background fill (`bg-tollerud-yellow/5`). Use for callout boxes, cheapest-item highlights, and CTAs.
*
* Cascades to `CardHeader`/`CardContent`/`CardFooter` tinting. Any of those parts can
* set their own `accent` prop to override the cascade for just that region.
*/
accent?boolean | 'filled'
density?'comfortable' | 'compact'
asChild?boolean
* Force structured layout (no shell padding, header/content/footer own their padding) on or off.
* Omit to auto-detect from `CardHeader`/`CardContent`/`CardFooter` children — that detection reads
* `child.type.displayName`, which can fail to survive a Next.js Server/Client Component boundary.
* Set this explicitly when composing across that boundary instead of relying on auto-detection.
*/
structured?boolean
emma — readyhealthy
iris — reviewattention
pia — cheapestbest price
cards

Restart emma

Stops 4 running services. They can be restarted from the dashboard.

emma.tollerud.no — SSH connected
card-sections

Review required

iris.tollerud.no

Attention
card-sections-accent

Brukt av budsjett

12 930 kr / 2 700 kr
card-region-accent

Active sessions

Last 24h

+12%

42

Error rate

Last 24h

-3%

0.4%

Uptime

Last 24h

99.9%

card-header-change
card-as-child

Deploy

Body

Deploy

+12%
Body content
card-structured-prop

Compact price display: a primary value with an optional secondary Badge below it. Use highlight='cheapest' for success coloring. size='sm' | 'md' | 'lg' scales the block for table cells or prominent rows. Defaults to right-aligned.

PropsPriceDisplayProps
PropType
primarystring
secondary?string
* `"cheapest"` switches the primary value to success color and the badge to `variant="success"`.
* `false` (default) uses muted text for the primary and default badge styling.
*/
highlight?'cheapest' | false
align?'left' | 'right'
size?PriceDisplaySize
Total Wine · Downtown
$4.29/pt$8.58
Costco · Eastside
$3.99/pt$7.98
Whole Foods · compact
$4.79/pt$9.58
Featured · large
$4.79/pt$9.58
price-display

Hover card shell for list and grid items. Pass href to render as a link. Use highlight='cheapest' for a yellow border tint on the best-value item. Children are fully consumer-controlled — compose with Cluster or Split for left/right layouts.

PropsListCardProps
PropType
href?string
* `"cheapest"` applies a yellow border tint to flag the best-value item.
* `false` (default) uses the standard border.
*/
highlight?'cheapest' | false
external?boolean

Two-column marketing block with a text column and a consumer-controlled visual slot. Eyebrow matches PageHeader — mono uppercase yellow. Pass shimmer='word' to give one word in the title a shimmer accent. Collapses to single-column on mobile with text always first. background='raised' goes edge-to-edge with contentWidth capping the inner content.

PropsPromoSectionProps
PropType
eyebrow?ReactNode
titleReactNode
* When `title` is a string, wraps the first matching substring(s) in `.tollerud-display-shimmer`.
* Pass a string for a single accent or a string[] to shimmer multiple words/phrases.
* e.g. shimmer="favorittøl" or shimmer={["favorittøl", "dine butikker"]}
*/
shimmer?string | string[]
description?ReactNode
actions?ReactNode
visual?ReactNode
visualPlacement?PromoSectionVisualPlacement
background?PromoSectionBackground
textWidth?PromoSectionTextWidth
contentWidth?PromoSectionContentWidth
Beer prices

See what your favourite beers cost across every store

Create a free account and track prices on your go-to beers. Set up alerts when prices change.

App preview
promo-section

A horizontal rule. Default uses the border token; accent variant draws a short yellow rule for section breaks.

Content above the divider

Content below the divider

Accent variant — short yellow rule

dividers

Badges label status inline. Pills are tiny mono-flavored tags.

PropsBadgeProps
PropType
variant?keyof typeof badgeVariants
NewOnlineDegradedOfflineBetaDefault
badges
newdeprecatedstablecritical
pills

Status dots show liveness with a soft glow. Kbd renders shortcut chips.

emma — readyCPU 87%pia — unreachableiris — idleNote added
status
⌘+KSEsc
kbd

Compact metric tiles for dashboards, with optional trend. tone colors the value + border independently of accent — for a status-carrying figure.

PropsStatCardProps
PropType
labelstring
valueReactNode
change?{
value?string
directionCardChangeDirection
tone?'success' | 'error' | 'warning' | 'info' | 'accent'
}
accent?boolean
tone?StatCardTone
icon?ReactNode
secondaryValue?ReactNode
secondaryTone?'default' | 'accent' | 'success' | 'error' | 'warning' | 'info'

Active Sessions

12%

42

CPU Load

4%

63%

Storage

1.2 TB

stats

Brukt av budsjett

12 930 kr / 2 700 kr

stats-tone

Price

23,90 kr

47,80 kr/l

Ticket price

stats-secondary-value

Loading and identity primitives. Avatar and AvatarGroup stack naturally.

progress
avatar-group

Appears on hover and focus. Supports top (default) and bottom placement.

tooltip

Four semantic tones. Pass icon to override the default icon per tone. Alert has no built-in outer margin — stack with Stack or className in apps.

PropsAlertProps
PropType
tone?keyof typeof toneStyles
title?string
icon?React.ReactNode
alerts

Organize content. Tabs ship pill and underline variants.

Pill tabs — the default. Good for switching views inside a card.
Underline tabs — for page-level sections.
tabs
npm install @tollerud/ui tailwindcss@4, then @import globals.css and @source the package dist in app/globals.css.
accordion

Vertical activity feed with status-colored dots and metadata. variant='flat' (v4.16.0) drops the connector line for a divided activity/audit-log list, and title accepts rich content.

Deployed hermes v2.014:32

Rolled out to emma

success3s
Restarted nginx14:31

Config reloaded

warning
SSH connection failed14:30

emma refused connection

timeline
Karoline krysset av «Laks, filet»
12 min siden
Mathias la til Kenneth Granstrøm
1 t siden
timeline-flat

Plain static table primitives — no sorting, filtering, search, or pagination. Use DataTable for that; use Table for a fixed comparison table or small dataset.

PropsTableRowProps
PropType
highlight?boolean
IngrediensFor 8For 14
Laks, filet3,2 kg5,6 kg
Sitron4 stk7,0 stk
table

A card with a header bar: title, optional description, and optional actions. Pass a fragment with multiple buttons to actions for a toolbar.

Compose stack

All services healthy

hermes

Restart pending
panel

A labeled progress row that turns red past a hot threshold (default 85%). Used for CPU/memory/disk and plan-usage limits.

CPU23%
Disk88%
Containers28 running
meter

Horizontal step indicator for wizards and multi-stage flows. Pass an array of step labels and the current step index (0-based). Completed steps fill yellow; the active step carries a ring.

  1. 1
    Connect host
  2. 2
    Choose stacks
  3. 3
    Invite team
  4. 4
    Finish
  1. Connect host
  2. Choose stacks
  3. 3
    Invite team
  4. 4
    Finish
  1. Connect host
  2. Choose stacks
  3. Invite team
  4. 4
    Finish
stepper

Two ways to apply compact density: set density='compact' directly on a Card, or wrap a group with data-density='compact' to tighten everything inside.

Card title

Padding tightens in compact mode.

TOTP at sign-in.

density="compact"

Always compact via prop.

Default

Comfortable by default.

density

For surfaces with no data, no results, or an error. Icon, headline, calm explanation, one clear action. Use compact inside cards, tables, and panels.

PropsEmptyStateProps
PropType
icon?EmptyStateIconName | ReactNode
title?ReactNode
description?ReactNode
action?ReactNode
secondaryAction?ReactNode
compact?boolean
accent?boolean
No hosts connected

Connect your first machine and Tia will start watching it within seconds.

All clear

No open alerts across your fleet. The last incident was acknowledged 6 days ago.

No results

Nothing matches “grafna”. Check the spelling or clear the filter to see everything.

Couldn’t reach the agent

emma.tollerud.no refused the connection. The agent may be offline or the port blocked.

empty-state
Alert inbox0
Inbox zero

No alerts right now — we’ll surface anything that needs you here.

empty-state-compact

Terminal-style code display with an optional copy button. Use the code prop for a single string, or children for richer markup.

systemctl status tollerud-agent
code-block

Layout width constraint — 1100px max with 24px horizontal padding. Use as a page wrapper or section cap.

Content capped at 1100px
container

A single command-list row — icon, label, description and shortcut. Used inside CommandMenu-style surfaces.

action-row

Wraps any surface with a cursor-tracking yellow glow. Intensity and color are configurable.

Hover to see the glow follow the cursor.
glow-card