Skip to main content
Copy for LLM

Theme: Soft

Warm, rounded, developer-facing SaaS aesthetic. Inspired by Notion, Loom, Pitch. Requires config/wirekit.php → 'sans' => 'dm-sans':

/* WireKit Theme: Soft — Warm, rounded, developer SaaS aesthetic.
   Inherits from Default: neutral palette, dark-mode colors, sizing,
   border-wk-width 1px, WCAG-verified text/bg contrasts.

   Prerequisite: config/wirekit.php → 'sans' => 'dm-sans'
   WCAG: All violet pairs ≥ AA — verify exact ratios via DevTools
   against actual Tailwind v4 OKLCH values.

   IMPORTANT: .dark block includes shadow overrides to prevent
   Default's dark shadows (2/12/32px blur) from overriding Soft's
   wider blur values (8/20/40px). Without this, the "airy" feeling
   disappears in dark mode. */
/* `: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 {
    /* Font — DM Sans: warmer and rounder than Inter.
       letter-spacing reset to 0em — overrides Default's -0.01em.
       DM Sans has naturally friendly proportions. */
    --font-wk-sans:           'DM Sans', ui-sans-serif, system-ui, sans-serif;
    --font-wk-letter-spacing: 0em;

    /* Heading — bold for strong hierarchy. */
    --font-wk-heading-weight: 700;

    /* Radius — 0.75rem base → sm: 0.5625rem, md: 0.75rem,
       lg: 0.9375rem, xl: 1.5rem (signature Soft rounding). */
    --radius-wk: 0.75rem;

    /* Shadows — soft, airy, diffuse light (wider blur than Default).
       Dark-mode shadows MUST be set in .dark block below. */
    --shadow-wk-sm: 0 2px 8px -1px rgba(0, 0, 0, 0.06),
                    0 1px 2px -1px rgba(0, 0, 0, 0.04);
    --shadow-wk-md: 0 8px 20px -4px rgba(0, 0, 0, 0.08),
                    0 3px 8px -2px rgba(0, 0, 0, 0.04);
    --shadow-wk-lg: 0 20px 40px -8px rgba(0, 0, 0, 0.10),
                    0 8px 16px -4px rgba(0, 0, 0, 0.06);

    /* Motion — 200ms ease-out decelerate: starts fast, settles gently. */
    --transition-wk-duration: 200ms;
    --transition-wk-easing:   cubic-bezier(0, 0, 0.2, 1);

    /* Accent — Violet.
       white on violet-600: ≥ 5:1 (AA ✓)
       white on violet-700 (hover): ≥ 6:1 (AAA ✓)
       violet-600 ring on white: ≥ 3:1 (UI ✓) */
    --color-wk-accent:         var(--color-violet-600);
    --color-wk-accent-hover:   var(--color-violet-700);
    --color-wk-accent-content: var(--color-violet-700);
    --color-wk-accent-fg:      var(--color-white);
    --color-wk-ring:           var(--color-violet-600);
}

.dark {
    /* Accent dark — accent-fg (neutral-900) inherited from Default.
       neutral-900 on violet-400: ≥ 6:1 (AAA ✓)
       neutral-900 on violet-300 (hover): ≥ 9:1 (AAA ✓) */
    /* The label ON the accent, pinned here as well as in the light block. It was set
       only in `:root`, and a plain `:root` beats the base stylesheet's `:where(.dark)` —
       so white bled into dark mode and sat on violet-400 at 2.72:1. A near-black label
       reaches 6.59:1 on the same fill. */
    --color-wk-accent-fg:      var(--color-neutral-900);
    --color-wk-accent:         var(--color-violet-400);
    --color-wk-accent-hover:   var(--color-violet-300);
    --color-wk-accent-content: var(--color-violet-300);
    --color-wk-ring:           var(--color-violet-400);

    /* Shadows dark — MUST override to keep Soft's wider blur values.
       Without this, Default's .dark shadows (2/12/32px blur) win
       the cascade and the airy feeling disappears. */
    --shadow-wk-sm: 0 2px 8px -1px rgba(0, 0, 0, 0.25),
                    0 1px 2px -1px rgba(0, 0, 0, 0.20);
    --shadow-wk-md: 0 8px 20px -4px rgba(0, 0, 0, 0.30),
                    0 3px 8px -2px rgba(0, 0, 0, 0.20);
    --shadow-wk-lg: 0 20px 40px -8px rgba(0, 0, 0, 0.40),
                    0 8px 16px -4px rgba(0, 0, 0, 0.25);
}

Design notes

Soft is warm and rounded: DM Sans for friendlier letterforms, a 0.75rem radius, and wide, diffuse shadows that give surfaces an airy, lifted feel — paired with an approachable violet accent. The mood is drawn from tools like Notion, Loom, and Pitch.

The accent itself is Tailwind's own violet-600 rather than a hue picked to match that mood — the preset reads var(--color-violet-600) directly, so it moves with your Tailwind version instead of drifting away from it. Cupertino anchors on Apple's system blue and Material on MD3's indigo for the same reason: a preset accent that names where it comes from is one you can reason about when you retint it. Aurora's Violet retint lands on the same hue, so the library has one violet rather than two that are nearly the same.

Best for: developer-facing SaaS, onboarding flows, documentation, and any product that wants to feel approachable. Avoid it for ultra-dense data UIs, where the generous radius and shadow spread cost vertical rhythm.

Accessibility

Every violet accent pairing clears WCAG AA: white on violet-600 is ≥5:1, the violet-700 hover state ≥6:1 (AAA), and the violet-600 focus ring ≥3:1 for UI contrast. Dark mode shifts the accent to violet-400/300 (≥6:1 / ≥9:1 against the dark surface) and re-declares the wide shadows so the airy feel survives the cascade. Because the accent is theme-overridable, re-verify the exact ratios against your built OKLCH values if you retune the violet.

Was this page helpful?

Thank you for your feedback!

Voting requires cookies or local storage. What we store