Skip to main content
Copy for LLM

Theme: Minimal

The UI disappears behind the content. No radius, no shadows, no decorative borders. For data-dense interfaces, admin tools, and developer dashboards:

/* WireKit Theme: Minimal — Radical reduction, function over form.
   Inherits fully from the Default baseline (neutral palette, dark mode,
   WCAG-verified contrasts). Only structural tokens are overridden.

   Three values are set for accessibility rather than for the look, so they are
   the ones not to trim when adapting this:
   — ring-wk-width 2px → WCAG 2.4.11 minimum focus area
   — opacity-wk-hover 0.75 → WCAG 1.4.3 on white (~5.73:1)
   — bg-input neutral-200 → borderless inputs stay visible on a white background */
/* `:root` and `.dark`, NOT `@theme` / `@layer theme`, and the difference decides whether
   this block does anything at all.

   WireKit's own defaults sit inside `:where(:root)` — specificity 0 — precisely so a plain
   `:root` override wins whichever stylesheet the browser reads last. `@theme` compiles into
   `@layer theme`, and UNLAYERED CSS beats LAYERED CSS whatever the specificity: the defaults
   are unlayered, so a preset in `@theme` loses to them and silently does nothing except for
   the handful of tokens WireKit never declares.

   Nothing reports that. The CSS is valid, the custom properties resolve, and the page renders
   in the default theme while the developer reads their own preset in their own stylesheet. */
:root {
    /* Radius — square everything. calc() cascade makes sm/md/lg/xl all 0. */
    --radius-wk: 0px;

    /* Shadows — flat. Elevation via background color, not decoration.
       Transparent rather than none, which would take the focus ring with it. */
    --shadow-wk-sm:   0 0 0 0 transparent;
    --shadow-wk-md:   0 0 0 0 transparent;
    --shadow-wk-lg:   0 0 0 0 transparent;
    --shadow-wk-none: 0 0 0 0 transparent;

    /* Typography — headings recede, content leads. */
    --font-wk-heading-weight: 500;
    --font-wk-letter-spacing: 0.01em;

    /* Borders — none. bg-input differentiation replaces visual borders. */
    --border-wk-width: 0px;

    /* Focus ring — WCAG 2.4.11: 2px meets minimum area (perimeter × 2px).
       0px offset: ring sits flush — shows the boundary borders would. */
    --ring-wk-width:  2px;
    --ring-wk-offset: 0px;

    /* Motion — snappier than default (150ms). */
    --transition-wk-duration: 100ms;

    /* Hover — WCAG 1.4.3: 0.75 renders primary button text at ~5.73:1.
       Previous 0.7 yielded ~4.36:1 which failed AA on white backgrounds. */
    --opacity-wk-hover: 0.75;

    /* Input visibility — without borders, inputs need a visible background
       tint. neutral-200 (#e5e5e5) on white provides clear differentiation.
       Body text (neutral-950) on neutral-200: ~15:1 ✓
       Note: boundary contrast (1.26:1) is below WCAG 1.4.11's 3:1 —
       for full compliance, add a 1px border override (see tip below). */
    --color-wk-bg-input: var(--color-neutral-200);

    /* The two text tokens that live INSIDE that fill, stepped down with it.
       The stock neutral-500 is calibrated for a WHITE field (4.73:1) and reads
       3.76:1 on this tint — below the ≥ 4.5:1 the theming guide guarantees for
       text-subtle / text-placeholder on bg-input in every preset. neutral-600
       restores the floor at 6.19:1 and stays well clear of body text, so the
       hierarchy inside the field is unchanged. Dark needs no counterpart:
       neutral-400 on neutral-800 already reads 5.83:1. */
    --color-wk-text-subtle: var(--color-neutral-600);
    --color-wk-text-placeholder: var(--color-neutral-600);

    /* Overlay elevation — the LIGHT baseline sets bg-elevated to #fff, the
       same value as bg, and leans on the border and the shadow this theme has
       just zeroed. Dark carries a real step already (#0a0a0a page → #171717
       panel), so without this line an open dropdown, popover or command
       palette has a boundary in dark mode and none whatever in light: white
       on white, 0px border, no shadow. neutral-100 (#f5f5f5) restores the step
       at the magnitude the dark baseline uses — 1.09:1 against the page vs
       1.10:1 there — and stays one tone lighter than bg-input, so page <
       panel < input still reads as a hierarchy. It is a perceptual step, not
       a WCAG 1.4.11 boundary; for that, add the panel border in the tip below. */
    --color-wk-bg-elevated: var(--color-neutral-100);
}

