Getting Started
Theming
Customizing the default light and dark theme.
Theme Structure
Tremor's theming is managed in the theme section of your tailwind.config.js file. It includes a customizable light and dark mode, allowing you to tailor your design. Within the theme, you have the flexibility to define colors, border radii, shadows, and font sizes.
Note that by default the prefers-color-scheme CSS media feature is used to toggle the dark mode. If you want to use light mode only, add darkMode: "class" to the tailwind.config.js file.
Theme Tokens
To personalize the theme, modify the tokens accordingly. Each component has its own dedicated Theming section that provides further information about the theming tokens utilized in that particular component.
const colors = require('tailwindcss/colors'); module.exports = { // ... theme: { transparent: 'transparent', current: 'currentColor', extend: { colors: { // light mode tremor: { brand: { faint: colors.blue[50], muted: colors.blue[200], subtle: colors.blue[400], DEFAULT: colors.blue[500], emphasis: colors.blue[700], inverted: colors.white, }, background: { muted: colors.gray[50], subtle: colors.gray[100], DEFAULT: colors.white, emphasis: colors.gray[700], }, border: { DEFAULT: colors.gray[200], }, ring: { DEFAULT: colors.gray[200], }, content: { subtle: colors.gray[400], DEFAULT: colors.gray[500], emphasis: colors.gray[700], strong: colors.gray[900], inverted: colors.white, }, }, // dark mode 'dark-tremor': { brand: { faint: '#0B1229', muted: colors.blue[950], subtle: colors.blue[800], DEFAULT: colors.blue[500], emphasis: colors.blue[400], inverted: colors.blue[950], }, background: { muted: '#131A2B', subtle: colors.gray[800], DEFAULT: colors.gray[900], emphasis: colors.gray[300], }, border: { DEFAULT: colors.gray[800], }, ring: { DEFAULT: colors.gray[800], }, content: { subtle: colors.gray[600], DEFAULT: colors.gray[500], emphasis: colors.gray[200], strong: colors.gray[50], inverted: colors.gray[950], }, }, }, boxShadow: { // light 'tremor-input': '0 1px 2px 0 rgb(0 0 0 / 0.05)', 'tremor-card': '0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)', 'tremor-dropdown': '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)', // dark 'dark-tremor-input': '0 1px 2px 0 rgb(0 0 0 / 0.05)', 'dark-tremor-card': '0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)', 'dark-tremor-dropdown': '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)', }, borderRadius: { 'tremor-small': '0.375rem', 'tremor-default': '0.5rem', 'tremor-full': '9999px', }, fontSize: { 'tremor-label': ['0.75rem', { lineHeight: '1rem' }], 'tremor-default': ['0.875rem', { lineHeight: '1.25rem' }], 'tremor-title': ['1.125rem', { lineHeight: '1.75rem' }], 'tremor-metric': ['1.875rem', { lineHeight: '2.25rem' }], }, }, }, safelist: [ { pattern: /^(bg-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/, variants: ['hover', 'ui-selected'], }, { pattern: /^(text-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/, variants: ['hover', 'ui-selected'], }, { pattern: /^(border-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/, variants: ['hover', 'ui-selected'], }, { pattern: /^(ring-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/, }, { pattern: /^(stroke-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/, }, { pattern: /^(fill-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/, }, ], plugins: [require('@headlessui/tailwindcss'), require('@tailwindcss/forms')],};
Notes on dark mode
Tremor uses by default your system preference (prefers-color-scheme CSS) to decide with mode is rendered. If you want to use white mode only, or manually switch to dark mode, add the following to your tailwind.config.js file.
module.exports = { darkMode: 'class', // ...};
Now, rather than relying on the prefers-color-scheme to determine the use of dark: classes, their application is contingent on the presence of the dark class higher up in the HTML hierarchy. Lastly, if you would like to switch themes with a button, we highly recommend next-themes.
Theming Example
Here's a KPI card with Tremor's standard light theme.
Revenue
45.598
$36.5% ($45.564)
78.484
We are tasked to make the light theme to fit our brand, which means, matching a particular shade of orange: #F97315. To bring our theme on brand, we look up the ProgressBar's documentation on Theming.
Element | Theme Token |
---|---|
Roundness borderRadiustremor-full | borderRadiustremor-full |
Background color colorstremor-brand-faint | colorstremor-brand-faint |
Progress color colorstremor-brand-DEFAULT | colorstremor-brand-DEFAULT |
Label color colorstremor-content-emphasis | colorstremor-content-emphasis |
Font size fontSizetremor-default | fontSizetremor-default |
To achieve our goal, we have to change two tokens. The background color token: tremor-brand-faint and the progress color token: tremor-brand-DEFAULT. In our tailwind.config.js file, we look up the tokens in the colors section and make our changes.
module.exports = { // ... theme: { transparent: 'transparent', current: 'currentColor', extend: { colors: { // light mode tremor: { brand: { faint: '#F9BD9C', // <--- tremor-brand-faint, lighter shade of brand color muted: colors.blue[200], subtle: colors.blue[400], DEFAULT: '#F99157', // <--- tremor-brand-DEFAULT, brand color emphasis: colors.blue[700], inverted: colors.white, }, // ... }, }, }, },};
The resulting change of changing our brand color to orange:
Revenue
45.598
$36.5% ($45.564)
78.484
Custom Charts Colors
The Area, Bar, Line, Donut, and Scatter Chart allow you to set a custom color, e.g. #FFCC33. To ensure Tailwind generates classNames at build time to mirror classNames calculated at run time, you have to include your custom colors in your tailwind.config.js file.
For example, here is a BarChart with a customised yellow:
As you can see, in the code example, we pass the custom color to the colors array.
// ... <Card className="max-w-2xl mx-auto"> <BarChart className="h-72 mt-4" data={...} index="date" categories={["Distance Running", "Road Cycling"]} colors={["purple", "#ffcc33"]} // <-- Custom color yAxisWidth={30} /> </Card>
Now, we have to update the safelist in the tailwind.config.js with the custom color, to make it work. After you updated the config, make sure to restart the server.
// ...{ pattern: /^(fill-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950))$/,},// We add this flatMap to the safelist. You can pass more than one color if needed. E.g. "[#ffcc33]","[#161616]"...["[#ffcc33]"].flatMap((customColor) => [ `bg-${customColor}`, `border-${customColor}`, `hover:bg-${customColor}`, `hover:border-${customColor}`, `hover:text-${customColor}`, `fill-${customColor}`, `ring-${customColor}`, `stroke-${customColor}`, `text-${customColor}`, `ui-selected:bg-${customColor}`, `ui-selected:border-${customColor}`, `ui-selected:text-${customColor}`,]),],plugins: [// ...