Skip to main content
ThemingThe theme contains design tokens like colors, fonts, spacing, and more. The ThemeProvider provides access to these values via CSS Variables for web, and React Context for both web and React Native.

ThemeProvider component

The ThemeProvider provides the theme context to all child components, and automatically generates CSS Variables for dynamic theming.

You must pass the theme prop to configure the theme, and the activeColorScheme prop to set light or dark mode.

See the ThemeProvider docs here →

import { ThemeProvider } from '@coinbase/cds-web/system/ThemeProvider';
import { defaultTheme } from '@coinbase/cds-web/themes/defaultTheme';

const App = () => (
<ThemeProvider theme={defaultTheme} activeColorScheme="light">
{/* Your app components */}
</ThemeProvider>
);
Tip

Changing the activeColorScheme automatically updates the values returned from the useTheme hook and from CSS Variables.

useTheme hook

The useTheme hook provides access to the current theme and activeColorScheme.

The color and spectrum objects automatically change based on the activeColorScheme.

See the useTheme docs here →

const theme = useTheme();
theme.activeColorScheme; // "light" or "dark"
theme.spectrum; // Resolves to lightSpectrum or darkSpectrum, depends on activeColorScheme
theme.color; // Resolves to lightColor or darkColor, depends on activeColorScheme
theme.color.bgPrimary; // "rgb(0,82,255)" or "rgb(87,139,250)", depends on activeColorScheme
theme.space[2]; // 16
theme.borderRadius[200]; // 8
theme.fontSize.display3; // "2.5rem"
Tip

For best performance, prefer to use CSS Variables instead of the useTheme hook whenever possible.

ThemeProvider CSS Variables

CSS Variables are created for every value in the theme.

For best performance, prefer to use CSS Variables instead of the useTheme hook whenever possible.

const theme = useTheme();
theme.color.bgPrimary; // --color-bgPrimary
theme.lightColor.bgPrimary; // --lightColor-bgPrimary
theme.darkColor.bgPrimary; // --darkColor-bgPrimary
theme.spectrum.blue10; // --blue10
theme.lightSpectrum.blue10; // --light-blue10
theme.darkSpectrum.blue10; // --dark-blue10
theme.space[2]; // --space-2
theme.space[0.25]; // --space-0_25
theme.borderRadius[400]; // --borderRadius-400
theme.fontSize.body; // --fontSize-body

You can see all the CSS Variables for the defaultTheme below.

