Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact

Get started

InstallationMCP server

Guides

CLICoding agentsUpdatesTheming

More

ComponentsChangelogllms.txt
InstallationMCP serverCLICoding agentsUpdatesTheming

Docs

Theming

Every component reads CSS variables, so one set of tokens restyles the whole library, in light and dark mode. Change a value once and every screen follows.

Tokens

74 variables: surfaces, text levels, brand and status tones (each with a soft variant), elevation, stacking layers and motion. Tailwind maps them to utilities like bg-surface, text-muted-foreground, bg-success-soft and shadow-floating. Left light, right dark:

Surfaces

  • --backgroundoklch(1.0000 0 0) / oklch(0 0 0)
  • --surface#FFFFFF / #1A1A1A
  • --card#EBEBEB / oklch(0.1822 0 0)
  • --popoveroklch(1.0000 0 0) / #262626
  • --primary#000 / oklch(0.9850 0 0)

Text and lines

  • --foregroundoklch(0.3211 0 0) / oklch(0.9219 0 0)
  • --muted-foregroundoklch(0.5200 0.0234 264.3637) / oklch(0.7155 0 0)
  • --borderoklch(0.9276 0.0058 264.5313) / oklch(0.3715 0 0)
  • --ringoklch(0.6000 0.2000 36.9340) / oklch(0.6617 0.2215 36.9340)

Tones

  • --brand#D63F00
  • --success#15803D
  • --warning#F5A524
  • --destructive#DC2626
  • --info#2563EB

Setup

npx wingo-ui@latest init merges the tokens into your global stylesheet, and add adds any a new component needs. Only missing names are added; values you already have stay. The full block is at /r/tokens.css (and in the MCP tool get_theme_tokens):

app/globals.css

:root {
  --background: oklch(1.0000 0 0);
  --foreground: oklch(0.3211 0 0);
  --card: #EBEBEB;
  --card-foreground: oklch(0.3211 0 0);
  --popover: oklch(1.0000 0 0);
  --popover-foreground: oklch(0.3211 0 0);
  --surface: #FFFFFF;
  --surface-foreground: oklch(0.3211 0 0);
  --canvas: #F6F7F9;
  --canvas-foreground: oklch(0.3211 0 0);
  --primary: #000;
  --primary-foreground: oklch(1.0000 0 0);
  --secondary: oklch(0.9670 0.0029 264.5419);
  --secondary-foreground: oklch(0.4461 0.0263 256.8018);
  --muted: oklch(0.9846 0.0017 247.8389);
  --muted-foreground: oklch(0.5200 0.0234 264.3637);
  --accent: oklch(0.9640 0.0230 45.0000);
  --accent-foreground: oklch(0.5200 0.1700 40.0000);
  --destructive: #DC2626;
  --destructive-foreground: oklch(1.0000 0 0);
  --destructive-soft: #FDEDED;
  --destructive-soft-foreground: #B42318;
  --brand: #D63F00;
  --brand-foreground: #FFFFFF;
  --brand-soft: #FFEFE6;
  --brand-soft-foreground: #B03400;
  /* … */
}

Dark mode

  • Class (recommended): dark values in .dark plus @custom-variant dark (&:is(.dark *));, toggled by next-themes with attribute="class".
  • System only: when your stylesheet already uses @media (prefers-color-scheme: dark), the CLI puts the dark values there instead.

Theme generator

Pick a brand color, radius, font and component defaults in the theme generator, preview them on real components, then export theme.json and apply it:

npx wingo-ui@latest theme apply ./theme.json

It replaces the values of the tokens the theme sets (light and dark) and adds the Tailwind mappings for new ones. It prints the component defaults and locale for UIProvider.

Open the theme generator

Component defaults

UIProvider (item ui-config, installed with every component) sets app-wide defaults per component and the locale for dates and numbers. Explicit props always win.

// app/layout.tsx
import { ThemeProvider } from "next-themes"
import { UIProvider } from "@/lib/ui-config"

