Theming
Clawscale's look comes from design tokens. Change a token and every component follows. To switch the whole look at once, pick a theme.
How it works#
The stylesheets use cascade layers. Rules in a later layer win, whatever their specificity.
@layer blueprint, clawscale.base, clawscale.themes;
@layer blueprint {
/* normalize.css and Blueprint's CSS, unchanged */
}
@layer clawscale.base {
/* 1. tokens: --cs-* variables for the default theme, light and dark */
/* 2. bridge: Blueprint's --bp-* tokens point at --cs-* tokens */
/* 3. overrides for what Blueprint hardcodes */
}
@layer clawscale.themes {
/* each theme stylesheet: its tokens, then its own rules */
}Your own CSS is not in a layer, so it beats all of them. No !important needed.
Color schemes#
Every theme has a light and a dark color scheme. ClawscaleProvider puts the bp6-dark class and data-cs-color-scheme on <html>. It supports light, dark and system, and saves the choice. Read or change it with useTheme.
const { colorScheme, resolvedColorScheme, setColorScheme } = useTheme();Override tokens#
Each color, shadow and chart token has a light and a dark value side by side, such as --cs-color-primary-light and --cs-color-primary-dark. Set both, and every color scheme picks its value.
:root {
--cs-color-primary-light: #0e7c6b;
--cs-color-primary-dark: #0e7c6b;
--cs-color-primary-text-light: #0b6b5c;
--cs-color-primary-text-dark: #4fd1b8;
--cs-radius-md: 4px;
}You can also set the final token for the whole page, with its dark value under the dark attribute.
:root {
--cs-color-primary-text: #0b6b5c;
}
[data-cs-color-scheme="dark"] {
--cs-color-primary-text: #4fd1b8;
}See Tokens for every variable.
Scope tokens#
data-cs-theme and data-cs-color-scheme work on any element. Each re-applies the tokens for its subtree, so token values set on the same element apply there. This card restates the current theme and sets a teal brand.
import { Button, ButtonGroup, Card, Switch, Tag, useTheme } from "@clawscale/react";
import type { CSSProperties } from "react";
// Light and dark values side by side. The card picks the pair for the color scheme around it.
const brand = {
"--cs-color-primary-light": "#0E7C6B",
"--cs-color-primary-dark": "#0E7C6B",
"--cs-color-primary-hover-light": "#0B6B5C",
"--cs-color-primary-hover-dark": "#0B6B5C",
"--cs-color-primary-active-light": "#095A4D",
"--cs-color-primary-active-dark": "#095A4D",
"--cs-color-primary-on-light": "#FFFFFF",
"--cs-color-primary-on-dark": "#FFFFFF",
"--cs-color-primary-text-light": "#0B6B5C",
"--cs-color-primary-text-dark": "#4FD1B8",
"--cs-color-primary-subtle-light": "rgba(14, 124, 107, 0.12)",
"--cs-color-primary-subtle-dark": "rgba(79, 209, 184, 0.16)",
"--cs-color-focus-light": "#0E7C6B",
"--cs-color-focus-dark": "#4FD1B8",
} as CSSProperties;
export default function BrandColor() {
// Restating the current theme makes the card pick its tokens again, from the values above.
const { theme } = useTheme();
return (
<Card data-cs-theme={theme} style={{ ...brand, display: "grid", gap: 12, width: 340 }}>
<ButtonGroup>
<Button intent="primary" text="Deploy" />
<Button intent="primary" variant="outlined" text="Preview" />
</ButtonGroup>
<Switch defaultChecked label="Auto-scale workers" />
<Tag minimal intent="primary">
us-east-1
</Tag>
</Card>
);
}Fonts#
@clawscale/react/fonts.css loads Inter and JetBrains Mono, and IBM Plex for the Ledger theme. Browsers download only the fonts a page uses. To use your own, set --cs-font-sans and --cs-font-mono.
Labels and corners#
Two token groups describe a theme's voice and shape, so your own components can match it.
--cs-label-transformand--cs-label-trackingset short labels, such as card titles. A theme can set them in capitals.--cs-corner-shapeisroundorbevel. Pair it with a radius token to cut corners where the browser supports it.
.queue-title {
letter-spacing: var(--cs-label-tracking);
text-transform: var(--cs-label-transform);
}
.queue-panel {
border-radius: var(--cs-radius-lg);
corner-shape: var(--cs-corner-shape);
}ClawscaleClasses.LABEL applies the label tokens as a class.
Density#
Clawscale sets a 13px base size and tabular numbers in tables. Use size="small" on buttons and inputs, compact on HTMLTable, CardList and Callout for denser screens.
Your own cascade layers#
If your app declares cascade layers, list Clawscale's first so yours win:
@layer blueprint, clawscale, app;