{
"--light-blue0": "245,248,255",
"--light-blue5": "211,225,255",
"--light-blue10": "176,202,255",
"--light-blue15": "146,182,255",
"--light-blue20": "115,162,255",
"--light-blue30": "70,132,255",
"--light-blue40": "38,110,255",
"--light-blue50": "16,94,255",
"--light-blue60": "0,82,255",
"--light-blue70": "0,75,235",
"--light-blue80": "0,62,193",
"--light-blue90": "0,41,130",
"--light-blue100": "0,24,77",
"--light-green0": "245,255,251",
"--light-green5": "203,245,227",
"--light-green10": "163,235,205",
"--light-green15": "131,224,186",
"--light-green20": "101,214,167",
"--light-green30": "60,194,138",
"--light-green40": "34,173,115",
"--light-green50": "18,153,97",
"--light-green60": "9,133,81",
"--light-green70": "4,112,67",
"--light-green80": "2,83,50",
"--light-green90": "0,57,35",
"--light-green100": "0,31,18",
"--light-orange0": "255,250,245",
"--light-orange5": "254,232,210",
"--light-orange10": "253,213,176",
"--light-orange15": "251,194,147",
"--light-orange20": "249,174,118",
"--light-orange30": "244,140,76",
"--light-orange40": "237,112,47",
"--light-orange50": "225,89,27",
"--light-orange60": "207,71,14",
"--light-orange70": "181,54,6",
"--light-orange80": "145,39,2",
"--light-orange90": "100,26,0",
"--light-orange100": "51,13,0",
"--light-gray0": "255,255,255",
"--light-gray5": "247,248,249",
"--light-gray10": "238,240,243",
"--light-gray15": "222,225,231",
"--light-gray20": "206,210,219",
"--light-gray30": "177,183,195",
"--light-gray40": "137,144,158",
"--light-gray50": "113,120,134",
"--light-gray60": "91,97,110",
"--light-gray70": "70,75,85",
"--light-gray80": "50,53,61",
"--light-gray90": "30,32,37",
"--light-gray100": "10,11,13",
"--light-indigo0": "246,247,255",
"--light-indigo5": "230,232,255",
"--light-indigo10": "214,218,254",
"--light-indigo15": "198,204,253",
"--light-indigo20": "181,189,253",
"--light-indigo30": "148,161,251",
"--light-indigo40": "116,135,247",
"--light-indigo50": "89,111,242",
"--light-indigo60": "66,91,233",
"--light-indigo70": "47,74,215",
"--light-indigo80": "31,54,173",
"--light-indigo90": "17,32,107",
"--light-indigo100": "8,15,51",
"--light-pink0": "255,245,255",
"--light-pink5": "253,228,253",
"--light-pink10": "251,212,250",
"--light-pink15": "248,195,245",
"--light-pink20": "244,178,240",
"--light-pink30": "235,143,227",
"--light-pink40": "221,110,209",
"--light-pink50": "203,81,187",
"--light-pink60": "179,58,162",
"--light-pink70": "149,39,133",
"--light-pink80": "116,26,102",
"--light-pink90": "83,17,72",
"--light-pink100": "51,10,44",
"--light-purple0": "251,247,255",
"--light-purple5": "244,232,255",
"--light-purple10": "237,217,255",
"--light-purple15": "230,201,255",
"--light-purple20": "222,184,255",
"--light-purple30": "205,153,253",
"--light-purple40": "188,123,251",
"--light-purple50": "157,107,242",
"--light-purple60": "138,85,233",
"--light-purple70": "119,67,215",
"--light-purple80": "90,48,173",
"--light-purple90": "54,27,107",
"--light-purple100": "25,13,51",
"--light-red0": "255,245,246",
"--light-red5": "254,225,228",
"--light-red10": "253,206,210",
"--light-red15": "251,186,191",
"--light-red20": "249,166,173",
"--light-red30": "244,127,136",
"--light-red40": "237,89,102",
"--light-red50": "225,57,71",
"--light-red60": "207,32,47",
"--light-red70": "181,15,29",
"--light-red80": "145,5,16",
"--light-red90": "100,1,9",
"--light-red100": "51,0,4",
"--light-teal0": "240,254,255",
"--light-teal5": "188,246,253",
"--light-teal10": "136,237,251",
"--light-teal15": "93,226,248",
"--light-teal20": "51,213,244",
"--light-teal30": "0,188,235",
"--light-teal40": "0,169,221",
"--light-teal50": "0,147,203",
"--light-teal60": "0,123,179",
"--light-teal70": "0,97,149",
"--light-teal80": "0,71,116",
"--light-teal90": "0,47,83",
"--light-teal100": "0,27,51",
"--light-yellow0": "255,252,241",
"--light-yellow5": "255,244,192",
"--light-yellow10": "255,240,145",
"--light-yellow15": "255,234,100",
"--light-yellow20": "255,228,54",
"--light-yellow30": "247,210,26",
"--light-yellow40": "235,186,0",
"--light-yellow50": "207,151,0",
"--light-yellow60": "174,113,0",
"--light-yellow70": "136,76,0",
"--light-yellow80": "96,48,0",
"--light-yellow90": "58,20,0",
"--light-yellow100": "27,6,0",
"--light-chartreuse0": "245,255,250",
"--light-chartreuse5": "221,251,232",
"--light-chartreuse10": "198,247,209",
"--light-chartreuse15": "176,242,182",
"--light-chartreuse20": "159,238,155",
"--light-chartreuse30": "137,223,117",
"--light-chartreuse40": "127,208,87",
"--light-chartreuse50": "86,179,64",
"--light-chartreuse60": "53,151,48",
"--light-chartreuse70": "35,122,43",
"--light-chartreuse80": "25,93,41",
"--light-chartreuse90": "17,64,35",
"--light-chartreuse100": "7,26,17",
"--dark-blue0": "0,16,51",
"--dark-blue5": "1,29,91",
"--dark-blue10": "1,42,130",
"--dark-blue15": "3,51,154",
"--dark-blue20": "5,59,177",
"--dark-blue30": "10,72,206",
"--dark-blue40": "19,84,225",
"--dark-blue50": "33,98,238",
"--dark-blue60": "55,115,245",
"--dark-blue70": "87,139,250",
"--dark-blue80": "132,170,253",
"--dark-blue90": "185,207,255",
"--dark-blue100": "245,248,255",
"--dark-green0": "0,31,18",
"--dark-green5": "0,48,29",
"--dark-green10": "1,70,42",
"--dark-green15": "2,82,48",
"--dark-green20": "2,92,55",
"--dark-green30": "6,112,68",
"--dark-green40": "11,133,82",
"--dark-green50": "21,153,98",
"--dark-green60": "39,173,117",
"--dark-green70": "68,194,141",
"--dark-green80": "111,214,171",
"--dark-green90": "171,235,208",
"--dark-green100": "245,255,251",
"--dark-orange0": "51,13,0",
"--dark-orange5": "79,20,0",
"--dark-orange10": "107,28,1",
"--dark-orange15": "131,36,2",
"--dark-orange20": "155,44,4",
"--dark-orange30": "189,59,9",
"--dark-orange40": "213,76,18",
"--dark-orange50": "230,96,32",
"--dark-orange60": "240,120,54",
"--dark-orange70": "248,150,86",
"--dark-orange80": "252,185,131",
"--dark-orange90": "254,219,185",
"--dark-orange100": "255,250,245",
"--dark-gray0": "10,11,13",
"--dark-gray5": "20,21,25",
"--dark-gray10": "30,32,37",
"--dark-gray15": "40,43,49",
"--dark-gray20": "50,53,61",
"--dark-gray30": "70,75,85",
"--dark-gray40": "91,97,110",
"--dark-gray50": "114,120,134",
"--dark-gray60": "138,145,158",
"--dark-gray70": "165,170,182",
"--dark-gray80": "193,198,207",
"--dark-gray90": "224,226,231",
"--dark-gray100": "255,255,255",
"--dark-indigo0": "8,15,51",
"--dark-indigo5": "14,27,91",
"--dark-indigo10": "21,39,130",
"--dark-indigo15": "27,47,154",
"--dark-indigo20": "33,56,177",
"--dark-indigo30": "48,73,206",
"--dark-indigo40": "68,92,225",
"--dark-indigo50": "92,113,238",
"--dark-indigo60": "121,138,245",
"--dark-indigo70": "153,165,250",
"--dark-indigo80": "187,194,253",
"--dark-indigo90": "219,223,255",
"--dark-indigo100": "246,247,255",
"--dark-pink0": "51,10,44",
"--dark-pink5": "70,14,61",
"--dark-pink10": "89,19,78",
"--dark-pink15": "108,24,94",
"--dark-pink20": "126,30,111",
"--dark-pink30": "159,44,142",
"--dark-pink40": "187,64,170",
"--dark-pink50": "208,88,193",
"--dark-pink60": "225,117,214",
"--dark-pink70": "237,149,230",
"--dark-pink80": "246,184,243",
"--dark-pink90": "252,217,251",
"--dark-pink100": "255,245,255",
"--dark-purple0": "25,13,51",
"--dark-purple5": "43,22,89",
"--dark-purple10": "73,30,137",
"--dark-purple15": "97,37,175",
"--dark-purple20": "123,45,211",
"--dark-purple30": "142,51,234",
"--dark-purple40": "164,84,244",
"--dark-purple50": "188,123,251",
"--dark-purple60": "205,153,253",
"--dark-purple70": "217,176,254",
"--dark-purple80": "230,201,255",
"--dark-purple90": "237,217,255",
"--dark-purple100": "251,247,255",
"--dark-red0": "51,0,4",
"--dark-red5": "79,0,7",
"--dark-red10": "107,1,10",
"--dark-red15": "131,4,14",
"--dark-red20": "155,7,19",
"--dark-red30": "189,19,33",
"--dark-red40": "213,38,52",
"--dark-red50": "230,64,78",
"--dark-red60": "240,97,109",
"--dark-red70": "248,134,144",
"--dark-red80": "252,174,181",
"--dark-red90": "254,213,216",
"--dark-red100": "255,245,246",
"--dark-teal0": "0,20,38",
"--dark-teal5": "0,32,59",
"--dark-teal10": "0,45,79",
"--dark-teal15": "0,58,99",
"--dark-teal20": "0,72,118",
"--dark-teal30": "0,99,153",
"--dark-teal40": "0,125,182",
"--dark-teal50": "0,149,205",
"--dark-teal60": "0,170,223",
"--dark-teal70": "6,190,236",
"--dark-teal80": "69,217,245",
"--dark-teal90": "149,239,251",
"--dark-teal100": "240,254,255",
"--dark-yellow0": "27,6,0",
"--dark-yellow5": "49,17,0",
"--dark-yellow10": "81,40,0",
"--dark-yellow15": "96,48,0",
"--dark-yellow20": "115,64,0",
"--dark-yellow30": "147,96,0",
"--dark-yellow40": "175,128,0",
"--dark-yellow50": "199,158,0",
"--dark-yellow60": "222,189,23",
"--dark-yellow70": "229,205,48",
"--dark-yellow80": "242,222,94",
"--dark-yellow90": "255,240,145",
"--dark-yellow100": "255,252,241",
"--dark-chartreuse0": "5,22,14",
"--dark-chartreuse5": "14,54,29",
"--dark-chartreuse10": "21,79,34",
"--dark-chartreuse15": "29,103,36",
"--dark-chartreuse20": "45,128,40",
"--dark-chartreuse30": "73,152,54",
"--dark-chartreuse40": "107,176,73",
"--dark-chartreuse50": "123,200,105",
"--dark-chartreuse60": "140,209,136",
"--dark-chartreuse70": "158,217,163",
"--dark-chartreuse80": "178,222,188",
"--dark-chartreuse90": "209,238,220",
"--dark-chartreuse100": "245,255,250",
"--lightColor-fg": "rgb(10,11,13)",
"--lightColor-fgMuted": "rgb(91,97,110)",
"--lightColor-fgInverse": "rgb(255,255,255)",
"--lightColor-fgPrimary": "rgb(0,82,255)",
"--lightColor-fgWarning": "rgb(207,71,14)",
"--lightColor-fgPositive": "rgb(9,133,81)",
"--lightColor-fgNegative": "rgb(207,32,47)",
"--lightColor-bg": "rgb(255,255,255)",
"--lightColor-bgAlternate": "rgb(238,240,243)",
"--lightColor-bgInverse": "rgb(10,11,13)",
"--lightColor-bgOverlay": "rgba(50,53,61,0.33)",
"--lightColor-bgPrimary": "rgb(0,82,255)",
"--lightColor-bgPrimaryWash": "rgb(245,248,255)",
"--lightColor-bgSecondary": "rgb(238,240,243)",
"--lightColor-bgTertiary": "rgb(206,210,219)",
"--lightColor-bgSecondaryWash": "rgb(247,248,249)",
"--lightColor-bgNegative": "rgb(207,32,47)",
"--lightColor-bgNegativeWash": "rgb(255,245,246)",
"--lightColor-bgPositive": "rgb(9,133,81)",
"--lightColor-bgPositiveWash": "rgb(245,255,251)",
"--lightColor-bgWarning": "rgb(237,112,47)",
"--lightColor-bgWarningWash": "rgb(255,250,245)",
"--lightColor-currentColor": "currentColor",
"--lightColor-bgLine": "rgba(91,97,110,0.2)",
"--lightColor-bgLineHeavy": "rgba(91,97,110,0.66)",
"--lightColor-bgLineInverse": "rgb(255,255,255)",
"--lightColor-bgLinePrimary": "rgb(0,82,255)",
"--lightColor-bgLinePrimarySubtle": "rgb(115,162,255)",
"--lightColor-bgElevation1": "rgb(255,255,255)",
"--lightColor-bgElevation2": "rgb(255,255,255)",
"--lightColor-accentSubtleGreen": "rgb(245,255,251)",
"--lightColor-accentBoldGreen": "rgb(9,133,81)",
"--lightColor-accentSubtleBlue": "rgb(245,248,255)",
"--lightColor-accentBoldBlue": "rgb(0,82,255)",
"--lightColor-accentSubtlePurple": "rgb(251,247,255)",
"--lightColor-accentBoldPurple": "rgb(90,48,173)",
"--lightColor-accentSubtleYellow": "rgb(255,252,241)",
"--lightColor-accentBoldYellow": "rgb(247,210,26)",
"--lightColor-accentSubtleRed": "rgb(255,245,246)",
"--lightColor-accentBoldRed": "rgb(207,32,47)",
"--lightColor-accentSubtleGray": "rgb(238,240,243)",
"--lightColor-accentBoldGray": "rgb(50,53,61)",
"--lightColor-transparent": "rgba(255,255,255,0)",
"--darkColor-fg": "rgb(255,255,255)",
"--darkColor-fgInverse": "rgb(10,11,13)",
"--darkColor-fgMuted": "rgb(138,145,158)",
"--darkColor-fgPrimary": "rgb(87,139,250)",
"--darkColor-fgPositive": "rgb(39,173,117)",
"--darkColor-fgNegative": "rgb(240,97,109)",
"--darkColor-fgWarning": "rgb(248,150,86)",
"--darkColor-bg": "rgb(10,11,13)",
"--darkColor-bgAlternate": "rgb(20,21,25)",
"--darkColor-bgInverse": "rgb(255,255,255)",
"--darkColor-bgOverlay": "rgba(10,11,13,0.33)",
"--darkColor-bgPrimary": "rgb(87,139,250)",
"--darkColor-bgPrimaryWash": "rgb(0,16,51)",
"--darkColor-bgSecondary": "rgb(40,43,49)",
"--darkColor-bgTertiary": "rgb(50,53,61)",
"--darkColor-bgSecondaryWash": "rgb(20,21,25)",
"--darkColor-bgNegative": "rgb(240,97,109)",
"--darkColor-bgNegativeWash": "rgb(51,0,4)",
"--darkColor-bgPositive": "rgb(39,173,117)",
"--darkColor-bgPositiveWash": "rgb(0,31,18)",
"--darkColor-bgWarning": "rgb(199,158,0)",
"--darkColor-bgWarningWash": "rgb(51,13,0)",
"--darkColor-currentColor": "currentColor",
"--darkColor-bgLine": "rgba(138,145,158,0.2)",
"--darkColor-bgLineInverse": "rgb(10,11,13)",
"--darkColor-bgLineHeavy": "rgba(138,145,158,0.66)",
"--darkColor-bgLinePrimary": "rgb(87,139,250)",
"--darkColor-bgLinePrimarySubtle": "rgb(5,59,177)",
"--darkColor-bgElevation1": "rgb(20,21,25)",
"--darkColor-bgElevation2": "rgb(30,32,37)",
"--darkColor-accentSubtleGreen": "rgb(0,31,18)",
"--darkColor-accentBoldGreen": "rgb(39,173,117)",
"--darkColor-accentSubtleBlue": "rgb(0,16,51)",
"--darkColor-accentBoldBlue": "rgb(55,115,245)",
"--darkColor-accentSubtlePurple": "rgb(25,13,51)",
"--darkColor-accentBoldPurple": "rgb(230,201,255)",
"--darkColor-accentSubtleYellow": "rgb(27,6,0)",
"--darkColor-accentBoldYellow": "rgb(147,96,0)",
"--darkColor-accentSubtleRed": "rgb(51,0,4)",
"--darkColor-accentBoldRed": "rgb(240,97,109)",
"--darkColor-accentSubtleGray": "rgb(30,32,37)",
"--darkColor-accentBoldGray": "rgb(193,198,207)",
"--darkColor-transparent": "rgba(10,11,13,0)",
"--space-0": "0px",
"--space-1": "8px",
"--space-2": "16px",
"--space-3": "24px",
"--space-4": "32px",
"--space-5": "40px",
"--space-6": "48px",
"--space-7": "56px",
"--space-8": "64px",
"--space-9": "72px",
"--space-10": "80px",
"--space-0_25": "2px",
"--space-0_5": "4px",
"--space-0_75": "6px",
"--space-1_5": "12px",
"--borderWidth-0": "0px",
"--borderWidth-100": "1px",
"--borderWidth-200": "2px",
"--borderWidth-300": "4px",
"--borderWidth-400": "6px",
"--borderWidth-500": "8px",
"--borderRadius-0": "0px",
"--borderRadius-100": "4px",
"--borderRadius-200": "8px",
"--borderRadius-300": "12px",
"--borderRadius-400": "16px",
"--borderRadius-500": "24px",
"--borderRadius-600": "32px",
"--borderRadius-700": "40px",
"--borderRadius-800": "48px",
"--borderRadius-900": "56px",
"--borderRadius-1000": "100000px",
"--iconSize-xs": "12px",
"--iconSize-s": "16px",
"--iconSize-m": "24px",
"--iconSize-l": "32px",
"--avatarSize-s": "16px",
"--avatarSize-m": "24px",
"--avatarSize-l": "32px",
"--avatarSize-xl": "40px",
"--avatarSize-xxl": "48px",
"--avatarSize-xxxl": "56px",
"--controlSize-checkboxSize": "20px",
"--controlSize-radioSize": "20px",
"--controlSize-switchWidth": "52px",
"--controlSize-switchHeight": "32px",
"--controlSize-switchThumbSize": "30px",
"--controlSize-tileSize": "106px",
"--fontFamily-display1": "var(--defaultFont-sans)",
"--fontFamily-display2": "var(--defaultFont-sans)",
"--fontFamily-display3": "var(--defaultFont-sans)",
"--fontFamily-title1": "var(--defaultFont-sans)",
"--fontFamily-title2": "var(--defaultFont-sans)",
"--fontFamily-title3": "var(--defaultFont-sans)",
"--fontFamily-title4": "var(--defaultFont-sans)",
"--fontFamily-headline": "var(--defaultFont-sans)",
"--fontFamily-body": "var(--defaultFont-sans)",
"--fontFamily-label1": "var(--defaultFont-sans)",
"--fontFamily-label2": "var(--defaultFont-sans)",
"--fontFamily-caption": "var(--defaultFont-sans)",
"--fontFamily-legal": "var(--defaultFont-sans)",
"--fontFamilyMono-display1": "var(--defaultFont-mono)",
"--fontFamilyMono-display2": "var(--defaultFont-mono)",
"--fontFamilyMono-display3": "var(--defaultFont-mono)",
"--fontFamilyMono-title1": "var(--defaultFont-mono)",
"--fontFamilyMono-title2": "var(--defaultFont-mono)",
"--fontFamilyMono-title3": "var(--defaultFont-mono)",
"--fontFamilyMono-title4": "var(--defaultFont-mono)",
"--fontFamilyMono-headline": "var(--defaultFont-mono)",
"--fontFamilyMono-body": "var(--defaultFont-mono)",
"--fontFamilyMono-label1": "var(--defaultFont-mono)",
"--fontFamilyMono-label2": "var(--defaultFont-mono)",
"--fontFamilyMono-caption": "var(--defaultFont-mono)",
"--fontFamilyMono-legal": "var(--defaultFont-mono)",
"--fontSize-display1": "4rem",
"--fontSize-display2": "3rem",
"--fontSize-display3": "2.5rem",
"--fontSize-title1": "1.75rem",
"--fontSize-title2": "1.75rem",
"--fontSize-title3": "1.25rem",
"--fontSize-title4": "1.25rem",
"--fontSize-headline": "1rem",
"--fontSize-body": "1rem",
"--fontSize-label1": "0.875rem",
"--fontSize-label2": "0.875rem",
"--fontSize-caption": "0.8125rem",
"--fontSize-legal": "0.8125rem",
"--fontWeight-display1": "400",
"--fontWeight-display2": "400",
"--fontWeight-display3": "400",
"--fontWeight-title1": "600",
"--fontWeight-title2": "400",
"--fontWeight-title3": "600",
"--fontWeight-title4": "400",
"--fontWeight-headline": "600",
"--fontWeight-body": "400",
"--fontWeight-label1": "600",
"--fontWeight-label2": "400",
"--fontWeight-caption": "600",
"--fontWeight-legal": "400",
"--lineHeight-display1": "4.5rem",
"--lineHeight-display2": "3.5rem",
"--lineHeight-display3": "3rem",
"--lineHeight-title1": "2.25rem",
"--lineHeight-title2": "2.25rem",
"--lineHeight-title3": "1.75rem",
"--lineHeight-title4": "1.75rem",
"--lineHeight-headline": "1.5rem",
"--lineHeight-body": "1.5rem",
"--lineHeight-label1": "1.25rem",
"--lineHeight-label2": "1.25rem",
"--lineHeight-caption": "1rem",
"--lineHeight-legal": "1rem",
"--textTransform-display1": "none",
"--textTransform-display2": "none",
"--textTransform-display3": "none",
"--textTransform-title1": "none",
"--textTransform-title2": "none",
"--textTransform-title3": "none",
"--textTransform-title4": "none",
"--textTransform-headline": "none",
"--textTransform-body": "none",
"--textTransform-label1": "none",
"--textTransform-label2": "none",
"--textTransform-caption": "uppercase",
"--textTransform-legal": "none",
"--shadow-elevation1": "0px 8px 12px rgba(0, 0, 0, 0.12)",
"--shadow-elevation2": "0px 8px 24px rgba(0, 0, 0, 0.12)"
}

