From 183e55d371da5164e2cf92fcd0412f1043d7eaa4 Mon Sep 17 00:00:00 2001 From: Dave Stewart Date: Fri, 2 Aug 2024 12:09:59 +0100 Subject: [PATCH 01/20] feat: detect and reuse configured primary and gray colors --- src/runtime/plugins/colors.ts | 18 +++++++++++++----- src/runtime/utils/colors.ts | 27 +++++++++++++++++++-------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/runtime/plugins/colors.ts b/src/runtime/plugins/colors.ts index a9b886c787..2d72686a65 100644 --- a/src/runtime/plugins/colors.ts +++ b/src/runtime/plugins/colors.ts @@ -1,5 +1,5 @@ import { computed } from 'vue' -import { hexToRgb } from '../utils' +import { get, hexToRgb } from '../utils' import { defineNuxtPlugin, useAppConfig, useNuxtApp, useHead } from '#imports' import colors from '#tailwind-config/theme/colors' @@ -8,14 +8,22 @@ export default defineNuxtPlugin(() => { const nuxtApp = useNuxtApp() const root = computed(() => { - const primary: Record | undefined = colors[appConfig.ui.primary] - const gray: Record | undefined = 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 b6519d053f..61a6b3d0ff 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[]) => { From 4408c5635f498440ee8653e7cf65c60e3f23b16c Mon Sep 17 00:00:00 2001 From: Dave Stewart Date: Fri, 2 Aug 2024 12:25:30 +0100 Subject: [PATCH 02/20] fix: linting --- src/runtime/plugins/colors.ts | 2 +- src/runtime/utils/colors.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/plugins/colors.ts b/src/runtime/plugins/colors.ts index 2d72686a65..69b1ecd7d7 100644 --- a/src/runtime/plugins/colors.ts +++ b/src/runtime/plugins/colors.ts @@ -1,6 +1,6 @@ import { computed } from 'vue' import { get, hexToRgb } from '../utils' -import { defineNuxtPlugin, useAppConfig, useNuxtApp, useHead } from '#imports' +import { defineNuxtPlugin, useAppConfig, useHead, useNuxtApp } from '#imports' import colors from '#tailwind-config/theme/colors' export default defineNuxtPlugin(() => { diff --git a/src/runtime/utils/colors.ts b/src/runtime/utils/colors.ts index 61a6b3d0ff..f1df995543 100644 --- a/src/runtime/utils/colors.ts +++ b/src/runtime/utils/colors.ts @@ -280,7 +280,7 @@ export const setGlobalColors = (theme: TWConfig['theme']) => { return [ ...excludeColors(globalColors), - ...Object.keys(userColors), + ...Object.keys(userColors) ] } From e541d0294be15743e06ad66cea43075eb3e0e114 Mon Sep 17 00:00:00 2001 From: Dave Stewart Date: Fri, 2 Aug 2024 13:49:26 +0100 Subject: [PATCH 03/20] docs(Theming): clarify how new nuxt ui tailwind rules work --- docs/content/1.getting-started/3.theming.md | 63 ++++++++++++++++----- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/docs/content/1.getting-started/3.theming.md b/docs/content/1.getting-started/3.theming.md index 3d3c7c6548..7bb2ea0083 100644 --- a/docs/content/1.getting-started/3.theming.md +++ b/docs/content/1.getting-started/3.theming.md @@ -6,9 +6,20 @@ This module relies on Nuxt [App Config](https://nuxt.com/docs/guide/directory-st ## Colors +### Overview + +Components are based on a `primary` and a `gray` color: + +- `primary` is used for things like primary button colors, accents, etc +- `gray` is used for things like secondary actions, text, borders, etc + +::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. +:: + ### Configuration -Components are based on a `primary` and a `gray` color. You can change them in your `app.config.ts`. +These values can be configured in `app.config.ts`. ```ts [app.config.ts] export default defineAppConfig({ @@ -19,13 +30,9 @@ export default defineAppConfig({ }) ``` -::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. -:: - -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. By default, the `primary` color is `green` and the `gray` color is `cool`. +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. By default, the `primary` color is `green` and the `gray` color is `gray`. -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. +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`: ```ts [tailwind.config.ts] import type { Config } from 'tailwindcss' @@ -54,17 +61,45 @@ export default >{ } ``` -### CSS Variables +This is because many of the Nuxt UI components use the full range (you can peek at the values in the [`ui.config/`](https://github.com/nuxt/ui/tree/dev/src/runtime/ui.config) folder). -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). +If you need to [generate your own colors](https://tailwindcss.com/docs/customizing-colors#generating-colors) you can use tools such as https://uicolors.app/. -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. +### How it works -::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`. -:: +To support a range of tints for `primary` and `grey`, Nuxt UI augments your Tailwind config with new config that leverages CSS variables and alpha transparency: + +```js +{ + primary: { + 50: 'rgb(var(--color-primary-50) / )', + 100: 'rgb(var(--color-primary-100) / )', + 200: 'rgb(var(--color-primary-200) / )', + ... + }, + gray: { + 50: 'rgb(var(--color-gray-50) / )', + 100: 'rgb(var(--color-gray-100) / )', + 200: 'rgb(var(--color-gray-200) / )', + ... + }} +``` + +These new values are used by Tailwind during the build process so that something like `bg-primary-500/30` compiles to: -The `primary` color also has a `DEFAULT` shade that changes based on the theme. It is `500` in light mode and `400` in dark mode. You can use as a shortcut in your components and pages, e.g. `text-primary`, `bg-primary`, `focus-visible:ring-primary`, etc. +```css +.bg-primary-500\/30 { + color: rgb(var(--color-primary-500) / 0.3); +} +``` + +The `primary` color also has a `DEFAULT` shade that changes based on the theme. It is `500` in light mode and `400` in dark mode and you use it without any tint modifier, such as `text-primary`, `focus-inside:ring-primary`, etc. + +You are encouraged to use these color names in your own components and pages so your app automatically updates when changing your `app.config.ts`. + +::callout{icon="i-heroicons-light-bell-alert"} +If your theme already defines `primary` and `gray` colors, they will be converted to this new alpha-enabled version. Before Nuxt UI 2.19.0 the keys `primary` and `gray` were overwritten by Nuxt UI, but you are now free to uses these values in your Tailwind config +:: ### Smart Safelisting From 9303f2822c39cb89647efad180eefa36b0b11149 Mon Sep 17 00:00:00 2001 From: Dave Stewart Date: Fri, 2 Aug 2024 14:18:47 +0100 Subject: [PATCH 04/20] docs: minor tweaks --- docs/content/1.getting-started/3.theming.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/content/1.getting-started/3.theming.md b/docs/content/1.getting-started/3.theming.md index 7bb2ea0083..8792998f2d 100644 --- a/docs/content/1.getting-started/3.theming.md +++ b/docs/content/1.getting-started/3.theming.md @@ -10,7 +10,7 @@ This module relies on Nuxt [App Config](https://nuxt.com/docs/guide/directory-st Components are based on a `primary` and a `gray` color: -- `primary` is used for things like primary button colors, accents, etc +- `primary` is used for things like primary actions, accents, etc - `gray` is used for things like secondary actions, text, borders, etc ::callout{icon="i-heroicons-light-bulb"} @@ -30,9 +30,11 @@ export default defineAppConfig({ }) ``` -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. By default, the `primary` color is `green` and the `gray` color is `gray`. +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. -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`: +By default, the `primary` color is `green` and the `gray` color is `gray`. + +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) you'll need to make sure to define all shades from `50` to `950`: ```ts [tailwind.config.ts] import type { Config } from 'tailwindcss' @@ -67,7 +69,7 @@ If you need to [generate your own colors](https://tailwindcss.com/docs/customizi ### How it works -To support a range of tints for `primary` and `grey`, Nuxt UI augments your Tailwind config with new config that leverages CSS variables and alpha transparency: +To support a range of tints for `primary` and `grey`, Nuxt UI augments your Tailwind config with new config that [leverages CSS variables and alpha transparency](https://tailwindcss.com/docs/customizing-colors#using-css-variables): ```js { @@ -85,7 +87,7 @@ To support a range of tints for `primary` and `grey`, Nuxt UI augments your Tail }} ``` -These new values are used by Tailwind during the build process so that something like `bg-primary-500/30` compiles to: +These new values are used by Tailwind during the build process so a class like `bg-primary-500/30` compiles to: ```css .bg-primary-500\/30 { @@ -93,9 +95,9 @@ These new values are used by Tailwind during the build process so that something } ``` -The `primary` color also has a `DEFAULT` shade that changes based on the theme. It is `500` in light mode and `400` in dark mode and you use it without any tint modifier, such as `text-primary`, `focus-inside:ring-primary`, etc. +The `primary` color also has a `DEFAULT` shade that changes based on the theme (`500` in light mode and `400` in dark mode) which you use without any numeric value, i.e. `text-primary`, `focus-inside:ring-primary`, etc. -You are encouraged to use these color names in your own components and pages so your app automatically updates when changing your `app.config.ts`. +You are encouraged to use Nuxt UI's color names in your own components and pages so your app automatically updates when changing your `app.config.ts`. ::callout{icon="i-heroicons-light-bell-alert"} If your theme already defines `primary` and `gray` colors, they will be converted to this new alpha-enabled version. Before Nuxt UI 2.19.0 the keys `primary` and `gray` were overwritten by Nuxt UI, but you are now free to uses these values in your Tailwind config From fa74526419e8285f0c8a8fb886830576b92fc58f Mon Sep 17 00:00:00 2001 From: Dave Stewart Date: Fri, 2 Aug 2024 14:22:45 +0100 Subject: [PATCH 05/20] code: more tweaks --- docs/content/1.getting-started/3.theming.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/1.getting-started/3.theming.md b/docs/content/1.getting-started/3.theming.md index 8792998f2d..02e0f06a51 100644 --- a/docs/content/1.getting-started/3.theming.md +++ b/docs/content/1.getting-started/3.theming.md @@ -100,7 +100,7 @@ The `primary` color also has a `DEFAULT` shade that changes based on the theme ( You are encouraged to use Nuxt UI's color names in your own components and pages so your app automatically updates when changing your `app.config.ts`. ::callout{icon="i-heroicons-light-bell-alert"} -If your theme already defines `primary` and `gray` colors, they will be converted to this new alpha-enabled version. Before Nuxt UI 2.19.0 the keys `primary` and `gray` were overwritten by Nuxt UI, but you are now free to uses these values in your Tailwind config +If your theme already defines `primary` and `gray` colors, they will be converted to this new alpha-enabled version. Before Nuxt UI 2.19.0 the keys `primary` and `gray` were overwritten by Nuxt UI, but you can now configure your Tailwind with these keys and they will be used verbatim. :: ### Smart Safelisting From 761390e1d1dc79e0f7d5408106a816d35421edbd Mon Sep 17 00:00:00 2001 From: Dave Stewart Date: Fri, 2 Aug 2024 20:09:52 +0100 Subject: [PATCH 06/20] docs: rewrite theming and colors (again!) --- docs/content/1.getting-started/3.theming.md | 76 ++++++++++++++------- 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/docs/content/1.getting-started/3.theming.md b/docs/content/1.getting-started/3.theming.md index 02e0f06a51..41442109fe 100644 --- a/docs/content/1.getting-started/3.theming.md +++ b/docs/content/1.getting-started/3.theming.md @@ -1,40 +1,51 @@ --- +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 -### Overview +### Configuration -Components are based on a `primary` and a `gray` color: +Default component colors are based on `primary` and `gray` colors: - `primary` is used for things like primary actions, accents, etc - `gray` is used for things like secondary actions, text, borders, etc -::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. -:: - -### Configuration - -These values can be configured in `app.config.ts`. +You can set these theme colors in your [`app.config.ts`](https://nuxt.com/docs/guide/directory-structure/app-config#app-config-file) file, using the `ui` key: ```ts [app.config.ts] export default defineAppConfig({ ui: { primary: 'green', - gray: 'cool' + gray: 'gray' } }) ``` -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. +By default Nuxt UI is themed with Tailwind's default `green` and `gray` shades. + +You can stick to these, choose from any [named Tailwind color](https://tailwindcss.com/docs/customizing-colors), or [create your own](https://uicolors.app). + +::callout{icon="i-heroicons-light-bulb"} +Click 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 to try out other colors! + +:: + +### Customisation -By default, the `primary` color is `green` and the `gray` color is `gray`. +To use custom colors, 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 built-in colors. -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) you'll need to make sure to define all shades from `50` to `950`: +In the following example, we extend the default `green` colors with a richer hue: ```ts [tailwind.config.ts] import type { Config } from 'tailwindcss' @@ -63,13 +74,34 @@ export default >{ } ``` -This is because many of the Nuxt UI components use the full range (you can peek at the values in the [`ui.config/`](https://github.com/nuxt/ui/tree/dev/src/runtime/ui.config) folder). +Colors must supply all values from `50` to `950` because the Nuxt UI components use the full range. + +You can peek at the built-in classes in the `ui.config` folder: + +- on GitHub: [`runtime/ui.config/**/*.ts`](https://github.com/search?q=repo%3Anuxt%2Fui+path%3A%2F%5Esrc%5C%2Fruntime%5C%2Fui%5C.config%5C%2F%2F+-primary&type=code) +- in your project: `node_modules/@nuxt/ui/dist/runtime/ui.config/**/*.mjs` + + + +### Usage -If you need to [generate your own colors](https://tailwindcss.com/docs/customizing-colors#generating-colors) you can use tools such as https://uicolors.app/. +You can use these new `primary-*` and `gray-*` classes in your pages and components like regular Tailwind, with the added benefit that if you [choose a new theme](#configuration) color, your whole site will update. + +Note that the `primary` color also has a [`DEFAULT`](https://tailwindcss.com/docs/customizing-colors#color-object-syntax) shade that changes based on the theme (`500` in light mode and `400` in dark mode) which allows you to specify a color without a numeric modifier: + +```vue +