Skip to Content
Theming

Theming

Numa centralizes UI tokens in @numa/config/ui/theme. ThemeVariables injects them as CSS variables at the root.

How it works

  1. config/ui/theme.ts — single source of truth for all theme values
  2. ThemeVariables — injected at app root in app/layout.tsx, converts config to CSS variables
  3. Components — use var(--radius-lg), var(--ui-border-width-input), etc.

What you can customize

PropertyDescriptionExample
radius.baseCorner radius for buttons, inputs, cards6 (6px) or 10 (10px)
radius.scaleMultipliers for sm/md/lg/xl variants{ sm: 0.6, md: 0.8, lg: 1 }
border.inputInput border width1 or 2
border.buttonButton border width1
border.cardCard/container border width1
ring.widthFocus ring width3
sizes.inputInput height, padding, icon size{ height: 32, paddingX: 10 }
sizes.buttonButton heights per size variant{ default: 32, sm: 28, lg: 36 }

Quick example

// config/ui/theme.ts export const uiTheme = { radius: { base: 6, }, border: { input: 2, button: 1, card: 1, }, };

Using theme variables in components

When adding or modifying components, use theme variables instead of hardcoded values:

Use caseCSS variable
Border radiusrounded-[var(--radius-lg)]
Border width[border-width:var(--ui-border-width-input)]
Focus ringring-[var(--ui-ring-width)]
Input heighth-[var(--ui-input-height-default)]

Colors

Color theming uses shadcn color tokens in globals.css (:root and .dark). Edit those for brand colors, or use config/styles/colors.ts for app-specific tokens.

Tailwind v4

Numa uses Tailwind CSS v4 with CSS-first configuration. There is no tailwind.config.js. Instead:

  • Theme is defined in packages/ui/globals.css using @theme and @source directives
  • PostCSS plugin @tailwindcss/postcss handles compilation
  • Apps import this via their own globals.css
Last updated on