ThemeProvider classnames

The ThemeProvider renders with CSS classnames based on the activeColorScheme and the theme's id.

This allows you to style components based on the activeColorScheme or the theme's id.

// Renders with a .cds-default class and a .light class
<ThemeProvider theme={defaultTheme} activeColorScheme="light" />

Nested themes

ThemeProviders can be nested to create theme overrides for specific sections.

<ThemeProvider theme={defaultTheme} activeColorScheme="light">
{/* Default theme in light color scheme */}

<ThemeProvider theme={customTheme} activeColorScheme="dark">
{/* Custom theme in dark color scheme */}
</ThemeProvider>
</ThemeProvider>

When nesting, you may want to override specific color values from the current theme. Overrides must be conditionally applied because we don't enforce that a theme has both light and dark colors defined.

// Override parts of the parent theme
const theme = useTheme();
const customTheme = {
...theme,
...(theme.lightColor &&
theme.lightSpectrum && {
lightColor: {
...theme.lightColor,
bg: `rgb(${theme.lightSpectrum.orange50})`,
bgPrimary: `rgb(${theme.lightSpectrum.red20})`,
bgSecondary: `rgb(${theme.lightSpectrum.blue50})`,
},
}),
...(theme.darkColor &&
theme.darkSpectrum && {
darkColor: {
...theme.darkColor,
bg: `rgb(${theme.darkSpectrum.orange50})`,
bgPrimary: `rgb(${theme.darkSpectrum.red20})`,
bgSecondary: `rgb(${theme.darkSpectrum.blue50})`,
},
}),
} as const satisfies Theme;

