API Reference
Programmatic API for using Nightfall in your own tools, scripts, and build pipelines.
Installation
npm install nightfall-cssimport {
transformTheme,
detectThemeDirection,
classifyColors,
buildColorGraph,
contrastRatio,
autoFixContrast,
hexToOklch,
oklchToHex,
deltaE,
gamutMap,
} from 'nightfall-css'transformTheme()
The main transformation function. Takes classified colors and a configuration object, returns the complete transformed theme:
const result = transformTheme(classifiedColors, {
direction: 'light-to-dark',
preset: 'neutral',
contrast: { target: 'aa', autoFix: true },
brand: {
preserve: ['#2563eb', '#7c3aed'],
maxChromaShift: 0.15,
maxLightnessShift: 0.20,
maxDeltaE: 15,
},
})
// result.tokens — Record<string, TransformedToken>
// result.shadows — ShadowScale (generated for dark→light)
// result.warnings — string[] (auto-fix warnings)
// result.metadata — { direction, preset, generatedAt }Type signature:
function transformTheme(
colors: ClassifiedColor[],
config: TransformConfig
): TransformResult
interface TransformConfig {
direction: 'light-to-dark' | 'dark-to-light' | 'both'
preset?: 'neutral' | 'warm' | 'midnight' | 'oled' | 'dimmed' | string
contrast?: { target: 'aa' | 'aaa'; autoFix: boolean }
brand?: {
preserve: string[]
maxChromaShift?: number
maxLightnessShift?: number
maxDeltaE?: number
}
}
interface TransformResult {
tokens: Record<string, TransformedToken>
shadows: ShadowScale
warnings: string[]
metadata: TransformMetadata
}detectThemeDirection()
Analyzes a set of background colors and returns the detected theme direction:
const direction = detectThemeDirection(backgrounds)
// backgrounds: Array<{ color: string; area: number }>
// Returns: 'light' | 'dark' | 'ambiguous'
// Example:
const direction = detectThemeDirection([
{ color: '#ffffff', area: 921600 },
{ color: '#f8f9fa', area: 345600 },
])
// → 'light' (weighted avg L > 0.6)classifyColors()
Takes raw scanned colors and assigns semantic roles (background, text, border, brand, etc.):
const classified = classifyColors(rawColors)
// rawColors: Array<{ value: string; property: string; parentBg?: string }>
// Returns: ClassifiedColor[]
interface ClassifiedColor {
value: string // oklch(...) or hex
role: string // 'background.page' | 'text.heading' | 'brand.primary' | ...
property: string // CSS property it came from
parentBackground: string // What surface it sits on
contrastRatio: number // Against its parent
}
// Example:
const classified = classifyColors([
{ value: '#ffffff', property: 'background-color', parentBg: null },
{ value: '#111827', property: 'color', parentBg: '#ffffff' },
{ value: '#2563eb', property: 'background-color', parentBg: '#ffffff' },
])
// → [
// { value: '#ffffff', role: 'background.page', ... },
// { value: '#111827', role: 'text.heading', contrastRatio: 18.1, ... },
// { value: '#2563eb', role: 'brand.primary', contrastRatio: 4.8, ... },
// ]buildColorGraph()
Builds the color relationship graph from classified colors:
const graph = buildColorGraph(classifiedColors)
// Returns a tree structure:
interface ColorNode {
token: string // Variable name
value: string // Color value
role: string // Semantic role
children: ColorNode[] // Colors that sit on this one
contrastRatio?: number // Contrast against parent
}
// Traverse the graph:
function walk(node: ColorNode, depth = 0) {
console.log(' '.repeat(depth) + node.token + ' ' + node.value)
for (const child of node.children) {
walk(child, depth + 1)
}
}
walk(graph.root)Color Utilities
import {
hexToOklch,
oklchToHex,
contrastRatio,
deltaE,
gamutMap,
} from 'nightfall-css'
// Convert hex to OKLCH
const oklch = hexToOklch('#2563eb')
// { l: 0.55, c: 0.22, h: 260 }
// Convert OKLCH back to hex
const hex = oklchToHex({ l: 0.55, c: 0.22, h: 260 })
// '#2563eb'
// Calculate WCAG contrast ratio between two colors
const ratio = contrastRatio('#ffffff', '#2563eb')
// 4.87
// Measure perceptual distance between two OKLCH colors
const distance = deltaE(
{ l: 0.55, c: 0.22, h: 260 },
{ l: 0.62, c: 0.20, h: 260 }
)
// 4.2
// Map an out-of-gamut OKLCH color to the nearest in-gamut sRGB color
const inGamut = gamutMap({ l: 0.8, c: 0.35, h: 150 })
// { l: 0.8, c: 0.22, h: 150 } — chroma reduced to fit sRGBautoFixContrast()
Adjusts a foreground color to meet a target contrast ratio against a background:
const fixed = autoFixContrast({
foreground: '#9ca3af',
background: '#1e1e22',
targetRatio: 4.5, // WCAG AA
})
// fixed.value — the adjusted foreground color
// fixed.ratio — the new contrast ratio
// fixed.deltaE — perceptual distance from original
// fixed.adjustment — description of what changed
// Example result:
// {
// value: '#b0b5bd',
// ratio: 4.6,
// deltaE: 3.2,
// adjustment: 'lightness +0.06'
// }Presets
import { getPreset, listPresets } from 'nightfall-css'
// Get a preset configuration
const midnight = getPreset('midnight')
// {
// baseLightness: 0.10,
// hueUndertone: 250,
// chromaAmount: 0.015,
// elevationStep: 0.04,
// textContrast: 'normal',
// }
// List all available presets
const presets = listPresets()
// ['neutral', 'warm', 'midnight', 'oled', 'dimmed']Export Functions
import {
exportCssVariables,
exportTailwind,
exportScss,
exportJsonTokens,
exportFigmaTokens,
exportStyleDictionary,
} from 'nightfall-css'
// Each takes a TransformResult and returns a string
const css = exportCssVariables(result, {
selector: '[data-theme="dark"]',
prefix: 'nf',
fallback: 'hex',
})
const tailwind = exportTailwind(result)
const scss = exportScss(result)
const json = exportJsonTokens(result)
const figma = exportFigmaTokens(result)
const sd = exportStyleDictionary(result)