Reef includes a comprehensive color generation system that transforms source color definitions into consistent, themeable color palettes. The system uses the OKLCH color space to generate tints and shades while maintaining perceptual uniformity.
The color system consists of three parts:
colors/ - Source JSON files defining color families and their base values
scripts/generate-colors.ts - Effect-based script that generates color palettes
reef/src/colors.gen/ - Auto-generated TypeScript and StyleX files (do not edit)
Run bun run generate-colors to regenerate color files after modifying the source JSON.
Colors are organized into families and groups. Each family represents a cohesive color collection, while groups contain individual named colors within that family.
| Family | Groups | Description |
|---|---|---|
Chinese Colors | Blue, Red, Green, Purple, Pink, Orange, Yellow, Cyan, Brown, Black, White | Traditional Chinese color palettes with poetic names like Moonlight, Jade City, and Dragon's Blood |
Misc | Hagoromo | Miscellaneous color palettes including Hagoromo |
Moonlight
(月白)
Sapphire
(宝石蓝)
Crane Crest
(鹤顶红)
Rouge
(胭脂)
Source color files are JSON with the following structure:
{
"family": "Chinese Colors",
"group": "Blue",
"colors": {
"Moonlight (月白)": "#D4E5EF",
"Sapphire (宝石蓝)": "#2486B9",
"Cloisonne (景泰蓝)": "#2775B6",
"Ocean Depths (海青)": "#080F40"
}
}Color names can include Chinese characters or other annotations in parentheses. The generator strips these for the exported variable names while preserving them in the source for documentation.
Each source color generates 13 depth levels using the OKLCH color space. Tints increase lightness toward white, while shades decrease lightness toward black. Chroma is automatically adjusted at extremes to maintain visual quality.
| Level | Description |
|---|---|
0 | Near-white with minimal chroma (l: 0.97, c: 15% of original) |
50 | Very light tint (95% tint) |
100 | Light tint (85% tint) |
200 | Medium-light tint (65% tint) |
300 | Subtle tint (45% tint) |
400 | Slight tint (25% tint) |
500 | Base color (original) |
600 | Slight shade (15% shade) |
700 | Medium shade (30% shade) |
800 | Dark shade (45% shade) |
900 | Very dark shade (60% shade) |
950 | Near-black shade (70% shade) |
1000 | Near-black with reduced chroma (l: 0.08, c: 40% of original) |
The generator uses OKLCH (Oklab Lightness Chroma Hue) for perceptually uniform color transformations:
// Tint: blend toward white
function tint(color: Oklch, intensity: number): Oklch {
const newL = color.l + (1 - color.l) * intensity;
return {
...color,
l: newL,
c: newL > 0.9 ? color.c * 0.5 : color.c, // Reduce chroma near white
};
}
// Shade: blend toward black
function shade(color: Oklch, intensity: number): Oklch {
const newL = color.l - color.l * intensity;
return {
...color,
l: newL,
c: newL < 0.3 ? color.c * 0.8 : color.c, // Reduce chroma near black
};
}The generator creates two types of files for each color group:
reef/src/colors.gen/
├── raw/
│ ├── chinese-colors/
│ │ ├── blue.ts
│ │ ├── red.ts
│ │ └── ...
│ └── misc/
│ └── hagoromo.ts
└── stylex/
├── chinese-colors/
│ ├── blue.stylex.ts
│ ├── red.stylex.ts
│ └── ...
└── misc/
└── hagoromo.stylex.tsRaw files export OKLCH color objects for programmatic use:
// reef/src/colors.gen/raw/chinese-colors/blue.ts
export const Moonlight = {
"0": { l: 0.97, c: 0.003, h: 220 },
"50": { l: 0.96, c: 0.02, h: 220 },
"100": { l: 0.92, c: 0.02, h: 220 },
// ... levels 200-900 ...
"950": { l: 0.28, c: 0.016, h: 220 },
"1000": { l: 0.08, c: 0.008, h: 220 },
};
export const Sapphire = {
"0": { l: 0.97, c: 0.008, h: 230 },
// ...
};StyleX files export CSS-ready color constants using stylex.defineConsts:
// reef/src/colors.gen/stylex/chinese-colors/blue.stylex.ts
import * as stylex from "@stylexjs/stylex";
export const Moonlight = stylex.defineConsts({
"0": "oklch(97% 0.003 220)",
"50": "oklch(96% 0.02 220)",
"100": "oklch(92% 0.02 220)",
// ... levels 200-900 ...
"950": "oklch(28% 0.016 220)",
"1000": "oklch(8% 0.008 220)",
});
export const Sapphire = stylex.defineConsts({
"0": "oklch(97% 0.008 230)",
// ...
});Import generated StyleX colors for use in component styles:
import * as stylex from "@stylexjs/stylex";
import { Moonlight, Sapphire } from "@228-co/reef/colors.gen/stylex/chinese-colors/blue.stylex";
const styles = stylex.create({
card: {
backgroundColor: Moonlight[100],
borderColor: Moonlight[300],
},
highlight: {
color: Sapphire[600],
backgroundColor: Sapphire[50],
},
});Import raw OKLCH values for programmatic color manipulation:
import { Moonlight } from "@228-co/reef/colors.gen/raw/chinese-colors/blue";
import { formatCss } from "culori";
// Access raw OKLCH values
const baseColor = Moonlight["500"];
console.log(baseColor); // { l: 0.85, c: 0.02, h: 220 }
// Convert to CSS string
const cssColor = formatCss(baseColor);
console.log(cssColor); // "oklch(85% 0.02 220)"Colors are used in the theme system to define semantic color tokens:
// reef/src/themes/theme.stylex.ts
import { Red, Blue, Green } from "../colors.gen/stylex/misc/hagoromo.stylex";
import { Lampblack, FishBelly } from "../colors.gen/stylex/chinese-colors/black.stylex";
export const themeColors = stylex.defineVars({
danger100: Red[100],
danger500: Red[500],
danger900: Red[900],
info100: Blue[100],
info500: Blue[500],
primary500: { default: Lampblack[500], [DARK]: White[500] },
background100: { default: FishBelly[100], [DARK]: CeremonialBlack[100] },
});Never edit colors.gen files - They are auto-generated and will be overwritten
Use StyleX exports for styling - They integrate seamlessly with the build system
Prefer theme tokens over direct colors - Use themeColors for consistent semantics
Match depth to visual hierarchy - Lower numbers (100-400) for backgrounds, higher (600-900) for text
Test colors in both light and dark modes - Ensure sufficient contrast in all contexts
Use meaningful color names - Source colors should have descriptive, memorable names
culori - Color conversion and OKLCH manipulation
effect - Functional programming patterns and error handling
@effect/platform - File system operations
OKLCH provides perceptually uniform color manipulation, meaning equal changes in lightness values produce visually equal changes in perceived brightness. This is superior to HSL for generating consistent tints and shades across different hues.