Theme inheritence

Nested ThemeProviders do not automatically inherit the theme from their parent provider. You can manually inherit the theme with the useTheme hook.

const Example = () => {
// Pass the parent theme down to another ThemeProvider
const theme = useTheme();
return (
<ThemeProvider theme={theme} activeColorScheme={theme.activeColorScheme}>
{children}
</ThemeProvider>
);
};

InvertedThemeProvider component

The InvertedThemeProvider automatically inherits from its parent theme and flips the activeColorScheme to the opposite value.

<ThemeProvider theme={defaultTheme} activeColorScheme="light">
{/* Default theme in light color scheme */}

<InvertedThemeProvider>
{/* Default theme in inverse (dark) color scheme */}
</InvertedThemeProvider>
</ThemeProvider>

ThemeConfig vs Theme type

Use the ThemeConfig type when creating a theme, or when passing to the theme prop to the ThemeProvider.

Use the Theme type for the return value of the useTheme hook. The Theme type includes all the properties of ThemeConfig - plus the activeColorScheme, color, and spectrum properties.

See the ThemeConfig type definition here →

See the Theme type definition here →

Tip

Although the Theme type includes extra properties, you can still pass the useTheme return value directly to the ThemeProvider theme prop as shown in the theme inheritence section.

spectrum vs color values

