blokhaus

Theming

Customize Blokhaus's appearance using CSS custom properties.

Blokhaus uses CSS custom properties (design tokens) as its theming system. Every token is prefixed with --blokhaus- to prevent collisions with your host application's styles. This approach gives you full visual ownership without forking any components.

How it works

All Blokhaus components reference CSS variables instead of hardcoded color values. You control the look and feel by overriding these variables in your own CSS. This is the same pattern used by shadcn/ui.

Installing the token file

Copy tokens.css into your project and import it in your root layout or global stylesheet:

styles/blokhaus-tokens.css
@import "./blokhaus-tokens.css";

Or import it directly in your layout:

app/layout.tsx
import "./styles/blokhaus-tokens.css";

Full token reference

Surface tokens

These control the primary background and foreground colors of the editor.

TokenDefault (Light)Description
--blokhaus-backgroundhsl(0 0% 100%)Editor background
--blokhaus-foregroundhsl(222.2 84% 4.9%)Primary text color

Editor chrome

These tokens style borders, focus rings, and muted/secondary elements.

TokenDefault (Light)Description
--blokhaus-borderhsl(214.3 31.8% 91.4%)Border color for editor containers
--blokhaus-ringhsl(221.2 83.2% 53.3%)Focus ring color
--blokhaus-mutedhsl(210 40% 96.1%)Muted background (e.g., code blocks)
--blokhaus-muted-foregroundhsl(215.4 16.3% 46.9%)Muted text color

Interactive tokens

TokenDefault (Light)Description
--blokhaus-accenthsl(221.2 83.2% 53.3%)Accent color for interactive elements
--blokhaus-accent-foregroundhsl(0 0% 100%)Text on accent backgrounds

Status tokens

TokenDefault (Light)Description
--blokhaus-destructivehsl(0 84.2% 60.2%)Destructive action color
--blokhaus-ai-streamhsl(220 60% 50%)AI preview block accent

Radius

TokenDefaultDescription
--blokhaus-radius0.5remDefault border radius for all components

Typography

TokenDefaultDescription
--blokhaus-font-sansui-sans-serif, system-ui, sans-serifSans-serif font stack
--blokhaus-font-serifGeorgia, "Times New Roman", serifSerif font stack
--blokhaus-font-monoui-monospace, monospaceMonospace font stack
--blokhaus-font-hand"Caveat", cursiveHandwriting font stack

Text colors

These tokens provide a Notion-style palette for text color formatting via the ColorPlugin.

TokenDefault (Light)Description
--blokhaus-text-gray#9b9a97Gray text
--blokhaus-text-brown#64473aBrown text
--blokhaus-text-orange#d9730dOrange text
--blokhaus-text-yellow#dfab01Yellow text
--blokhaus-text-green#0f7b6cGreen text
--blokhaus-text-blue#0b6e99Blue text
--blokhaus-text-purple#6940a5Purple text
--blokhaus-text-pink#ad1a72Pink text
--blokhaus-text-red#e03e3eRed text

Highlight colors

Background highlight colors for text, used alongside the text color tokens.

TokenDefault (Light)Description
--blokhaus-highlight-gray#ebecedGray highlight
--blokhaus-highlight-brown#e9e5e3Brown highlight
--blokhaus-highlight-orange#faebddOrange highlight
--blokhaus-highlight-yellow#fbf3dbYellow highlight
--blokhaus-highlight-green#ddedeaGreen highlight
--blokhaus-highlight-blue#ddebf1Blue highlight
--blokhaus-highlight-purple#eae4f2Purple highlight
--blokhaus-highlight-pink#f4dfebPink highlight
--blokhaus-highlight-red#fbe4e4Red highlight

Table tokens

TokenDefault (Light)Description
--blokhaus-table-borderhsl(214.3 31.8% 91.4%)Table cell borders
--blokhaus-table-header-bghsl(210 40% 96.1%)Table header row background
--blokhaus-table-selectionhsla(221.2 83.2% 53.3% / 0.1)Table cell selection overlay
--blokhaus-table-resize-handlehsl(221.2 83.2% 53.3%)Column resize handle color

Popover / floating UI chrome

TokenDefault (Light)Description
--blokhaus-popover-bgrgba(255, 255, 255, 0.82)Popover background with blur
--blokhaus-popover-borderrgba(0, 0, 0, 0.06)Popover border
--blokhaus-popover-shadow(composite)Popover box shadow
--blokhaus-icon-secondaryrgba(0, 0, 0, 0.55)Secondary icon color
--blokhaus-separatorrgba(0, 0, 0, 0.1)Separator line color
--blokhaus-hover-bgrgba(0, 0, 0, 0.04)Hover background for interactive items

Overriding tokens

Override any token by redefining it in your CSS. Place your overrides after the Blokhaus token import:

styles/globals.css
@import "./blokhaus-tokens.css";

:root {
  /* Use your brand's blue as the accent */
  --blokhaus-accent: hsl(210 100% 50%);
  --blokhaus-accent-foreground: hsl(0 0% 100%);

  /* Rounded corners */
  --blokhaus-radius: 0.75rem;

  /* Custom font */
  --blokhaus-font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
}