.dark {
    /* Dark input bg: neutral-800 on neutral-950 page bg (~1.31:1).
       More visible than neutral-900 (~1.30:1). Same WCAG note applies. */
    --color-wk-bg-input: var(--color-neutral-800);

    /* The three light values above that dark mode must not keep. A `:root` value
       outranks WireKit's own dark default, so without these the panels stayed
       neutral-100 under light dark-mode text (1.04:1) and helper text stayed
       neutral-600 on a dark field.
       — bg-elevated neutral-900: the dark baseline's own step above the page
       — text-subtle / text-placeholder neutral-400: 5.83:1 on the neutral-800 fill,
         7.63:1 on the page, 6.91:1 on a panel */
    --color-wk-bg-elevated: var(--color-neutral-900);
    --color-wk-text-subtle: var(--color-neutral-400);
    --color-wk-text-placeholder: var(--color-neutral-400);
}

Minimal removes all shadows and borders. For full WCAG 1.4.11 compliance on form inputs (3:1 boundary contrast), give the fields their edge back. They already draw it in --color-wk-border-strong, so only the width is missing:

/* After WireKit's stylesheet: a 1px edge on every text field and field frame, and on every
   checkbox, radio and switch, whose edge is the control; nothing else. */
.wk-field,
.wk-field-frame,
.wk-choice-frame {
    --border-wk-width: 1px;
}

Without the last line an unchecked checkbox or radio is its fill alone, the off state of a toggle or the theme switch a pale track, and the radio rows of a dropdown lose their rings.

Dropdowns and popovers rely on bg-elevated for visual separation. For stronger overlay contrast, give the panel a 1px border with a closure. It is handed the panel's own classes, and this one changes only the width:

WireKit::personalize('dropdown.panel', [
    'base' => fn (string $classes): string => str_replace('border-[length:var(--border-wk-width)]', 'border', $classes),
]);

Not a plain string: a string replaces the whole block, and the base block of an input holds its fill, text colors, width and focus ring, the one of the dropdown panel its positioning, layer, fill and scrolling, all as well as the border.

Design notes

Minimal strips the interface down to its structure: zero radius, no shadows, no decorative borders, and snappier motion (100 ms). Elevation is communicated by background color alone rather than by decoration. The result is information-dense and tool-like — the deliberate opposite of a "designed" surface.

Best for: admin panels, data tables, developer dashboards, and internal tooling where scanning speed beats personality. Avoid it for customer-facing marketing pages, where warmth and visual hierarchy matter more than density.

Accessibility

Removing borders and shadows is a genuine accessibility risk, so Minimal compensates deliberately:

  • Inputs stay visible — without borders, inputs carry a neutral-200 background tint; body text on it reads at ~15:1, and the helper and placeholder tokens step down to neutral-600 so they read at 6.19:1 on that tint rather than the 3.76:1 the stock neutral-500 gives there.
  • Focus is unmissable — the ring is bumped to 2px to meet the WCAG 2.4.11 minimum focus-area requirement (a 1px ring would fail once borders are gone).
  • Hover stays legible — hover opacity is 0.75 so primary-button label text holds ~5.73:1 (WCAG 1.4.3 AA); the previous 0.7 dropped to ~4.36:1 and failed.

For full WCAG 1.4.11 boundary contrast (3:1) on form controls, add the 1px input border shown in the tip above.

Was this page helpful?

Thank you for your feedback!

Voting requires cookies or local storage. What we store