The spectrum variables are partial "r,g,b" strings while color variables are complete CSS color values.

Both color and spectrum behave inversely in light and dark mode.

For example with the defaultTheme config, spectrum.gray0 is white in light mode and black in dark mode. We use spectrum variables to define color variables, so this same behavior extends to color.

The color variables have semantic names which describe their application in the UI. You should prefer to use color variables instead of spectrum variables when styling UI.

const theme = useTheme();
theme.lightSpectrum.gray0; // "255,255,255"
theme.darkSpectrum.gray0; // "10,11,13"
theme.spectrum.gray100; // "255,255,255" or "10,11,13", depends on activeColorScheme
theme.lightColor.bg; // "rgb(255,255,255)"
theme.darkColor.bg; // "rgb(10,11,13)"
theme.color.bg; // "rgb(255,255,255)" or "rgb(10,11,13)", depends on activeColorScheme
Tip

Prefer to use semantic color variables for UI styles. Direct usage of spectrum values should be a rare exception.

Creating a theme

Defining colors

We recommend defining lightSpectrum and darkSpectrum as separate objects. This makes it easier to reference them when defining the lightColor and darkColor values.

The lightColor and darkColor values must be raw color strings (hex, rgba, hsl, etc), they cannot contain CSS Variables or CSS functions.

The space scale

CDS expects that the theme space values will be multiples of some base number.

For example, the defaultTheme uses 8px as the base number:

theme.space[0]; // 0
theme.space[0.25]; // 2
theme.space[0.5]; // 4
theme.space[1]; // 8
theme.space[1.5]; // 12
theme.space[2]; // 16
theme.space[3]; // 24
// etc.

While it is possible to customize the space values in any way, deviating from this expectation may produce broken styles.

Example new theme

In this example we'll start with the defaultTheme and customize a couple values.

import type { ThemeConfig } from '@coinbase/cds-web/core/theme';
import { ThemeProvider } from '@coinbase/cds-web/system/ThemeProvider';
import { defaultTheme } from '@coinbase/cds-web/themes/defaultTheme';

// Define lightSpectrum and darkSpectrum as separate objects
const lightSpectrum = {
...defaultTheme.lightSpectrum,
blue60: '8,90,255',
};

const darkSpectrum = {
...defaultTheme.darkSpectrum,
blue60: '65,125,245',
};

// Use lightSpectrum and darkSpectrum to define the lightColor and darkColor values
const myTheme = {
...defaultTheme,
id: 'my-custom-theme',
lightSpectrum,
darkSpectrum,
lightColor: {
...defaultTheme.lightColor,
bgPrimary: `rgb(${lightSpectrum.red60})`,
},
darkColor: {
...defaultTheme.darkColor,
bgPrimary: `rgb(${darkSpectrum.red60})`,
},
} as const satisfies ThemeConfig;

const App = () => (
<ThemeProvider theme={myTheme} activeColorScheme="light">
{/* Your app components */}
</ThemeProvider>
);
Tip

Use the ThemeConfig type with TypeScript's satisfies keyword to enforce type safety for your theme.

defaultTheme config

The defaultTheme is a good example of a complete ThemeConfig. You can use it as an example when developing your own themes.

See the defaultTheme source code here →

