Palette

A guide to customizing the palette of your theme.

Tailus UI React is built on top of Tailwind Css, which means that you can customize the colors of your theme by changing the colors in the tailwind.config.js file.

Semantic Naming

Our color system uses semantic color names to make it intuitive to understand the purpose of each color. For instance, primary is used for primary actions, success for success notifications, danger for error alerts, and so on. This approach simplifies the process of customizing and maintaining your application’s color palette.

Required Colors

For the theme to function properly, certain colors are necessary. Each color should have shades ranging from 50 to 950. However, the gray color is an exception and must include an additional 925 shade.

Brand

Primary

Secondary

Accent

Feedback

Success

Danger

Warning

Info

Neutral

Gray

Default Palettes

Tailus UI React comes with nine pre-configured color palettes for a quick start.

To use these default palettes, you need to import the palettes object.

import { palettes } from "@tailus/themer"

The available palettes are as follows:

trust

theme: {
    extend: {
        colors: palettes.trust,
    }
}

romance

theme: {
    extend: {
        colors: palettes.romance,
    }
}

passion

theme: {
    extend: {
        colors: palettes.passion,
    }
}

energy

theme: {
    extend: {
        colors: palettes.energy,
    }
}

nature

theme: {
    extend: {
        colors: palettes.nature,
    }
}

mystery

theme: {
    extend: {
        colors: palettes.mystery,
    }
}

oz

theme: {
    extend: {
        colors: palettes.oz,
    }
}

spring

theme: {
    extend: {
        colors: palettes.spring,
    }
}

winter

theme: {
    extend: {
        colors: palettes.winter,
    }
}

Override default palettes

If you want to override a color in a palette, you can simply replace it with a new color. This new color can be from Tailwind’s default colors or your own custom colors.

For instance, in the oz palette, indigo is the primary color. If you wish to change this primary color to purple, you can use the spread operator to merge the existing oz palette with your new color. This way, all the original colors are preserved, and the primary color is replaced with purple.

theme : {
    extend : {
        colors: ({colors}) => ({
            ...palettes.oz,
            primary: colors.purple,
        })
    }
},

If you wish to replace a gray color with a default gray color from Tailwind CSS, we recommend using the grays from @tailus/themer . This is because it includes a 925 shade, providing a wider range of shades.

import { grays } from "@tailus/themer"
theme : {
    extend : {
        colors: ({colors}) => ({
            ...palettes.oz,
            primary: colors.purple,
            gray: grays.slate,
        })
    }
},

Using Css variables

Please read the Tailwind Css documentation to learn more about how to define your colors as css variables

Multi Theming

If you aim to offer multiple themes in your application, consider using the palette plugin from @tailus/themer. This plugin provides nine pre-configured palettes. You can easily switch between these palettes using the data-palette attribute, allowing your users to select their preferred theme.

import { palette } from "@tailus/themer"
theme : {
    extend : {},
},
plugins : [
    palette,

    // ...other plugins
]

Theme Switcher

Build a theme switcher to let your users choose their preferred one

"use client"
import * as RadioGroup from "@radix-ui/react-radio-group"
import { useState, useEffect } from "react";
import { palettesArray, type Palette } from "@tailus/themer"

export const ThemeSwitcher = () => {

    const [palette, setPalette] = useState<Palette>(() => {
        return (localStorage.getItem('appTheme') as Palette) || "trust";
    });

    const setTheme = (root:HTMLElement, palette: Palette) => {
        root.setAttribute("data-palette", palette)
        setPalette(palette)
        localStorage.setItem('appTheme', palette);
    }
    
    useEffect(() => {
        const root = document.querySelector("[data-palette]") as HTMLElement
        setTheme(root,palette)
    }, [palette])

    return (
        <RadioGroup.Root
            className="grid grid-cols-6 gap-3"
            defaultValue={palette}
            onValueChange={(value) => setPalette(value as Palette)}
        >
            {
                palettesArray.map((palette, index) => (
                    <RadioGroup.Item
                        value={palette}
                        className="relative bg-primary-600 dark:border dark:border-white/25 rounded-full overflow-hidden flex outline-2 outline-offset-2 outline-primary-600 focus-visible:outline"
                        data-palette={palette}
                        aria-label={`Palette ${palette}`}
                        key={index}
                    >
                        <RadioGroup.Indicator className="absolute z-[1] size-2 inset-0 m-auto shadow-md shadow-gray-950/50 bg-white rounded-full" />
                        <div className="col-start-2 blur-[6px] w-1/2 ml-auto h-full">
                            <div className="h-1/2 bg-secondary-500" />
                            <div className="h-1/2 bg-accent-400" />
                        </div>
                    </RadioGroup.Item>
                ))
            }
        </RadioGroup.Root>
    )
}

