Tollerud UI / Foundations
Foundations

Foundations

The atomic decisions every component inherits — color, type, space, depth and motion. All defined as CSS variables that flip cleanly between dark and light.

Brand color

Yellow is the only chromatic color in the system. It signals interaction; everything else is monochrome.

Yellow & amber

Yellow
--tollerud-yellow
Yellow warm
--tollerud-yellow-warm
Yellow dim
--tollerud-yellow-dim
Amber
--tollerud-amber
Amber glow
--tollerud-amber-glow

Noir scale

Black
--tollerud-black
Noir 900
--tollerud-noir-900
Noir 800
--tollerud-noir-800
Noir 700
--tollerud-noir-700
Noir 600
--tollerud-noir-600
Noir 500
--tollerud-noir-500
Noir 400
--tollerud-noir-400
Noir 300
--tollerud-noir-300
Noir 200
--tollerud-noir-200
Noir 100
--tollerud-noir-100
Noir 50
--tollerud-noir-50
White
--tollerud-white

Monogram

The Tollerud mark is a single continuous path — a stylised T in acid yellow (#FFFF00). There is no separate wordmark; use the monogram everywhere the brand needs to appear at small scale.

96px · App chrome
48px · Nav / favicon
26px · Inline badge
20px · Minimum

When to use

ContextAssetNotes
Sidebar, topbar, favicon<Monogram />Primary brand mark — always on noir/black
Sign-in panel, auth flows<Monogram size={26} />26–32px beside product name
Hero / marketingMonogram + wordmark in copyNo separate wordmark file — set product name in Inter next to the mark

Clear space & background

Preserve at least one T-width of padding on all sides. The monogram is designed for dark surfaces — black, noir-900, or the grain gradient. Never place on white or light backgrounds; contrast breaks and the yellow reads as noise.

Do
Place on noir/black backgrounds onlyUse acid yellow fill as shipped — no recolorScale proportionally; 20px is the minimum widthPair with Inter for product name when space allows
Don't
Place on white or light card backgroundsStretch, rotate, outline, or add drop shadowsRecolor the fill or use gradientsUse as a decorative pattern or watermark
monogram.jsx
import { Monogram } from '@tollerud/ui'

// Default — acid yellow on dark surfaces
<Monogram size={26} />

// Light-mode nav / cards
<Monogram color="black" size={20} />

// On tinted or photo backgrounds
<Monogram color="white" className="h-5 w-auto" />

Navigation lockup

The monogram always appears to the left of the project name — never the name alone, never the mark alone. Use TopNav for top bars so the lockup, link states, focus styles, and spacing stay consistent.

top-nav.jsx
import { Button, TopNav } from '@tollerud/ui'

<TopNav
  projectName="Dashboard"
  navItems={[
    { label: 'Overview', href: '/', active: true },
    { label: 'Services', href: '/services' },
    { label: 'Logs', href: '/logs' },
  ]}
  actions={<Button size="sm" variant="primary">Deploy</Button>}
/>
app-shell.jsx
import { DashboardShell, PageHeader } from '@tollerud/ui'

<DashboardShell
  projectName="Dashboard"
  pageTitle="Overview"
  sidebarItems={[
    { id: 'overview', label: 'Overview', href: '/', active: true },
    { id: 'services', label: 'Services', href: '/services' },
    { id: 'settings', label: 'Settings', href: '/settings' },
  ]}
  header={<PageHeader title="Overview" description="Fleet health at a glance." />}
>
  {/* page content */}
</DashboardShell>

State color

Used sparingly for status only — kept muted so yellow stays the loudest thing on screen.

Success
--success
Warning
--warning
Error
--destructive
Info
--info

Semantic tokens

CSS variable aliases for background, foreground, card, and accent. Components reference these — re-theming is a matter of remapping nine variables.

TokenRoleReference
--backgroundPage backgroundvar(--background)
--foregroundPrimary textvar(--foreground)
--cardRaised surfacevar(--card)
--popoverOverlay surfacevar(--popover)
--primaryYellow actionvar(--primary)
--secondaryMuted surfacevar(--secondary)
--mutedMuted fillvar(--muted)
--borderHairline bordervar(--border)
--ringFocus ringvar(--ring)

Typography

Inter for display and body, JetBrains Mono for code, metrics and terminal moments. Tight tracking on display sizes.

Display
56 / 0.98 / -0.045em
Dark. Yellow.
Heading 1
40 / 1.02 / -0.04em
Mission control
Heading 2
28 / 1.1 / -0.025em
Service health
Heading 3
20 / 1.2 / -0.02em
Active sessions
Body
16 / 1.5
Direct, technical, warm-but-not-corporate copy.
Small
14 / 1.5
Secondary descriptions and metadata.
Mono
14 / 1.7
❯ systemctl status tollerud-agent

Display shimmer

Animated yellow sweep clipped to text — for hero accent lines and key metrics on dark surfaces. Ships with the standard @import "@tollerud/ui/globals.css" setup; no extra install step. Use on a short accent span inside .tollerud-display, not body copy. Respects prefers-reduced-motion (static yellow). For a static gradient, use .tollerud-gradient-text instead.

Dark. Monochrome.
Yellow where it counts.

42
display-shimmer

Spacing

A 4px base grid. These eight steps cover the vast majority of layout.

space-14px
space-28px
space-312px
space-416px
space-624px
space-832px
space-1248px
space-1664px

Radius

Subtle by default. Sharp corners hold the noir feel.

radius-none
0
radius-sm
2px
radius-DEFAULT
4px
radius-md
6px
radius-lg
8px
radius-xl
12px
radius-2xl
16px

Elevation

A four-tier shadow scale plus a yellow glow — theme-aware (deep in dark, soft in light). Lean on borders first; reach for a shadow only to lift overlays (drawers, popovers, menus) off the page.

--shadow-sm
--shadow-md
--shadow-lg
--shadow-xl
--shadow-glow

Density

Two modes: comfortable (default) and compact. Set data-density='compact' on any container, or use density='compact' directly on Card. Live demo → Components.

TokenEffect
data-density="comfortable"Default. Card padding 24px, table rows 48px, form rows relaxed.
data-density="compact"Card padding 12px, table rows 36px, panel headers 32px, button heights trimmed.
<Card density="compact">Per-card override — no wrapper needed.

Motion

Quick and confident. Durations stay short; easing does the expressive work. Everything here respects prefers-reduced-motion.

TokenValueUse for
--motion-duration-fast150msHover, focus, small toggles
--motion-duration-normal250msMost transitions, fades
--motion-duration-slow350msOverlays, large movement
--motion-ease-outcubic-bezier(.16,1,.3,1)Entrances
--motion-ease-in-outcubic-bezier(.4,0,.2,1)Movement
Easing curves
ease-out
Entrances — overshoot-free settle
ease-in-out
Movement between two states
linear
Progress, shimmer, marquee
Interaction patterns
Scroll reveal
fade + rise, staggered
Hover lift
hover me
move cursor over button

Iconography

Docs demos use lucide-react via the Icons registry (24px grid, 1.8 stroke). Yellow is reserved for interactive icons — most sit in the current text color.

adding-an-icon.jsx
// 1. Map a lucide icon in docs-app/components/kit/icons.jsx:
import { Container } from 'lucide-react'
// ...
container: icon(Container),

// 2. Use it anywhere — by component or by name string:
<Icons.container size={18}/>
<StatCard icon="container" .../>   // components that take an icon prop

Voice

Direct. Technical. Warm-but-not-corporate. Think terminal prompt, not marketing email.

Say this
❯ deploy --env productionOpen DashboardPort 8080 is in useemma — deployment completeNo alerts — everything looks good
Not this
Submit deployment requestClick here to get startedOops! Something went wrong!Your deployment was successfulThere are no items to display

Tia

Tia — Tollerud Infrastructure Agent — is the brand mascot. Cel-shaded monochrome gakuran, amber eyes, gold buttons. A brand signature, not a UI icon. Use sparingly on landing pages, about sections, agent-running moments and loading states.

Portraitbrand/tollerud-avatar.svg
Tia portrait
Waist-up wave — the default avatar for nav badges, chat bubbles, and compact brand moments. PNG variant (brand/tollerud-avatar.png) ships for hero-scale renders with drop shadow.
Full figurebrand/tollerud-avatar-full.svg · .png
Tia full figure
Head-to-toe illustration for hero sections, empty states, and onboarding. PNG variant (brand/tollerud-avatar-full.png) ships for hero-scale renders with drop shadow.
Do
Use portrait for avatars, chat, and compact UI chromeUse full figure for hero and onboarding momentsPlace on noir/black or grain-gradient backgroundsOne Tia per viewport — she is a signature, not wallpaper
Don't
Use Tia as a generic user avatar or icon substituteCrop below the shoulders on the full-figure assetPlace on light backgrounds without a dark scrimInline the SVG — reference the asset file instead
tia-avatar.jsx
import { TiaPortrait, TollerudAvatarFull } from '@/components/brand'

// Portrait — SVG for crisp scaling, PNG for hero glow
<TiaPortrait width={96} alt="Tia" />
<TiaPortrait variant="png" height={340} glow alt="Tia" />

// Full figure — SVG for docs panels, PNG for hero glow
<TollerudAvatarFull height={480} alt="Tia" />
<TollerudAvatarFull variant="png" height={520} glow alt="Tia" />