{
"id": "cds-default",
"lightSpectrum": {
"blue0": "245,248,255",
"blue5": "211,225,255",
"blue10": "176,202,255",
"blue15": "146,182,255",
"blue20": "115,162,255",
"blue30": "70,132,255",
"blue40": "38,110,255",
"blue50": "16,94,255",
"blue60": "0,82,255",
"blue70": "0,75,235",
"blue80": "0,62,193",
"blue90": "0,41,130",
"blue100": "0,24,77",
"green0": "245,255,251",
"green5": "203,245,227",
"green10": "163,235,205",
"green15": "131,224,186",
"green20": "101,214,167",
"green30": "60,194,138",
"green40": "34,173,115",
"green50": "18,153,97",
"green60": "9,133,81",
"green70": "4,112,67",
"green80": "2,83,50",
"green90": "0,57,35",
"green100": "0,31,18",
"orange0": "255,250,245",
"orange5": "254,232,210",
"orange10": "253,213,176",
"orange15": "251,194,147",
"orange20": "249,174,118",
"orange30": "244,140,76",
"orange40": "237,112,47",
"orange50": "225,89,27",
"orange60": "207,71,14",
"orange70": "181,54,6",
"orange80": "145,39,2",
"orange90": "100,26,0",
"orange100": "51,13,0",
"gray0": "255,255,255",
"gray5": "247,248,249",
"gray10": "238,240,243",
"gray15": "222,225,231",
"gray20": "206,210,219",
"gray30": "177,183,195",
"gray40": "137,144,158",
"gray50": "113,120,134",
"gray60": "91,97,110",
"gray70": "70,75,85",
"gray80": "50,53,61",
"gray90": "30,32,37",
"gray100": "10,11,13",
"indigo0": "246,247,255",
"indigo5": "230,232,255",
"indigo10": "214,218,254",
"indigo15": "198,204,253",
"indigo20": "181,189,253",
"indigo30": "148,161,251",
"indigo40": "116,135,247",
"indigo50": "89,111,242",
"indigo60": "66,91,233",
"indigo70": "47,74,215",
"indigo80": "31,54,173",
"indigo90": "17,32,107",
"indigo100": "8,15,51",
"pink0": "255,245,255",
"pink5": "253,228,253",
"pink10": "251,212,250",
"pink15": "248,195,245",
"pink20": "244,178,240",
"pink30": "235,143,227",
"pink40": "221,110,209",
"pink50": "203,81,187",
"pink60": "179,58,162",
"pink70": "149,39,133",
"pink80": "116,26,102",
"pink90": "83,17,72",
"pink100": "51,10,44",
"purple0": "251,247,255",
"purple5": "244,232,255",
"purple10": "237,217,255",
"purple15": "230,201,255",
"purple20": "222,184,255",
"purple30": "205,153,253",
"purple40": "188,123,251",
"purple50": "157,107,242",
"purple60": "138,85,233",
"purple70": "119,67,215",
"purple80": "90,48,173",
"purple90": "54,27,107",
"purple100": "25,13,51",
"red0": "255,245,246",
"red5": "254,225,228",
"red10": "253,206,210",
"red15": "251,186,191",
"red20": "249,166,173",
"red30": "244,127,136",
"red40": "237,89,102",
"red50": "225,57,71",
"red60": "207,32,47",
"red70": "181,15,29",
"red80": "145,5,16",
"red90": "100,1,9",
"red100": "51,0,4",
"teal0": "240,254,255",
"teal5": "188,246,253",
"teal10": "136,237,251",
"teal15": "93,226,248",
"teal20": "51,213,244",
"teal30": "0,188,235",
"teal40": "0,169,221",
"teal50": "0,147,203",
"teal60": "0,123,179",
"teal70": "0,97,149",
"teal80": "0,71,116",
"teal90": "0,47,83",
"teal100": "0,27,51",
"yellow0": "255,252,241",
"yellow5": "255,244,192",
"yellow10": "255,240,145",
"yellow15": "255,234,100",
"yellow20": "255,228,54",
"yellow30": "247,210,26",
"yellow40": "235,186,0",
"yellow50": "207,151,0",
"yellow60": "174,113,0",
"yellow70": "136,76,0",
"yellow80": "96,48,0",
"yellow90": "58,20,0",
"yellow100": "27,6,0",
"chartreuse0": "245,255,250",
"chartreuse5": "221,251,232",
"chartreuse10": "198,247,209",
"chartreuse15": "176,242,182",
"chartreuse20": "159,238,155",
"chartreuse30": "137,223,117",
"chartreuse40": "127,208,87",
"chartreuse50": "86,179,64",
"chartreuse60": "53,151,48",
"chartreuse70": "35,122,43",
"chartreuse80": "25,93,41",
"chartreuse90": "17,64,35",
"chartreuse100": "7,26,17"
},
"darkSpectrum": {
"blue0": "0,16,51",
"blue5": "1,29,91",
"blue10": "1,42,130",
"blue15": "3,51,154",
"blue20": "5,59,177",
"blue30": "10,72,206",
"blue40": "19,84,225",
"blue50": "33,98,238",
"blue60": "55,115,245",
"blue70": "87,139,250",
"blue80": "132,170,253",
"blue90": "185,207,255",
"blue100": "245,248,255",
"green0": "0,31,18",
"green5": "0,48,29",
"green10": "1,70,42",
"green15": "2,82,48",
"green20": "2,92,55",
"green30": "6,112,68",
"green40": "11,133,82",
"green50": "21,153,98",
"green60": "39,173,117",
"green70": "68,194,141",
"green80": "111,214,171",
"green90": "171,235,208",
"green100": "245,255,251",
"orange0": "51,13,0",
"orange5": "79,20,0",
"orange10": "107,28,1",
"orange15": "131,36,2",
"orange20": "155,44,4",
"orange30": "189,59,9",
"orange40": "213,76,18",
"orange50": "230,96,32",
"orange60": "240,120,54",
"orange70": "248,150,86",
"orange80": "252,185,131",
"orange90": "254,219,185",
"orange100": "255,250,245",
"gray0": "10,11,13",
"gray5": "20,21,25",
"gray10": "30,32,37",
"gray15": "40,43,49",
"gray20": "50,53,61",
"gray30": "70,75,85",
"gray40": "91,97,110",
"gray50": "114,120,134",
"gray60": "138,145,158",
"gray70": "165,170,182",
"gray80": "193,198,207",
"gray90": "224,226,231",
"gray100": "255,255,255",
"indigo0": "8,15,51",
"indigo5": "14,27,91",
"indigo10": "21,39,130",
"indigo15": "27,47,154",
"indigo20": "33,56,177",
"indigo30": "48,73,206",
"indigo40": "68,92,225",
"indigo50": "92,113,238",
"indigo60": "121,138,245",
"indigo70": "153,165,250",
"indigo80": "187,194,253",
"indigo90": "219,223,255",
"indigo100": "246,247,255",
"pink0": "51,10,44",
"pink5": "70,14,61",
"pink10": "89,19,78",
"pink15": "108,24,94",
"pink20": "126,30,111",
"pink30": "159,44,142",
"pink40": "187,64,170",
"pink50": "208,88,193",
"pink60": "225,117,214",
"pink70": "237,149,230",
"pink80": "246,184,243",
"pink90": "252,217,251",
"pink100": "255,245,255",
"purple0": "25,13,51",
"purple5": "43,22,89",
"purple10": "73,30,137",
"purple15": "97,37,175",
"purple20": "123,45,211",
"purple30": "142,51,234",
"purple40": "164,84,244",
"purple50": "188,123,251",
"purple60": "205,153,253",
"purple70": "217,176,254",
"purple80": "230,201,255",
"purple90": "237,217,255",
"purple100": "251,247,255",
"red0": "51,0,4",
"red5": "79,0,7",
"red10": "107,1,10",
"red15": "131,4,14",
"red20": "155,7,19",
"red30": "189,19,33",
"red40": "213,38,52",
"red50": "230,64,78",
"red60": "240,97,109",
"red70": "248,134,144",
"red80": "252,174,181",
"red90": "254,213,216",
"red100": "255,245,246",
"teal0": "0,20,38",
"teal5": "0,32,59",
"teal10": "0,45,79",
"teal15": "0,58,99",
"teal20": "0,72,118",
"teal30": "0,99,153",
"teal40": "0,125,182",
"teal50": "0,149,205",
"teal60": "0,170,223",
"teal70": "6,190,236",
"teal80": "69,217,245",
"teal90": "149,239,251",
"teal100": "240,254,255",
"yellow0": "27,6,0",
"yellow5": "49,17,0",
"yellow10": "81,40,0",
"yellow15": "96,48,0",
"yellow20": "115,64,0",
"yellow30": "147,96,0",
"yellow40": "175,128,0",
"yellow50": "199,158,0",
"yellow60": "222,189,23",
"yellow70": "229,205,48",
"yellow80": "242,222,94",
"yellow90": "255,240,145",
"yellow100": "255,252,241",
"chartreuse0": "5,22,14",
"chartreuse5": "14,54,29",
"chartreuse10": "21,79,34",
"chartreuse15": "29,103,36",
"chartreuse20": "45,128,40",
"chartreuse30": "73,152,54",
"chartreuse40": "107,176,73",
"chartreuse50": "123,200,105",
"chartreuse60": "140,209,136",
"chartreuse70": "158,217,163",
"chartreuse80": "178,222,188",
"chartreuse90": "209,238,220",
"chartreuse100": "245,255,250"
},
"lightColor": {
"fg": "rgb(10,11,13)",
"fgMuted": "rgb(91,97,110)",
"fgInverse": "rgb(255,255,255)",
"fgPrimary": "rgb(0,82,255)",
"fgWarning": "rgb(207,71,14)",
"fgPositive": "rgb(9,133,81)",
"fgNegative": "rgb(207,32,47)",
"bg": "rgb(255,255,255)",
"bgAlternate": "rgb(238,240,243)",
"bgInverse": "rgb(10,11,13)",
"bgOverlay": "rgba(50,53,61,0.33)",
"bgPrimary": "rgb(0,82,255)",
"bgPrimaryWash": "rgb(245,248,255)",
"bgSecondary": "rgb(238,240,243)",
"bgTertiary": "rgb(206,210,219)",
"bgSecondaryWash": "rgb(247,248,249)",
"bgNegative": "rgb(207,32,47)",
"bgNegativeWash": "rgb(255,245,246)",
"bgPositive": "rgb(9,133,81)",
"bgPositiveWash": "rgb(245,255,251)",
"bgWarning": "rgb(237,112,47)",
"bgWarningWash": "rgb(255,250,245)",
"currentColor": "currentColor",
"bgLine": "rgba(91,97,110,0.2)",
"bgLineHeavy": "rgba(91,97,110,0.66)",
"bgLineInverse": "rgb(255,255,255)",
"bgLinePrimary": "rgb(0,82,255)",
"bgLinePrimarySubtle": "rgb(115,162,255)",
"bgElevation1": "rgb(255,255,255)",
"bgElevation2": "rgb(255,255,255)",
"accentSubtleGreen": "rgb(245,255,251)",
"accentBoldGreen": "rgb(9,133,81)",
"accentSubtleBlue": "rgb(245,248,255)",
"accentBoldBlue": "rgb(0,82,255)",
"accentSubtlePurple": "rgb(251,247,255)",
"accentBoldPurple": "rgb(90,48,173)",
"accentSubtleYellow": "rgb(255,252,241)",
"accentBoldYellow": "rgb(247,210,26)",
"accentSubtleRed": "rgb(255,245,246)",
"accentBoldRed": "rgb(207,32,47)",
"accentSubtleGray": "rgb(238,240,243)",
"accentBoldGray": "rgb(50,53,61)",
"transparent": "rgba(255,255,255,0)"
},
"darkColor": {
"fg": "rgb(255,255,255)",
"fgInverse": "rgb(10,11,13)",
"fgMuted": "rgb(138,145,158)",
"fgPrimary": "rgb(87,139,250)",
"fgPositive": "rgb(39,173,117)",
"fgNegative": "rgb(240,97,109)",
"fgWarning": "rgb(248,150,86)",
"bg": "rgb(10,11,13)",
"bgAlternate": "rgb(20,21,25)",
"bgInverse": "rgb(255,255,255)",
"bgOverlay": "rgba(10,11,13,0.33)",
"bgPrimary": "rgb(87,139,250)",
"bgPrimaryWash": "rgb(0,16,51)",
"bgSecondary": "rgb(40,43,49)",
"bgTertiary": "rgb(50,53,61)",
"bgSecondaryWash": "rgb(20,21,25)",
"bgNegative": "rgb(240,97,109)",
"bgNegativeWash": "rgb(51,0,4)",
"bgPositive": "rgb(39,173,117)",
"bgPositiveWash": "rgb(0,31,18)",
"bgWarning": "rgb(199,158,0)",
"bgWarningWash": "rgb(51,13,0)",
"currentColor": "currentColor",
"bgLine": "rgba(138,145,158,0.2)",
"bgLineInverse": "rgb(10,11,13)",
"bgLineHeavy": "rgba(138,145,158,0.66)",
"bgLinePrimary": "rgb(87,139,250)",
"bgLinePrimarySubtle": "rgb(5,59,177)",
"bgElevation1": "rgb(20,21,25)",
"bgElevation2": "rgb(30,32,37)",
"accentSubtleGreen": "rgb(0,31,18)",
"accentBoldGreen": "rgb(39,173,117)",
"accentSubtleBlue": "rgb(0,16,51)",
"accentBoldBlue": "rgb(55,115,245)",
"accentSubtlePurple": "rgb(25,13,51)",
"accentBoldPurple": "rgb(230,201,255)",
"accentSubtleYellow": "rgb(27,6,0)",
"accentBoldYellow": "rgb(147,96,0)",
"accentSubtleRed": "rgb(51,0,4)",
"accentBoldRed": "rgb(240,97,109)",
"accentSubtleGray": "rgb(30,32,37)",
"accentBoldGray": "rgb(193,198,207)",
"transparent": "rgba(10,11,13,0)"
},
"space": {
"0": 0,
"1": 8,
"2": 16,
"3": 24,
"4": 32,
"5": 40,
"6": 48,
"7": 56,
"8": 64,
"9": 72,
"10": 80,
"0.25": 2,
"0.5": 4,
"0.75": 6,
"1.5": 12
},
"borderWidth": {
"0": 0,
"100": 1,
"200": 2,
"300": 4,
"400": 6,
"500": 8
},
"borderRadius": {
"0": 0,
"100": 4,
"200": 8,
"300": 12,
"400": 16,
"500": 24,
"600": 32,
"700": 40,
"800": 48,
"900": 56,
"1000": 100000
},
"iconSize": {
"xs": 12,
"s": 16,
"m": 24,
"l": 32
},
"avatarSize": {
"s": 16,
"m": 24,
"l": 32,
"xl": 40,
"xxl": 48,
"xxxl": 56
},
"controlSize": {
"checkboxSize": 20,
"radioSize": 20,
"switchWidth": 52,
"switchHeight": 32,
"switchThumbSize": 30,
"tileSize": 106
},
"fontFamily": {
"display1": "var(--defaultFont-sans)",
"display2": "var(--defaultFont-sans)",
"display3": "var(--defaultFont-sans)",
"title1": "var(--defaultFont-sans)",
"title2": "var(--defaultFont-sans)",
"title3": "var(--defaultFont-sans)",
"title4": "var(--defaultFont-sans)",
"headline": "var(--defaultFont-sans)",
"body": "var(--defaultFont-sans)",
"label1": "var(--defaultFont-sans)",
"label2": "var(--defaultFont-sans)",
"caption": "var(--defaultFont-sans)",
"legal": "var(--defaultFont-sans)"
},
"fontFamilyMono": {
"display1": "var(--defaultFont-mono)",
"display2": "var(--defaultFont-mono)",
"display3": "var(--defaultFont-mono)",
"title1": "var(--defaultFont-mono)",
"title2": "var(--defaultFont-mono)",
"title3": "var(--defaultFont-mono)",
"title4": "var(--defaultFont-mono)",
"headline": "var(--defaultFont-mono)",
"body": "var(--defaultFont-mono)",
"label1": "var(--defaultFont-mono)",
"label2": "var(--defaultFont-mono)",
"caption": "var(--defaultFont-mono)",
"legal": "var(--defaultFont-mono)"
},
"fontSize": {
"display1": "4rem",
"display2": "3rem",
"display3": "2.5rem",
"title1": "1.75rem",
"title2": "1.75rem",
"title3": "1.25rem",
"title4": "1.25rem",
"headline": "1rem",
"body": "1rem",
"label1": "0.875rem",
"label2": "0.875rem",
"caption": "0.8125rem",
"legal": "0.8125rem"
},
"fontWeight": {
"display1": "400",
"display2": "400",
"display3": "400",
"title1": "600",
"title2": "400",
"title3": "600",
"title4": "400",
"headline": "600",
"body": "400",
"label1": "600",
"label2": "400",
"caption": "600",
"legal": "400"
},
"lineHeight": {
"display1": "4.5rem",
"display2": "3.5rem",
"display3": "3rem",
"title1": "2.25rem",
"title2": "2.25rem",
"title3": "1.75rem",
"title4": "1.75rem",
"headline": "1.5rem",
"body": "1.5rem",
"label1": "1.25rem",
"label2": "1.25rem",
"caption": "1rem",
"legal": "1rem"
},
"textTransform": {
"display1": "none",
"display2": "none",
"display3": "none",
"title1": "none",
"title2": "none",
"title3": "none",
"title4": "none",
"headline": "none",
"body": "none",
"label1": "none",
"label2": "none",
"caption": "uppercase",
"legal": "none"
},
"shadow": {
"elevation1": "0px 8px 12px rgba(0, 0, 0, 0.12)",
"elevation2": "0px 8px 24px rgba(0, 0, 0, 0.12)"
}
}

