Theming

Starting Point UI uses CSS variables for theming. Override any variable in your CSS to customize the look and feel. Use the theme editor in the top right to preview changes and export your theme.


Convention

We use a background and foreground convention for colors. The background variable is used for the background color of a component and the foreground variable is used for the text color.

Given the following CSS variables:

--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);

The background color of the following component will be var(--primary) and the foreground color will be var(--primary-foreground).

<div className="bg-primary text-primary-foreground">Hello</div>

List of variables

Here's the full list of variables available for customization:

:root {
  --radius: 0.625rem;
  --background: oklch(1 0 0);
  --foreground: oklch(0.145 0 0);
  --card: oklch(1 0 0);
  --card-foreground: oklch(0.145 0 0);
  --card-border: oklch(0.922 0 0);
  --card-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --card-radius: 0.875rem;
  --popover: oklch(1 0 0);
  --popover-foreground: oklch(0.145 0 0);
  --popover-border: oklch(0.922 0 0);
  --popover-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
  --popover-radius: 0.5rem;
  --primary: oklch(0.205 0 0);
  --primary-foreground: oklch(0.985 0 0);
  --secondary: oklch(0.97 0 0);
  --secondary-foreground: oklch(0.205 0 0);
  --muted: oklch(0.97 0 0);
  --muted-foreground: oklch(0.556 0 0);
  --accent: oklch(0.556 0 0);
  --accent-foreground: oklch(0.985 0 0);
  --destructive: oklch(0.577 0.245 27.325);
  --destructive-foreground: oklch(0.985 0 0);
  --border: oklch(0.922 0 0);
  --input: oklch(1 0 0 / 0%);
  --input-foreground: oklch(0.145 0 0);
  --input-placeholder: oklch(0.556 0 0);
  --input-border: oklch(0.922 0 0);
  --input-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --input-radius: 0.5rem;
  --ring: oklch(0.708 0 0);
  --sidebar: oklch(0.985 0 0);
  --sidebar-foreground: oklch(0.145 0 0);
  --sidebar-primary: oklch(0.205 0 0);
  --sidebar-primary-foreground: oklch(0.985 0 0);
  --sidebar-accent: oklch(0.97 0 0);
  --sidebar-accent-foreground: oklch(0.205 0 0);
  --sidebar-border: oklch(0.922 0 0);
  --sidebar-ring: oklch(0.708 0 0);
  --sidebar-width: 16rem;
  --btn: oklch(1 0 0);
  --btn-foreground: oklch(0.145 0 0);
  --btn-border: oklch(0.922 0 0);
  --btn-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --btn-radius: 0.5rem;
  --badge-radius: 9999px;
  --track: oklch(0.922 0 0);
  --thumb: oklch(1 0 0);
  --font-heading: var(--font-sans);
}
 
.dark {
  --background: oklch(0.145 0 0);
  --foreground: oklch(0.985 0 0);
  --card: oklch(0.205 0 0);
  --card-foreground: oklch(0.985 0 0);
  --card-border: oklch(1 0 0 / 10%);
  --card-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --popover: oklch(0.205 0 0);
  --popover-foreground: oklch(0.985 0 0);
  --popover-border: oklch(1 0 0 / 10%);
  --popover-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
  --primary: oklch(0.922 0 0);
  --primary-foreground: oklch(0.205 0 0);
  --secondary: oklch(0.269 0 0);
  --secondary-foreground: oklch(0.985 0 0);
  --muted: oklch(0.269 0 0);
  --muted-foreground: oklch(0.708 0 0);
  --accent: oklch(0.708 0 0);
  --accent-foreground: oklch(0.205 0 0);
  --destructive: oklch(0.704 0.191 22.216);
  --destructive-foreground: oklch(0.985 0 0);
  --border: oklch(1 0 0 / 10%);
  --input: oklch(1 0 0 / 4.5%);
  --input-foreground: oklch(0.985 0 0);
  --input-placeholder: oklch(0.708 0 0);
  --input-border: oklch(1 0 0 / 15%);
  --input-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --ring: oklch(0.556 0 0);
  --sidebar: oklch(0.205 0 0);
  --sidebar-foreground: oklch(0.985 0 0);
  --sidebar-primary: oklch(0.922 0 0);
  --sidebar-primary-foreground: oklch(0.205 0 0);
  --sidebar-accent: oklch(0.269 0 0);
  --sidebar-accent-foreground: oklch(0.985 0 0);
  --sidebar-border: oklch(1 0 0 / 10%);
  --sidebar-ring: oklch(0.556 0 0);
  --btn: oklch(1 0 0 / 4.5%);
  --btn-foreground: oklch(0.985 0 0);
  --btn-border: oklch(1 0 0 / 15%);
  --btn-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --track: oklch(1 0 0 / 12%);
  --thumb: oklch(1 0 0);
}

Customizing the theme

Override any of these variables after importing the library styles:

app/globals.css
@import "tailwindcss";
@import "starting-point-ui";
 
:root {
  --primary: oklch(0.55 0.2 250);
  --primary-foreground: oklch(1 0 0);
  --ring: oklch(0.55 0.2 250);
}
 
.dark {
  --primary: oklch(0.65 0.18 250);
  --primary-foreground: oklch(0.15 0 0);
  --ring: oklch(0.65 0.18 250);
}

Fonts

The library uses two font variables:

  • --font-sans — Tailwind's default body font token. Defaults to the system sans-serif stack. Set this to use a custom body font.
  • --font-heading — applied to h1 through h6. Inherits from --font-sans by default, so headings follow the body font unless you override it.

Override them to use different fonts:

:root {
  --font-sans: "Inter", sans-serif;
  --font-heading: "Playfair Display", serif;
}

Adding new colors

To add new colors, define them in your CSS and use the @theme inline directive to make them available as Tailwind utilities:

app/globals.css
:root {
  --warning: oklch(0.84 0.16 84);
  --warning-foreground: oklch(0.28 0.07 46);
}
 
.dark {
  --warning: oklch(0.41 0.11 46);
  --warning-foreground: oklch(0.99 0.02 95);
}
 
@theme inline {
  --color-warning: var(--warning);
  --color-warning-foreground: var(--warning-foreground);
}

You can now use the warning utility class in your components:

<div className="bg-warning text-warning-foreground" />