Supasheet.

Theming

Customize the look and feel of Supasheet

Overview

Supasheet uses Tailwind CSS v4 and CSS variables for theming, making it easy to customize colors, typography, and overall appearance. All theme configuration lives in src/styles.css.

Color System

CSS Variables

Supasheet uses OKLCH color space for better perceptual uniformity and color manipulation. Colors are defined in src/styles.css:

: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);
  --popover: oklch(1 0 0);
  --popover-foreground: oklch(0.145 0 0);
  --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.97 0 0);
  --accent-foreground: oklch(0.205 0 0);
  --destructive: oklch(0.577 0.245 27.325);
  --border: oklch(0.922 0 0);
  --input: oklch(0.922 0 0);
  --ring: oklch(0.708 0 0);
  --chart-1: var(--color-blue-300);
  --chart-2: var(--color-blue-500);
  --chart-3: var(--color-blue-600);
  --chart-4: var(--color-blue-700);
  --chart-5: var(--color-blue-800);
  --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);
  --surface: oklch(0.98 0 0);
  --surface-foreground: var(--foreground);
  --code: var(--surface);
  --code-foreground: var(--surface-foreground);
  --code-highlight: oklch(0.96 0 0);
  --code-number: oklch(0.56 0 0);
  --selection: oklch(0.145 0 0);
  --selection-foreground: oklch(1 0 0);
}

.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);
  --popover: oklch(0.269 0 0);
  --popover-foreground: oklch(0.985 0 0);
  --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.371 0 0);
  --accent-foreground: oklch(0.985 0 0);
  --destructive: oklch(0.704 0.191 22.216);
  --border: oklch(1 0 0 / 10%);
  --input: oklch(1 0 0 / 15%);
  --ring: oklch(0.556 0 0);
  --chart-1: var(--color-blue-300);
  --chart-2: var(--color-blue-500);
  --chart-3: var(--color-blue-600);
  --chart-4: var(--color-blue-700);
  --chart-5: var(--color-blue-800);
  --sidebar: oklch(0.205 0 0);
  --sidebar-foreground: oklch(0.985 0 0);
  --sidebar-primary: oklch(0.488 0.243 264.376);
  --sidebar-primary-foreground: oklch(0.985 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.439 0 0);
  --surface: oklch(0.2 0 0);
  --surface-foreground: oklch(0.708 0 0);
  --code: var(--surface);
  --code-foreground: var(--surface-foreground);
  --code-highlight: oklch(0.27 0 0);
  --code-number: oklch(0.72 0 0);
  --selection: oklch(0.922 0 0);
  --selection-foreground: oklch(0.205 0 0);
}

Understanding OKLCH

OKLCH provides better perceptual uniformity compared to HSL:

  • L (Lightness): 0 (black) to 1 (white)
  • C (Chroma): Color intensity, typically 0 to 0.4
  • H (Hue): Angle in degrees (0-360)
/* Examples */
oklch(0.5 0.2 240)    /* Medium blue */
oklch(0.8 0.15 120)   /* Light green */
oklch(0.3 0.1 0)      /* Dark gray */

Color Categories

Supasheet includes several color categories:

Base Colors

  • background, foreground - Main page colors
  • card, card-foreground - Card component colors
  • popover, popover-foreground - Popover/dropdown colors

Interactive Colors

  • primary, primary-foreground - Primary actions and CTAs
  • secondary, secondary-foreground - Secondary actions
  • accent, accent-foreground - Highlighted elements
  • destructive - Destructive actions (delete, remove)

UI Elements

  • border - Border colors
  • input - Input field borders
  • ring - Focus ring colors
  • muted, muted-foreground - Muted/disabled states

Sidebar Colors

  • sidebar, sidebar-foreground - Sidebar background
  • sidebar-primary, sidebar-primary-foreground - Sidebar primary actions
  • sidebar-accent, sidebar-accent-foreground - Sidebar highlights
  • sidebar-border, sidebar-ring - Sidebar borders and focus

