diff --git a/docs/content/1.getting-started/3.theming.md b/docs/content/1.getting-started/3.theming.md index 9fe689a095..12e9d83316 100644 --- a/docs/content/1.getting-started/3.theming.md +++ b/docs/content/1.getting-started/3.theming.md @@ -1,31 +1,57 @@ --- +title: Theming description: 'Learn how to customize the look and feel of the components.' --- -This module relies on Nuxt [App Config](https://nuxt.com/docs/guide/directory-structure/app-config#app-config-file) file to customize the look and feel of the components at runtime with HMR (hot-module-replacement). +## Overview + +Nuxt UI uses [Tailwind CSS](https://tailwindcss.com) to style its components and drive its color theme. + +You'll use two main files to modify the defaults: + +- [`app.config.ts`](https://nuxt.com/docs/guide/directory-structure/app-config#app-config-file) to specify the main theme colors and override component styles +- [`tailwind.config.ts`](https://nuxt.com/docs/guide/directory-structure/app-config#app-config-file) to configure individual colors and palettes ## Colors ### Configuration -Components are based on a `primary` and a `gray` color. You can change them in your `app.config.ts`. +Nuxt UI's theme is configured using `primary` and `gray` color palettes: + +- `primary` is used for things like primary actions, accents, etc +- `gray` is used for things like secondary actions, text, borders, etc + + +You can choose which colors to use in your [`app.config.ts`](https://nuxt.com/docs/guide/directory-structure/app-config#app-config-file) file, under the `ui` key: ```ts [app.config.ts] export default defineAppConfig({ ui: { - primary: 'green', - gray: 'cool' + primary: 'rose', + gray: 'neutral' } }) ``` +These settings point to [named Tailwind colors](https://tailwindcss.com/docs/customizing-colors); either Nuxt UI's or your project's own. + +Your options are: + +- skip config and accept the defaults (`green` and `gray`) +- choose different Tailwind colors, e.g. `teal` and `slate` +- create and use custom colors (see [Customisation](#customisation) below) + +Note that you can target nested color config, e.g. `brand.primary` and `brand.secondary` + ::callout{icon="i-heroicons-light-bulb"} -Try to change the `primary` and `gray` colors by clicking on the :u-icon{name="i-heroicons-swatch-20-solid" class="w-4 h-4 align-middle text-primary-500 dark:text-primary-400"} button in the header. +You can preview available colors now by clicking the :u-icon{name="i-heroicons-swatch-20-solid" class="w-4 h-4 align-middle text-primary-500 dark:text-primary-400"} button in the header :: -As this module uses Tailwind CSS under the hood, you can use any of the [Tailwind CSS colors](https://tailwindcss.com/docs/customizing-colors#color-palette-reference) or your own custom colors or groups, such as `brand.primary`. By default, the `primary` color is `green` and the `gray` color is `cool`. +### Customisation + +To use custom shades, you'll need a [tailwind.config.ts](https://tailwindcss.com/docs/installation) to [replace](https://tailwindcss.com/docs/customizing-colors#using-custom-colors) or [extend](https://tailwindcss.com/docs/customizing-colors#adding-additional-colors) the defaults. -When [using custom colors](https://tailwindcss.com/docs/customizing-colors#using-custom-colors) or [adding additional colors](https://tailwindcss.com/docs/customizing-colors#adding-additional-colors) through the `extend` key in your `tailwind.config.ts`, you'll need to make sure to define all the shades from `50` to `950` as most of them are used in the components config defined in [`ui.config/`](https://github.com/nuxt/ui/tree/dev/src/runtime/ui.config) directory. You can [generate your colors](https://tailwindcss.com/docs/customizing-colors#generating-colors) using tools such as https://uicolors.app/ for example. +In the following example, we extend the default `green` config with a richer hue: ```ts [tailwind.config.ts] import type { Config } from 'tailwindcss' @@ -54,23 +80,87 @@ export default >{ } ``` -### CSS Variables +::callout{icon="i-heroicons-bell-alert"} +Note that [before Nuxt UI 2.19.0](https://github.com/nuxt/ui/blob/dev/docs/content/1.getting-started/3.theming.md#css-variables) the color key names `primary` and `gray` were reserved, but a recent update allows configuring these keys and the values will passed straight through as the theme's colors. +:: -To provide dynamic colors that can be changed at runtime, this module uses CSS variables. As Tailwind CSS already has a `gray` color, the module automatically renames it to `cool` to avoid conflicts (`coolGray` was renamed to `gray` when Tailwind CSS v3.0 was released). +Colors must supply all values from `50` to `950` because the Nuxt UI components use the full range. -Likewise, you can't define a `primary` color in your `tailwind.config.ts` as it would conflict with the `primary` color defined by the module. +If you need help in creating the colors, consider an online tool such as [UI Colors](https://uicolors.app). -::callout{icon="i-heroicons-light-bulb"} -We'd advise you to use those colors in your components and pages, e.g. `text-primary-500 dark:text-primary-400`, `bg-gray-100 dark:bg-gray-900`, etc. so your app automatically adapts when changing your `app.config.ts`. -:: +### Usage + +You are encouraged to use these new `primary-*` and `gray-*` classes in your pages and components so that when you [choose a new theme](#configuration) color, your whole design updates. + +Note that the `primary` color has a [default](https://tailwindcss.com/docs/customizing-colors#color-object-syntax) shade which lets you specify a color without a modifier: + +```vue +
{ @@ -8,14 +8,22 @@ export default defineNuxtPlugin(() => { const nuxtApp = useNuxtApp() const root = computed(() => { - const primary: Record | undefined = get(colors, appConfig.ui.primary) - const gray: Record | undefined = get(colors, appConfig.ui.gray) + const ui = appConfig.ui + const keyPrimary = '$primary' in colors && ui.primary === 'primary' + ? '$primary' + : ui.primary + const keyGray = '$gray' in colors && ui.gray === 'gray' + ? '$gray' + : ui.gray + + const primary: Record | undefined = get(colors, keyPrimary) + const gray: Record | undefined = get(colors, keyGray) if (!primary) { - console.warn(`[@nuxt/ui] Primary color '${appConfig.ui.primary}' not found in Tailwind config`) + console.warn(`[@nuxt/ui] Primary color '${ui.primary}' not found in Tailwind config`) } if (!gray) { - console.warn(`[@nuxt/ui] Gray color '${appConfig.ui.gray}' not found in Tailwind config`) + console.warn(`[@nuxt/ui] Gray color '${ui.gray}' not found in Tailwind config`) } return `:root { diff --git a/src/runtime/utils/colors.ts b/src/runtime/utils/colors.ts index f8a8c19a78..3b76024258 100644 --- a/src/runtime/utils/colors.ts +++ b/src/runtime/utils/colors.ts @@ -233,8 +233,18 @@ export const setGlobalColors = (theme: TWConfig['theme']) => { ...theme.extend?.colors } - // @ts-ignore - globalColors.primary = theme.extend.colors.primary = { + // reference theme as any + const themeColors: any = theme.extend.colors + + // track user colors + const userColors: ColorConfig = {} + + // primary colors + if (globalColors.primary) { + userColors.$primary = themeColors.$primary = globalColors.primary + } + + globalColors.primary = themeColors.primary = { 50: 'rgb(var(--color-primary-50) / )', 100: 'rgb(var(--color-primary-100) / )', 200: 'rgb(var(--color-primary-200) / )', @@ -250,13 +260,11 @@ export const setGlobalColors = (theme: TWConfig['theme']) => { } if (globalColors.gray) { - // @ts-ignore - globalColors.cool = theme.extend.colors.cool = - defaultColors.gray + userColors.$gray = themeColors.$gray = globalColors.gray + globalColors.cool = themeColors.cool = defaultColors.gray } - // @ts-ignore - globalColors.gray = theme.extend.colors.gray = { + globalColors.gray = themeColors.gray = { 50: 'rgb(var(--color-gray-50) / )', 100: 'rgb(var(--color-gray-100) / )', 200: 'rgb(var(--color-gray-200) / )', @@ -270,7 +278,10 @@ export const setGlobalColors = (theme: TWConfig['theme']) => { 950: 'rgb(var(--color-gray-950) / )' } - return excludeColors(globalColors) + return [ + ...excludeColors(globalColors), + ...Object.keys(userColors) + ] } export const generateSafelist = (colors: string[], globalColors: string[]) => {