The Pindoba color system uses custom color ramps stored as W3C Design Tokens (DTCG format) with automatic light and dark mode adaptation. Five base palettes feed into semantic color groups.
---
import { css } from "@pindoba/styled-system/css";
const containerStyle = css({
display: "grid",
gridTemplateColumns: "1fr",
gap: "lg",
width: "100%",
});
const colorSectionStyle = css.raw({
display: "grid",
gridTemplateColumns: "auto repeat(11, 1fr)",
gap: "4xs",
alignItems: "center",
backgroundColor: "neutral.surface",
borderRadius: "lg",
padding: "lg",
border: "1px solid",
borderColor: "neutral.border.muted",
});
const sectionTitleStyle = css.raw({
fontSize: "md",
fontWeight: "bold",
marginBottom: "sm",
color: "neutral.text.bold",
gridColumn: "1 / -1",
});
const modeLabelStyle = css.raw({
fontSize: "2xs",
fontFamily: "mono",
color: "neutral.text",
textTransform: "uppercase",
letterSpacing: "wide",
paddingRight: "sm",
});
const swatchBoxStyle = css.raw({
width: "full",
aspectRatio: "1 / 1",
borderRadius: "md",
border: "1px solid",
borderColor: "neutral.border",
});
const shadeLabelStyle = css.raw({
fontSize: "2xs",
fontFamily: "mono",
color: "neutral.text",
textAlign: "center",
});
// Light mode color ramp styles
const lightBgStyles = {
"blue.50": css.raw({ backgroundColor: "blue.light.50" }),
"blue.100": css.raw({ backgroundColor: "blue.light.100" }),
"blue.200": css.raw({ backgroundColor: "blue.light.200" }),
"blue.300": css.raw({ backgroundColor: "blue.light.300" }),
"blue.400": css.raw({ backgroundColor: "blue.light.400" }),
"blue.500": css.raw({ backgroundColor: "blue.light.500" }),
"blue.600": css.raw({ backgroundColor: "blue.light.600" }),
"blue.700": css.raw({ backgroundColor: "blue.light.700" }),
"blue.800": css.raw({ backgroundColor: "blue.light.800" }),
"blue.900": css.raw({ backgroundColor: "blue.light.900" }),
"blue.950": css.raw({ backgroundColor: "blue.light.950" }),
"gray.50": css.raw({ backgroundColor: "gray.light.50" }),
"gray.100": css.raw({ backgroundColor: "gray.light.100" }),
"gray.200": css.raw({ backgroundColor: "gray.light.200" }),
"gray.300": css.raw({ backgroundColor: "gray.light.300" }),
"gray.400": css.raw({ backgroundColor: "gray.light.400" }),
"gray.500": css.raw({ backgroundColor: "gray.light.500" }),
"gray.600": css.raw({ backgroundColor: "gray.light.600" }),
"gray.700": css.raw({ backgroundColor: "gray.light.700" }),
"gray.800": css.raw({ backgroundColor: "gray.light.800" }),
"gray.900": css.raw({ backgroundColor: "gray.light.900" }),
"gray.950": css.raw({ backgroundColor: "gray.light.950" }),
"green.50": css.raw({ backgroundColor: "green.light.50" }),
"green.100": css.raw({ backgroundColor: "green.light.100" }),
"green.200": css.raw({ backgroundColor: "green.light.200" }),
"green.300": css.raw({ backgroundColor: "green.light.300" }),
"green.400": css.raw({ backgroundColor: "green.light.400" }),
"green.500": css.raw({ backgroundColor: "green.light.500" }),
"green.600": css.raw({ backgroundColor: "green.light.600" }),
"green.700": css.raw({ backgroundColor: "green.light.700" }),
"green.800": css.raw({ backgroundColor: "green.light.800" }),
"green.900": css.raw({ backgroundColor: "green.light.900" }),
"green.950": css.raw({ backgroundColor: "green.light.950" }),
"orange.50": css.raw({ backgroundColor: "orange.light.50" }),
"orange.100": css.raw({ backgroundColor: "orange.light.100" }),
"orange.200": css.raw({ backgroundColor: "orange.light.200" }),
"orange.300": css.raw({ backgroundColor: "orange.light.300" }),
"orange.400": css.raw({ backgroundColor: "orange.light.400" }),
"orange.500": css.raw({ backgroundColor: "orange.light.500" }),
"orange.600": css.raw({ backgroundColor: "orange.light.600" }),
"orange.700": css.raw({ backgroundColor: "orange.light.700" }),
"orange.800": css.raw({ backgroundColor: "orange.light.800" }),
"orange.900": css.raw({ backgroundColor: "orange.light.900" }),
"orange.950": css.raw({ backgroundColor: "orange.light.950" }),
"red.50": css.raw({ backgroundColor: "red.light.50" }),
"red.100": css.raw({ backgroundColor: "red.light.100" }),
"red.200": css.raw({ backgroundColor: "red.light.200" }),
"red.300": css.raw({ backgroundColor: "red.light.300" }),
"red.400": css.raw({ backgroundColor: "red.light.400" }),
"red.500": css.raw({ backgroundColor: "red.light.500" }),
"red.600": css.raw({ backgroundColor: "red.light.600" }),
"red.700": css.raw({ backgroundColor: "red.light.700" }),
"red.800": css.raw({ backgroundColor: "red.light.800" }),
"red.900": css.raw({ backgroundColor: "red.light.900" }),
"red.950": css.raw({ backgroundColor: "red.light.950" }),
} as const;
// Dark mode color ramp styles
const darkBgStyles = {
"blue.50": css.raw({ backgroundColor: "blue.dark.50" }),
"blue.100": css.raw({ backgroundColor: "blue.dark.100" }),
"blue.200": css.raw({ backgroundColor: "blue.dark.200" }),
"blue.300": css.raw({ backgroundColor: "blue.dark.300" }),
"blue.400": css.raw({ backgroundColor: "blue.dark.400" }),
"blue.500": css.raw({ backgroundColor: "blue.dark.500" }),
"blue.600": css.raw({ backgroundColor: "blue.dark.600" }),
"blue.700": css.raw({ backgroundColor: "blue.dark.700" }),
"blue.800": css.raw({ backgroundColor: "blue.dark.800" }),
"blue.900": css.raw({ backgroundColor: "blue.dark.900" }),
"blue.950": css.raw({ backgroundColor: "blue.dark.950" }),
"gray.50": css.raw({ backgroundColor: "gray.dark.50" }),
"gray.100": css.raw({ backgroundColor: "gray.dark.100" }),
"gray.200": css.raw({ backgroundColor: "gray.dark.200" }),
"gray.300": css.raw({ backgroundColor: "gray.dark.300" }),
"gray.400": css.raw({ backgroundColor: "gray.dark.400" }),
"gray.500": css.raw({ backgroundColor: "gray.dark.500" }),
"gray.600": css.raw({ backgroundColor: "gray.dark.600" }),
"gray.700": css.raw({ backgroundColor: "gray.dark.700" }),
"gray.800": css.raw({ backgroundColor: "gray.dark.800" }),
"gray.900": css.raw({ backgroundColor: "gray.dark.900" }),
"gray.950": css.raw({ backgroundColor: "gray.dark.950" }),
"green.50": css.raw({ backgroundColor: "green.dark.50" }),
"green.100": css.raw({ backgroundColor: "green.dark.100" }),
"green.200": css.raw({ backgroundColor: "green.dark.200" }),
"green.300": css.raw({ backgroundColor: "green.dark.300" }),
"green.400": css.raw({ backgroundColor: "green.dark.400" }),
"green.500": css.raw({ backgroundColor: "green.dark.500" }),
"green.600": css.raw({ backgroundColor: "green.dark.600" }),
"green.700": css.raw({ backgroundColor: "green.dark.700" }),
"green.800": css.raw({ backgroundColor: "green.dark.800" }),
"green.900": css.raw({ backgroundColor: "green.dark.900" }),
"green.950": css.raw({ backgroundColor: "green.dark.950" }),
"orange.50": css.raw({ backgroundColor: "orange.dark.50" }),
"orange.100": css.raw({ backgroundColor: "orange.dark.100" }),
"orange.200": css.raw({ backgroundColor: "orange.dark.200" }),
"orange.300": css.raw({ backgroundColor: "orange.dark.300" }),
"orange.400": css.raw({ backgroundColor: "orange.dark.400" }),
"orange.500": css.raw({ backgroundColor: "orange.dark.500" }),
"orange.600": css.raw({ backgroundColor: "orange.dark.600" }),
"orange.700": css.raw({ backgroundColor: "orange.dark.700" }),
"orange.800": css.raw({ backgroundColor: "orange.dark.800" }),
"orange.900": css.raw({ backgroundColor: "orange.dark.900" }),
"orange.950": css.raw({ backgroundColor: "orange.dark.950" }),
"red.50": css.raw({ backgroundColor: "red.dark.50" }),
"red.100": css.raw({ backgroundColor: "red.dark.100" }),
"red.200": css.raw({ backgroundColor: "red.dark.200" }),
"red.300": css.raw({ backgroundColor: "red.dark.300" }),
"red.400": css.raw({ backgroundColor: "red.dark.400" }),
"red.500": css.raw({ backgroundColor: "red.dark.500" }),
"red.600": css.raw({ backgroundColor: "red.dark.600" }),
"red.700": css.raw({ backgroundColor: "red.dark.700" }),
"red.800": css.raw({ backgroundColor: "red.dark.800" }),
"red.900": css.raw({ backgroundColor: "red.dark.900" }),
"red.950": css.raw({ backgroundColor: "red.dark.950" }),
} as const;
type BgKey = keyof typeof lightBgStyles;
const colorPalettes = [
{ name: "Blue (Primary)", colorKey: "blue" as const },
{ name: "Gray (Neutral)", colorKey: "gray" as const },
{ name: "Green (Success)", colorKey: "green" as const },
{ name: "Orange (Warning)", colorKey: "orange" as const },
{ name: "Red (Danger)", colorKey: "red" as const },
];
const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950] as const;
---
<div class={containerStyle}>
{
colorPalettes.map(({ name, colorKey }) => (
<div class={css(colorSectionStyle)}>
<h3 class={css(sectionTitleStyle)}>{name}</h3>
{/* Light row: label + 11 swatches */}
<span class={css(modeLabelStyle)}>Light</span>
{shades.map((shade) => {
const bgKey = `${colorKey}.${shade}` as BgKey;
return <div class={css(swatchBoxStyle, lightBgStyles[bgKey])} />;
})}
{/* Labels row: empty cell + 11 shade labels */}
<span />
{shades.map((shade) => (
<span class={css(shadeLabelStyle)}>{shade}</span>
))}
{/* Dark row: label + 11 swatches */}
<span class={css(modeLabelStyle)}>Dark</span>
{shades.map((shade) => {
const bgKey = `${colorKey}.${shade}` as BgKey;
return <div class={css(swatchBoxStyle, darkBgStyles[bgKey])} />;
})}
</div>
))
}
</div>Five base color families, each with 11 shades (50–950):
primary semantic groupneutral semantic groupsuccess semantic groupwarning semantic groupdanger semantic groupEach color has separate light and dark ramps. Tokens reference these ramps through semantic tokens that resolve to the correct mode automatically.
Semantic tokens provide structured access to colors by intent rather than raw shade. Each semantic group exposes the same set of sub-tokens:
{
// Text colors
primary.text // Default text
primary.text.bold // High-emphasis text
primary.text.contrast // Text on solid backgrounds
primary.text.contrast.bold
// Borders (rendered at 65% opacity)
primary.border // Default border
primary.border.muted // Subtle separation
primary.border.bold // Strong emphasis
// Surfaces
primary.surface // Default surface fill
primary.surface.hover // Hover state
primary.surface.active // Active/pressed state
// Sunken (recessed backgrounds)
primary.sunken
primary.sunken.hover
primary.sunken.active
// Interactive states
primary.hover
primary.active
}
The same structure applies to neutral, success, warning, and danger.
Two fixed contrast values are available for cases where you need guaranteed light or dark:
contrast.darkest // #181818
contrast.lightest // #f9fbff
import { css } from "@pindoba/styled-system/css";
// Semantic surface and text
<div className={css({
backgroundColor: "neutral.surface",
color: "neutral.text.bold",
})}>
Card content
</div>
// Interactive element
<button className={css({
backgroundColor: "primary.sunken",
color: "primary.text.contrast",
_hover: { backgroundColor: "primary.sunken.hover" },
_active: { backgroundColor: "primary.sunken.active" },
})}>
Submit
</button>
// Status feedback
<div className={css({
backgroundColor: "danger.surface",
color: "danger.text.bold",
borderWidth: "1px",
borderColor: "danger.border.muted",
})}>
Error message
</div>
The colorPalette utility lets components switch between semantic groups without duplicating styles:
<div className={css({ colorPalette: "success" })}>
<span className={css({ color: "colorPalette.text.bold" })}>
Status text
</span>
</div>
<div className={css({ colorPalette: "danger" })}>
<span className={css({ color: "colorPalette.text.bold" })}>
Error text
</span>
</div>
primary.surface, neutral.text.bold) rather than raw base colors (blue.light.500).text.contrast for text on solid-colored backgrounds.border.muted for subtle separators and .border.bold for emphasis.surface / .sunken for background fills — they automatically adapt to the active theme mode