The shell

Anatomy of a DiffLab app

Every internal app is the same three regions: a 240px fixed gradient sidebar, a 56px white header with breadcrumbs, and a scrollable content area. This is the canonical DiffLab app shell (from the enterprise-workflows template) — it supersedes any legacy app style.

grid-template-columns: 240px 1fr — the sidebar spans both rows; only the content scrolls.

Live reference

See it running

A complete, self-contained implementation — no framework, no build step, just the tokens file and one HTML page. Copy it as the starting point for any new internal app.

/layout/demo.html — light-first by design; it does not follow this site’s theme toggle Open full screen ↗

Specification

The numbers

Every value below is normative and available as a --dl-* token in tokens.json / tokens.css.

Sidebar

PropertyValueToken
Width 240px, fixed --dl-layout-sidebar-width
Background linear-gradient(167deg, #1A2744 0%, #0B1224 100%) --dl-color-app-sidebar-gradient
Text rgba(255,255,255,0.84) --dl-color-app-sidebar-text
Text, muted / section labels rgba(255,255,255,0.55) --dl-color-app-sidebar-text-muted
Active item background rgba(245,158,11,0.18) (amber @ 18%) --dl-color-app-sidebar-active-bg
Active item indicator inset 2px white left bar + white text (box-shadow: inset 2px 0 0 #fff) --dl-color-app-sidebar-active-indicator
Brand block the mark rendered white at the top; user block pinned to the bottom

Header & content

PropertyValueToken
Header height 56px (3.5rem) --dl-layout-header-height
Header treatment white background, 1px bottom hairline, breadcrumbs left / actions right
Content padding 1.5rem --dl-layout-content-pad
Content padding, ≥ 1024px 2rem --dl-layout-content-pad-lg
Page background paper #f8fafc; cards sit on it as white surfaces --dl-color-brand-paper

Text ramp (light app surfaces)

RoleValueToken
Strong — headings, primary data #111827 --dl-color-app-text-strong
Muted — labels, descriptions #4B5563 --dl-color-app-text-muted
Faint — placeholders, tertiary #9CA3AF --dl-color-app-text-faint

Type conventions

ConventionValue
Root font size html { font-size: 106.25% } — 17px at the browser default
Line height 1.55 for app UI text
Families Inter for UI, Space Grotesk for headings, JetBrains Mono for code, IDs, and eyebrow labels
Numerals font-variant-numeric: tabular-nums in every data table and stat

Radii

ElementRadiusToken
Card0.75rem (padding 1.25–1.5rem)--dl-radius-card
Button0.375rem--dl-radius-button
StatusBadge9999px (pill)--dl-radius-badge

Buttons — 4 variants

VariantBackgroundTextHover
Primary amber #F59E0B white #D97706
Secondary white, 1px border #111827 border darkens to #9CA3AF
Ghost transparent #4B5563 faint gray fill
Danger #DC2626 white #B91C1C

Buttons — 3 sizes

SizePaddingFont size
sm0.3rem 0.7rem0.75rem
md (default)0.45rem 0.95rem0.85rem
lg0.6rem 1.25rem0.95rem

Status badges

StatusForegroundBackground
Success#0F7A0A#E4FFEC
Error#DC2626#FEE2E2
Warning#B45309#FEF3C7
Info#0085FF#E0F2FF

Recipes

Component recipes

Framework-free snippets — plain HTML and CSS over the tokens. Port them to React, Vue, or whatever your app uses; the numbers are what matter.

Card

White surface on the paper background. Radius 0.75rem, padding 1.25–1.5rem, hairline border.

<div class="card">…</div>

.card {
  background: #ffffff;
  border: 1px solid hsl(214 32% 91%);
  border-radius: var(--dl-radius-card);   /* 0.75rem */
  padding: 1.25rem;                       /* 1.5rem for roomy cards */
}

Button

Radius 0.375rem, weight 600. Variants: primary, secondary, ghost, danger. Sizes: sm, md, lg.

<button class="btn btn--primary btn--md">New run</button>

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  border: 1px solid transparent;
  border-radius: var(--dl-radius-button); /* 0.375rem */
  font: 600 0.85rem/1.2 var(--dl-font-family-sans);
  cursor: pointer;
}

.btn--sm { padding: 0.3rem 0.7rem;   font-size: 0.75rem; }
.btn--md { padding: 0.45rem 0.95rem; font-size: 0.85rem; }
.btn--lg { padding: 0.6rem 1.25rem;  font-size: 0.95rem; }

.btn--primary   { background: #F59E0B; color: #fff; }         /* hover #D97706 */
.btn--secondary { background: #fff; color: #111827;
                  border-color: hsl(214 32% 91%); }
.btn--ghost     { background: transparent; color: #4B5563; }
.btn--danger    { background: #DC2626; color: #fff; }          /* hover #B91C1C */

StatusBadge

Pill (radius 9999px): soft background, strong foreground. Four statuses only.

<span class="badge badge--success">Succeeded</span>

.badge {
  display: inline-flex;
  padding: 0.15rem 0.6rem;
  border-radius: var(--dl-radius-badge);  /* 9999px */
  font-size: 0.72rem;
  font-weight: 600;
}

.badge--success { color: #0F7A0A; background: #E4FFEC; }
.badge--error   { color: #DC2626; background: #FEE2E2; }
.badge--warning { color: #B45309; background: #FEF3C7; }
.badge--info    { color: #0085FF; background: #E0F2FF; }

SectionHeader

Title and description on the left, primary action on the right. One per content section.

<div class="section-header">
  <div>
    <h2>Workflow Runs</h2>
    <p>Every execution across your pipelines.</p>
  </div>
  <button class="btn btn--primary btn--md">New run</button>
</div>

.section-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.5rem;
}
.section-header h2 {
  font: 700 1.375rem/1.2 var(--dl-font-family-display);
  letter-spacing: -0.03em;
  color: #111827;
  margin: 0;
}
.section-header p { margin: 0.2rem 0 0; font-size: 0.85rem; color: #4B5563; }