DocumentationComponentsTheme Creator
Theme CreatorGitHubIntroduction
InstallationUsageThemingMotion
Components
AI agentsContributing

Theming

Customize Tessina UI to match your brand

Customizing Colors

Tessina UI uses CSS variables for theming. You can customize colors by modifying the CSS variables in your global CSS file.

Color Tokens

All color tokens use HSL format:

example.css
:root {
  --background: 0 0% 100%;        /* Page background */
  --foreground: 0 0% 3.9%;        /* Main text color */
  --primary: 0 0% 9%;             /* Primary brand color */
  --primary-foreground: 0 0% 98%; /* Text on primary */
  --secondary: 0 0% 96.1%;        /* Secondary color */
  --destructive: 0 84.2% 60.2%;   /* Error/danger color */
  --border: 0 0% 89.8%;           /* Border color */
  --radius: 0.5rem;               /* Border radius */
}

Example: Blue Theme

example.css
:root {
  --primary: 221 83% 53%;          /* Blue */
  --primary-foreground: 210 40% 98%;
}

Example: Green Theme

example.css
:root {
  --primary: 142 71% 45%;          /* Green */
  --primary-foreground: 144 61% 98%;
}

Dark Mode

Tessina UI includes dark mode support. Override the .dark class variables:

example.css
.dark {
  --background: 0 0% 3.9%;
  --foreground: 0 0% 98%;
  --primary: 0 0% 98%;
  --primary-foreground: 0 0% 9%;
}

Enabling Dark Mode

Use a theme provider like next-themes:

example.tsx
import { ThemeProvider } from "next-themes";

export default function RootLayout({ children }) {
  return (
    <html suppressHydrationWarning>
      <body>
        <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
          {children}
        </ThemeProvider>
      </body>
    </html>
  );
}

Border Radius

Customize the global border radius:

example.css
:root {
  --radius: 0rem;     /* Square corners */
  --radius: 0.5rem;   /* Default (8px) */
  --radius: 1rem;     /* More rounded (16px) */
}

Motion

Transitions read a small set of motion tokens, named by role rather than by value, so one override retunes every component that shares a motion:

TokenUtilityDefaultUsed by
--ease-gestureease-gesturecubic-bezier(0.32, 0.72, 0, 1)Drawer, ActionSheet, the mobile Sidebar sheet and Carousel's snap — enter and exit, panel and scrim
--transition-duration-gestureduration-gesture450msTheir enter
--transition-duration-gesture-exitduration-gesture-exit350msTheir exit, shortened by how hard a swipe was flicked
--ease-emphasizedease-emphasizedcubic-bezier(0.16, 1, 0.3, 1)Modal's enter
--ease-emphasized-softease-emphasized-softcubic-bezier(0.22, 1, 0.36, 1)The fullscreen Modal, and the TimePicker and TimeRange popups
--ease-indicatorease-indicatora spring, as linear(…)BottomNav's sliding indicator: from rest, a 1.5% overshoot
--transition-duration-indicatorduration-indicator350msThe spring's duration. linear() stretches over whatever duration it runs, so change the two together

Everything else uses Tailwind's ease-out / ease-in and its numeric duration scale. Override a token on :root:

example.css
:root {
  --ease-gesture: cubic-bezier(0.2, 0.9, 0.1, 1); /* a snappier sheet */
  --transition-duration-gesture: 380ms;
}

Every movement transition stops under prefers-reduced-motion: reduce, and an override cannot turn one back on. Your own classes can use the same tokens. Gate the duration along with the transition, as the components do: motion-safe:transition-transform motion-safe:duration-gesture ease-gesture.

Per-Component Customization

You can also customize individual components using Tailwind classes:

example.tsx
<Button className="rounded-full bg-purple-600">
  Custom Button
</Button>
UsageMotion

On this page

Customizing ColorsColor TokensExample: Blue ThemeExample: Green ThemeDark ModeEnabling Dark ModeBorder RadiusMotionPer-Component Customization