Customize a palette

To modify a palette, you’ll use CSS variables. We’ve converted all default Tailwind CSS colors, along with our three unique grays (cyanish, greenish, and indigray), into CSS variables. If you want to customize a palette, such as changing the primary color of the oz palette, you’ll do this in the base layer.

@layer base {
    [data-palette="oz"] {
        --colors-primary-50: var(--colors-purple-50);
        --colors-primary-100: var(--colors-purple-100);
        --colors-primary-200: var(--colors-purple-200);
        --colors-primary-300: var(--colors-purple-300);
        --colors-primary-400: var(--colors-purple-400);
        --colors-primary-500: var(--colors-purple-500);
        --colors-primary-600: var(--colors-purple-600);
        --colors-primary-700: var(--colors-purple-700);
        --colors-primary-800: var(--colors-purple-800);
        --colors-primary-900: var(--colors-purple-900);
        --colors-primary-950: var(--colors-purple-950);
    }
}

With your own color

To set your own color, you first need to convert all its shades to the RGB format. However, this format should exclude commas, round brackets, and the alpha value. For example, an RGB color would be represented as 168 85 247.

@layer base {
    [data-palette="oz"] {
        --colors-primary-50: 250 245 255;
        --colors-primary-100: 243 232 255;
        --colors-primary-200: 233 213 255;
        --colors-primary-300: 216 180 254;
        --colors-primary-400: 192 132 252;
        --colors-primary-500: 168 85 247;
        --colors-primary-600: 147 51 234;
        --colors-primary-700: 126 34 206;
        --colors-primary-800: 107 33 168;
        --colors-primary-900: 88 28 135;
        --colors-primary-950: 59 7 100;
    }
}

Adding a new palette

To create a new palette, define a new [data-palette="your palette name"] selector. Inside this selector, add your custom colors or use the default colors from Tailwind CSS. Remember, a palette must include eight colors: primary, secondary, accent, info, danger, success, warning, and gray.

@layer base{
    [data-palette="lualaba"]{
        // ...your colors here
    }
}

Removing a palette

Actually, you can’t directly remove a palette. However, you can exclude it from the palettesArray and the Palette type to prevent it from being used in your application.

"use client"
import * as RadioGroup from "@radix-ui/react-radio-group"
import { useState, useEffect } from "react";
import { palettesArray, type Palette } from "@tailus/themer"

type PaletteWithoutOz = Exclude<Palette, "oz">

export const ThemeSwitcher = () => {

    const [palette, setPalette] = useState<PaletteWithoutOz>(() => {
        return (localStorage.getItem('appTheme') as PaletteWithoutOz) || "trust";
    });

    const setTheme = (root:HTMLElement, palette: PaletteWithoutOz) => {
        root.setAttribute("data-palette", palette)
        setPalette(palette)
        localStorage.setItem('appTheme', palette);
    }
    
    useEffect(() => {
        const root = document.querySelector("[data-palette]") as HTMLElement
        setTheme(root,palette)
    }, [palette])

    return (
        <RadioGroup.Root
            className="grid grid-cols-6 gap-3"
            defaultValue={palette}
            onValueChange={(value) => setPalette(value as PaletteWithoutOz)}
        >
            {
                palettesArray.map((palette, index) => (
                    <RadioGroup.Item
                        value={palette}
                        className="relative bg-primary-600 dark:border dark:border-white/25 rounded-full overflow-hidden flex outline-2 outline-offset-2 outline-primary-600 focus-visible:outline"
                        data-palette={palette}
                        aria-label={`Palette ${palette}`}
                        key={index}
                    >
                        <RadioGroup.Indicator className="absolute z-[1] size-2 inset-0 m-auto shadow-md shadow-gray-950/50 bg-white rounded-full" />
                        <div className="col-start-2 blur-[6px] w-1/2 ml-auto h-full">
                            <div className="h-1/2 bg-secondary-500" />
                            <div className="h-1/2 bg-accent-400" />
                        </div>
                    </RadioGroup.Item>
                ))
            }
        </RadioGroup.Root>
    )
}