Styling

Get started with styling your app.

To build the web user interface, TurboStarter comes with Tailwind CSS and Radix UI pre-configured.

Why Tailwind CSS and Radix UI?

The combination of Tailwind CSS and Radix UI gives ready-to-use, accessible UI components that can be fully customized to match your brand's design.

Tailwind configuration

In the packages/ui/shared/src/styles directory, you will find shared CSS files with Tailwind CSS configuration. To change global styles, you can edit the files in this folder.

Here is an example of a shared CSS file that includes the Tailwind CSS configuration:

packages/ui/shared/src/styles/globals.css
@import "tailwindcss";
@import "./themes.css";

@custom-variant dark (&:is(.dark *));

:root {
  --radius: 0.65rem;
}

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-card: var(--card);
  --color-card-foreground: var(--card-foreground);
  --color-popover: var(--popover);
  --color-popover-foreground: var(--popover-foreground);
  --color-primary: var(--primary);
  --color-primary-foreground: var(--primary-foreground);
  --color-secondary: var(--secondary);
  --color-secondary-foreground: var(--secondary-foreground);
  --color-muted: var(--muted);
  --color-muted-foreground: var(--muted-foreground);

  ...
}

For colors, we rely strictly on CSS Variables in OKLCH format to allow for easy theme management without the need for any JavaScript.

Also, each app has its own globals.css file, which extends the shared config and allows you to override the global styles.

Here is an example of an app's globals.css file:

apps/web/src/assets/styles/globals.css
@import "@turbostarter/ui/globals.css";
@import "@turbostarter/ui-web/globals.css";

@theme inline {
  /* Overridden theme variables for the app */
  --background: oklch(0.98 0.01 80);
  --foreground: oklch(0.22 0.03 120);
  --card: oklch(0.97 0.02 50);
  --card-foreground: oklch(0.18 0.01 280);
  ...
}

This way, we maintain a separation of concerns and a clear structure for the Tailwind CSS configuration.

Themes

TurboStarter comes with 9+ predefined themes, which you can use to quickly change the look and feel of your app.

They're defined in the packages/ui/shared/src/styles/themes directory. Each theme is a set of variables that can be overridden:

packages/ui/shared/src/styles/themes/orange.css
.theme-orange {
  --background: oklch(1 0 0);
  --foreground: oklch(0.141 0.005 285.823);
  --card: oklch(1 0 0);
  --card-foreground: oklch(0.141 0.005 285.823);
  ...
}

Feel free to add your own themes or override the existing ones to match your brand's identity.

To apply a theme to your app, you can apply a specific theme class to the body element:

apps/web/src/app/layout.tsx
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html>
      <body className="theme-orange">{children}</body>
    </html>
  );
}

Dark mode

TurboStarter comes with built-in dark mode support.

Each theme has a corresponding set of dark mode variables, which are used to switch the theme to its dark mode counterpart.

packages/ui/shared/src/styles/themes/orange.css
.theme-orange {
  ...
  @variant dark {
    --background: oklch(0.141 0.005 285.823);
    --foreground: oklch(0.985 0 0);
    --card: oklch(0.21 0.006 285.885);
    --card-foreground: oklch(0.985 0 0);
    ...
  }
}

Because the dark variant is defined to use a class (@custom-variant dark (&:is(.dark *))) in the shared Tailwind configuration, we need to add the dark class to the html element to apply dark mode styles.

For this purpose, we're using the next-themes package under the hood to handle user preference management.

apps/web/src/providers/theme.tsx
export const ThemeProvider = memo<ThemeProviderProps>(({ children }) => {
  return (
    <NextThemeProvider
      attribute="class"
      defaultTheme={appConfig.theme.mode}
      enableSystem
    >
      {children}
      <ThemeConfigProvider />
    </NextThemeProvider>
  );
});

You can also define the default theme mode and color in the app configuration.

How is this guide?

Last updated on

On this page

Ship your startup everywhere. In minutes.