<ThemeProvider attribute="class" defaultTheme="system" enableSystem disableTransitionOnChange>
  <UIProvider defaults={{ button: { radius: "full" }, input: { variant: "filled" } }} locale="en-US">
    {children}
  </UIProvider>
</ThemeProvider>

Backgrounds and contrast

Never put a card, tile, panel, input, select or date picker on a background of the same or a very similar shade. Every nesting level steps the fill: the page, then bg-surface shadow-raised, then bg-foreground/5 tiles and soft fields or bg-background wells. A border-only design (one color, only borders separate the parts) is allowed but not recommended.

Pages alternate a main background with a secondary band. PageBackdrop sets both: background (plain, soft, glow, aurora, grid, dots), backgroundColor, bandBackground (muted, tinted, gradient, dots) and bandColor. The theme does not change them; pick a tinted pair that suits the brand rather than pure black.

import { MarketingSection, PageBackdrop } from "@/components/blocks/marketing-section"

<PageBackdrop background="aurora" backgroundColor="#0ea5e9" bandBackground="tinted">
  <MarketingSection title="Features">{/* bg-surface cards */}</MarketingSection>
  <MarketingSection background="muted" title="Pricing">{/* a band: its cards are lifted */}</MarketingSection>
</PageBackdrop>

// or app-wide
<UIProvider defaults={{ "page-backdrop": { background: "aurora", backgroundColor: "#0ea5e9" } }}>

Rules of thumb

  • Semantic tokens only: no hex values or arbitrary colors in app code.
  • Neutral by default; the brand tone for the one main action on a screen.
  • Colored text uses the soft foreground tokens (text-success-soft-foreground) for contrast in both themes.
  • No card, panel, tile or field on a fill of its own shade: step the fill at every level.
  • Check every change in light and dark mode.
Installation guide

Related guides

  • Next.js and Tailwind CSS

    Tailwind v4 Dark Mode: Class Toggle, Tokens, next-themes

    Tailwind v4 dark mode with a class: the @custom-variant line, next-themes wiring, why dark: ignores your toggle, and tokens that keep both themes designed.

    Oct 13, 2026 · 9 min read

  • Next.js and Tailwind CSS

    Tailwind v4 Design Tokens: Colors, Dark Mode and Contrast

    Tailwind v4 design tokens from a production React library: @theme inline, semantic surfaces, status colors, dark mode and a contrast check you can run in CI.

    Oct 9, 2026 · 20 min read

  • Next.js and Tailwind CSS

    shadcn Tailwind v4 Migration: Step by Step From v3

    A shadcn tailwind v4 migration in order: the upgrade codemod, tailwind.config into @theme inline, hsl to oklch, border and ring fixes, and tw-animate-css.

    Nov 6, 2026 · 10 min read

All posts

On this page

TokensSetupDark modeTheme generatorComponent defaultsBackgrounds and contrastRules of thumb
WingoUI

Animated, configurable, mobile-first React components and blocks. Copy the source, make it yours, and let your coding agent build with it.

Product

  • Components
  • Templates
  • Pricing
  • AI agents
  • For teams
  • Theme generator

Resources

  • Docs
  • Contact
  • Programs
  • Blog
  • Changelog
  • Changelog RSS
  • llms.txt

Compare

  • Wingo UI vs paid kits
  • Wingo UI vs shadcn/ui
  • shadcn/ui alternatives
  • MUI alternatives
  • Tailwind Plus alternatives
  • Magic UI alternatives
  • Free components

Legal

  • Terms
  • Privacy
  • Refunds
  • License
  • Imprint

Component categories

  • Buttons & Actions
  • Inputs
  • Forms
  • Navigation
  • Overlays
  • Feedback
  • Data Display
  • Tables & Lists
  • Charts & Stats
  • Layout
  • Media
  • AI Kit
  • Text & Effects
  • Mobile
  • Commerce
  • Marketing Sections
  • Blocks
  • Hooks & Utilities

© 2026 Wingo UI

Wingo UI