ThemeVars namespace

The ThemeVars namespace contains type definitions for all themeable variable names in CDS. It includes any custom theme variables added in ThemeVarsExtended.

import type { ThemeVars } from '@coinbase/cds-common/core/theme';

// All theme variables are accessible through ThemeVars
ThemeVars.Color; // 'fg' | 'bg' | 'bgPrimary' | 'bgSecondary' | ...
ThemeVars.SpectrumColor; // 'blue60' | 'red40' | 'gray100' | ...
ThemeVars.SpectrumHue; // 'blue' | 'green' | 'orange' | 'gray' | ...
ThemeVars.SpectrumHueStep; // 0 | 5 | 10 | 20 | ...
ThemeVars.Space; // 0 | 0.25 | 0.5 | 1 | 2 | ...
ThemeVars.BorderWidth; // 0 | 100 | 200 | ...
ThemeVars.BorderRadius; // 0 | 100 | 200 | ...
ThemeVars.Font; // 'display1' | 'title1' | 'body' | ...
ThemeVars.FontFamily; // 'display1' | 'title1' | 'body' | ...
ThemeVars.FontSize; // 'display1' | 'title1' | 'body' | ...
ThemeVars.FontWeight; // 'display1' | 'title1' | 'body' | ...
ThemeVars.LineHeight; // 'display1' | 'title1' | 'body' | ...
ThemeVars.TextTransform; // 'display1' | 'title1' | 'body' | ...
ThemeVars.IconSize; // 'xs' | 's' | 'm' | 'l'
ThemeVars.AvatarSize; // 's' | 'm' | 'l' | 'xl' | ...
ThemeVars.ControlSize; // 'checkboxSize' | 'radioSize' | ...