Dark mode

Blokhaus supports dark mode via the .dark class on a parent element. The token file includes a complete .dark block that redefines every token for dark backgrounds:

tokens.css (dark mode excerpt)
.dark {
  --blokhaus-background: hsl(222.2 84% 4.9%);
  --blokhaus-foreground: hsl(210 40% 98%);
  --blokhaus-border: hsl(217.2 32.6% 17.5%);
  --blokhaus-ring: hsl(224.3 76.3% 48%);
  --blokhaus-muted: hsl(217.2 32.6% 17.5%);
  --blokhaus-muted-foreground: hsl(215 20.2% 65.1%);
  --blokhaus-accent: hsl(224.3 76.3% 48%);
  --blokhaus-accent-foreground: hsl(210 40% 98%);
  --blokhaus-destructive: hsl(0 62.8% 30.6%);
  /* ... all tokens redefined */
}

Toggle dark mode by adding or removing the .dark class on your <html> or a parent element:

components/ThemeToggle.tsx
"use client";

import { useEffect, useState } from "react";

export function ThemeToggle() {
  const [dark, setDark] = useState(false);

  useEffect(() => {
    document.documentElement.classList.toggle("dark", dark);
  }, [dark]);

  return (
    <button onClick={() => setDark((d) => !d)}>
      {dark ? "Light mode" : "Dark mode"}
    </button>
  );
}

Tailwind CSS integration

Blokhaus's Tailwind configuration maps CSS variables to utility classes. If you are extending Tailwind in your own project, you can reference the same variables:

tailwind.config.ts
import type { Config } from "tailwindcss";

export default {
  theme: {
    extend: {
      colors: {
        "blokhaus-background": "var(--blokhaus-background)",
        "blokhaus-foreground": "var(--blokhaus-foreground)",
        "blokhaus-border": "var(--blokhaus-border)",
        "blokhaus-ring": "var(--blokhaus-ring)",
        "blokhaus-muted": "var(--blokhaus-muted)",
        "blokhaus-muted-foreground": "var(--blokhaus-muted-foreground)",
        "blokhaus-accent": "var(--blokhaus-accent)",
        "blokhaus-accent-foreground": "var(--blokhaus-accent-foreground)",
        "blokhaus-destructive": "var(--blokhaus-destructive)",
      },
      borderRadius: {
        blokhaus: "var(--blokhaus-radius)",
      },
      fontFamily: {
        "blokhaus-sans": "var(--blokhaus-font-sans)",
        "blokhaus-mono": "var(--blokhaus-font-mono)",
        "blokhaus-serif": "var(--blokhaus-font-serif)",
      },
    },
  },
} satisfies Config;

This lets you use classes like bg-blokhaus-accent, text-blokhaus-foreground, and rounded-blokhaus in your own components.

Creating a custom theme

Here is a complete example of a warm, earthy theme:

styles/earth-theme.css
:root {
  /* Surface */
  --blokhaus-background: hsl(30 20% 98%);
  --blokhaus-foreground: hsl(20 15% 15%);

  /* Chrome */
  --blokhaus-border: hsl(30 15% 88%);
  --blokhaus-ring: hsl(25 70% 50%);
  --blokhaus-muted: hsl(30 15% 94%);
  --blokhaus-muted-foreground: hsl(20 10% 50%);

  /* Interactive */
  --blokhaus-accent: hsl(25 70% 50%);
  --blokhaus-accent-foreground: hsl(0 0% 100%);

  /* Status */
  --blokhaus-destructive: hsl(0 65% 55%);
  --blokhaus-ai-stream: hsl(25 70% 50%);

  /* Radius */
  --blokhaus-radius: 0.375rem;

  /* Typography */
  --blokhaus-font-sans:
    "Merriweather Sans", ui-sans-serif, system-ui, sans-serif;
  --blokhaus-font-mono: "JetBrains Mono", ui-monospace, monospace;
}

.dark {
  --blokhaus-background: hsl(20 15% 10%);
  --blokhaus-foreground: hsl(30 20% 92%);
  --blokhaus-border: hsl(20 12% 20%);
  --blokhaus-ring: hsl(25 70% 55%);
  --blokhaus-muted: hsl(20 12% 16%);
  --blokhaus-muted-foreground: hsl(20 10% 60%);
  --blokhaus-accent: hsl(25 70% 55%);
  --blokhaus-accent-foreground: hsl(0 0% 100%);
  --blokhaus-destructive: hsl(0 50% 40%);
  --blokhaus-ai-stream: hsl(25 70% 55%);
}

Import this file instead of the default blokhaus-tokens.css and every Blokhaus component will pick up the new theme automatically. No prop changes or component modifications required.

Important rules

  • Never hardcode colors in components. Always reference a CSS variable. If a required token does not exist, add it to tokens.css first.
  • The --blokhaus- prefix is mandatory. It prevents collisions with the host app's CSS variables and other component libraries.
  • Dark mode uses the .dark class. Blokhaus does not use prefers-color-scheme by default. You control when dark mode activates by toggling the class.