Code & Surface Colors

  • surface, surface-foreground - Secondary surface colors
  • code, code-foreground - Code block background
  • code-highlight - Code line highlights
  • code-number - Line numbers
  • selection, selection-foreground - Text selection

Chart Colors

  • chart-1 through chart-5 - Data visualization colors

Customizing Colors

To customize the theme, modify the CSS variables in src/styles.css:

/* Example: Customizing primary color */
:root {
  --primary: oklch(0.5 0.2 240);  /* Custom blue */
}

.dark {
  --primary: oklch(0.65 0.2 240); /* Lighter for dark mode */
}

Custom brand colors:

:root {
  --brand-primary: oklch(0.55 0.25 240);    /* Vibrant blue */
  --brand-secondary: oklch(0.6 0.22 280);   /* Purple */
  --brand-accent: oklch(0.65 0.2 150);      /* Green */
}

.dark {
  --brand-primary: oklch(0.65 0.25 240);
  --brand-secondary: oklch(0.7 0.22 280);
  --brand-accent: oklch(0.75 0.2 150);
}

Using Theme Colors

In Tailwind Classes

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

<div className="bg-secondary text-secondary-foreground">
  Secondary background
</div>

<button className="bg-destructive text-destructive-foreground">
  Delete
</button>

<aside className="bg-sidebar text-sidebar-foreground">
  Sidebar content
</aside>

<div className="bg-surface text-surface-foreground">
  Secondary surface
</div>

<pre className="bg-code text-code-foreground">
  Code block
</pre>

Tailwind CSS v4 Configuration

Supasheet uses Tailwind CSS v4 with the @theme inline directive in src/styles.css:

@import "tailwindcss";

@theme inline {
  --breakpoint-3xl: 1600px;
  --breakpoint-4xl: 2000px;
  --font-sans: var(--font-sans);
  --font-mono: var(--font-mono);
  --radius-sm: calc(var(--radius) - 4px);
  --radius-md: calc(var(--radius) - 2px);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) + 4px);
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  /* ... other color mappings */
}

Custom Variants

Supasheet includes custom Tailwind variants:

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

Use them in your components:

<div className="bg-white dark:bg-gray-900">
  Responsive to dark mode
</div>

<div className="relative fixed:absolute">
  Changes based on layout type
</div>

Best Practices

1. Use OKLCH for Better Color Manipulation

/* Good ✅ - OKLCH provides better perceptual uniformity */
:root {
  --brand-color: oklch(0.55 0.2 240);
  --brand-hover: oklch(0.45 0.2 240);  /* Darker, same hue */
  --brand-light: oklch(0.75 0.15 240); /* Lighter, reduced chroma */
}

/* Less ideal - RGB/Hex harder to adjust perceptually */
:root {
  --brand-color: #3b82f6;
  --brand-hover: #2563eb;
}

2. Consistent Naming Convention

/* Good ✅ - Semantic naming with foreground pairs */
--primary
--primary-foreground
--secondary
--secondary-foreground
--sidebar
--sidebar-foreground

/* Bad ❌ - Color-based naming */
--blue
--text-on-blue
--light-gray
--dark-text

3. Theme Scoping with Data Attributes

/* Good ✅ - Scoped to data attribute */
[data-theme='custom'] {
  --primary: oklch(0.5 0.2 240);
}

4. Maintain Accessibility

/* Good ✅ - Sufficient contrast between background and foreground */
:root {
  --background: oklch(1 0 0);        /* White */
  --foreground: oklch(0.145 0 0);    /* Very dark gray */
}

/* Bad ❌ - Insufficient contrast */
:root {
  --background: oklch(0.8 0 0);      /* Light gray */
  --foreground: oklch(0.6 0 0);      /* Medium gray */
}

5. Use Alpha Channel for Transparency

/* Good ✅ - OKLCH with alpha */
:root {
  --overlay: oklch(0 0 0 / 50%);
  --border: oklch(1 0 0 / 10%);
}

.dark {
  --border: oklch(1 0 0 / 15%);
}

Next Steps