Extending the theme

You can extend the theme by adding custom theme variables. In this example we'll show how to add a custom color variable, but you can extend other types of ThemeVars as well.

Start by overriding interfaces in the ThemeVarsExtended namespace to add new theme variables. Only the key names are used, the void type is just a necessary placeholder.

declare module '@coinbase/cds-common/core/theme' {
export namespace ThemeVarsExtended {
export interface Color {
myCustomColor: void;
}
}
}

This adds myCustomColor to ThemeVars.Color - which enforces that this variable must be defined in your theme to satisfy the ThemeConfig type, and allows this variable name to be passed to the StyleProps API anywhere that theme colors are accepted.

Now that myCustomColor is defined in your theme the useTheme hook will include it in the return value, and the ThemeProvider will create CSS Variables for this value just like every other ThemeVars.Color.

Next define the corresponding static classnames for your new theme variables via the initializeCDS function extendStyleProps options. These static classnames should use the CSS Variable that will be created by the ThemeProvider.

Tip

Call the initializeCDS function only once in your app entry point, before your app renders.

Web StyleProps support responsive syntax, so you must provide 4 unique classnames per style prop: one each for base, phone, tablet, and desktop. Use the CDS media object to use the same responsive breakpoints as CDS.

import { initializeCDS } from '@coinbase/cds-web/styles/config';

initializeCDS({
extendStyleProps: {
// Specify the ThemeVars interface name that you extended
Color: {
// Specify the new theme variable name that you added
myCustomColor: {
// Configure the necessary static classNames for the new theme variable
background: {
base: 'background-myCustomColor',
phone: 'background-myCustomColor-phone',
tablet: 'background-myCustomColor-tablet',
desktop: 'background-myCustomColor-desktop',
},
color: {
base: 'color-myCustomColor',
phone: 'color-myCustomColor-phone',
tablet: 'color-myCustomColor-tablet',
desktop: 'color-myCustomColor-desktop',
},
borderColor: {
base: 'borderColor-myCustomColor',
phone: 'borderColor-myCustomColor-phone',
tablet: 'borderColor-myCustomColor-tablet',
desktop: 'borderColor-myCustomColor-desktop',
},
},
},
},
});

With the classnames defined as follows:

.background-myCustomColor {
background-color: var(--color-myCustomColor);
}

.background-myCustomColor-phone {
@media (max-width: 767px) {
background-color: var(--color-myCustomColor);
}
}

.background-myCustomColor-tablet {
@media (min-width: 768px) and (max-width: 1279px) {
background-color: var(--color-myCustomColor);
}
}

.background-myCustomColor-desktop {
@media (min-width: 1280px) {
background-color: var(--color-myCustomColor);
}
}

/* etc for color and borderColor */

Or, using CSS-in-JS:

import { css } from '@linaria/core';
import { media } from '@coinbase/cds-web/styles/media';

const myCustomColor = {
background: {
base: css`
background-color: var(--color-myCustomColor);
`,
phone: css`
@media ${media.phone} {
background-color: var(--color-myCustomColor);
}
`,
tablet: css`
@media ${media.tablet} {
background-color: var(--color-myCustomColor);
}
`,
desktop: css`
@media ${media.desktop} {
background-color: var(--color-myCustomColor);
}
`,
},
// etc for color and borderColor
};

Is this page useful?

Coinbase Design is an open-source, adaptable system of guidelines, components, and tools that aid the best practices of user interface design for crypto products.