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:
@import "./blokhaus-tokens.css";Or import it directly in your layout:
import "./styles/blokhaus-tokens.css";Full token reference
Surface tokens
These control the primary background and foreground colors of the editor.
| Token | Default (Light) | Description |
|---|---|---|
--blokhaus-background | hsl(0 0% 100%) | Editor background |
--blokhaus-foreground | hsl(222.2 84% 4.9%) | Primary text color |
Editor chrome
These tokens style borders, focus rings, and muted/secondary elements.
| Token | Default (Light) | Description |
|---|---|---|
--blokhaus-border | hsl(214.3 31.8% 91.4%) | Border color for editor containers |
--blokhaus-ring | hsl(221.2 83.2% 53.3%) | Focus ring color |
--blokhaus-muted | hsl(210 40% 96.1%) | Muted background (e.g., code blocks) |
--blokhaus-muted-foreground | hsl(215.4 16.3% 46.9%) | Muted text color |
Interactive tokens
| Token | Default (Light) | Description |
|---|---|---|
--blokhaus-accent | hsl(221.2 83.2% 53.3%) | Accent color for interactive elements |
--blokhaus-accent-foreground | hsl(0 0% 100%) | Text on accent backgrounds |
Status tokens
| Token | Default (Light) | Description |
|---|---|---|
--blokhaus-destructive | hsl(0 84.2% 60.2%) | Destructive action color |
--blokhaus-ai-stream | hsl(220 60% 50%) | AI preview block accent |
Radius
| Token | Default | Description |
|---|---|---|
--blokhaus-radius | 0.5rem | Default border radius for all components |
Typography
| Token | Default | Description |
|---|---|---|
--blokhaus-font-sans | ui-sans-serif, system-ui, sans-serif | Sans-serif font stack |
--blokhaus-font-serif | Georgia, "Times New Roman", serif | Serif font stack |
--blokhaus-font-mono | ui-monospace, monospace | Monospace font stack |
--blokhaus-font-hand | "Caveat", cursive | Handwriting font stack |
Text colors
These tokens provide a Notion-style palette for text color formatting via the ColorPlugin.
| Token | Default (Light) | Description |
|---|---|---|
--blokhaus-text-gray | #9b9a97 | Gray text |
--blokhaus-text-brown | #64473a | Brown text |
--blokhaus-text-orange | #d9730d | Orange text |
--blokhaus-text-yellow | #dfab01 | Yellow text |
--blokhaus-text-green | #0f7b6c | Green text |
--blokhaus-text-blue | #0b6e99 | Blue text |
--blokhaus-text-purple | #6940a5 | Purple text |
--blokhaus-text-pink | #ad1a72 | Pink text |
--blokhaus-text-red | #e03e3e | Red text |
Highlight colors
Background highlight colors for text, used alongside the text color tokens.
| Token | Default (Light) | Description |
|---|---|---|
--blokhaus-highlight-gray | #ebeced | Gray highlight |
--blokhaus-highlight-brown | #e9e5e3 | Brown highlight |
--blokhaus-highlight-orange | #faebdd | Orange highlight |
--blokhaus-highlight-yellow | #fbf3db | Yellow highlight |
--blokhaus-highlight-green | #ddedea | Green highlight |
--blokhaus-highlight-blue | #ddebf1 | Blue highlight |
--blokhaus-highlight-purple | #eae4f2 | Purple highlight |
--blokhaus-highlight-pink | #f4dfeb | Pink highlight |
--blokhaus-highlight-red | #fbe4e4 | Red highlight |
Table tokens
| Token | Default (Light) | Description |
|---|---|---|
--blokhaus-table-border | hsl(214.3 31.8% 91.4%) | Table cell borders |
--blokhaus-table-header-bg | hsl(210 40% 96.1%) | Table header row background |
--blokhaus-table-selection | hsla(221.2 83.2% 53.3% / 0.1) | Table cell selection overlay |
--blokhaus-table-resize-handle | hsl(221.2 83.2% 53.3%) | Column resize handle color |
Popover / floating UI chrome
| Token | Default (Light) | Description |
|---|---|---|
--blokhaus-popover-bg | rgba(255, 255, 255, 0.82) | Popover background with blur |
--blokhaus-popover-border | rgba(0, 0, 0, 0.06) | Popover border |
--blokhaus-popover-shadow | (composite) | Popover box shadow |
--blokhaus-icon-secondary | rgba(0, 0, 0, 0.55) | Secondary icon color |
--blokhaus-separator | rgba(0, 0, 0, 0.1) | Separator line color |
--blokhaus-hover-bg | rgba(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:
@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:
.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:
"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:
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:
: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.cssfirst. - The
--blokhaus-prefix is mandatory. It prevents collisions with the host app's CSS variables and other component libraries. - Dark mode uses the
.darkclass. Blokhaus does not useprefers-color-schemeby default. You control when dark mode activates by toggling the class.