From c6056ed13323f854a9ab4a07303b9e64cd0f563a Mon Sep 17 00:00:00 2001 From: Benjamin Canac Date: Thu, 3 Aug 2023 16:27:23 +0200 Subject: [PATCH] feat(module): add `DEFAULT` shade to `primary` color (#493) --- docs/app.vue | 4 +- docs/content/1.getting-started/3.theming.md | 58 ++++++++++++--------- src/module.ts | 3 +- src/runtime/app.config.ts | 22 ++++---- src/runtime/plugins/colors.ts | 9 +++- src/runtime/ui.css | 4 +- 6 files changed, 58 insertions(+), 42 deletions(-) diff --git a/docs/app.vue b/docs/app.vue index 870c43bfaf..7b5b5d9268 100644 --- a/docs/app.vue +++ b/docs/app.vue @@ -4,9 +4,9 @@ diff --git a/docs/content/1.getting-started/3.theming.md b/docs/content/1.getting-started/3.theming.md index a0dacc1297..de71c35e01 100644 --- a/docs/content/1.getting-started/3.theming.md +++ b/docs/content/1.getting-started/3.theming.md @@ -8,6 +8,8 @@ This module relies on Nuxt [App Config](https://nuxt.com/docs/guide/directory-st ## Colors +### Configuration + Components are based on a `primary` and a `gray` color. You can change them in your `app.config.ts`. ```ts [app.config.ts] @@ -25,6 +27,8 @@ Try to change the `primary` and `gray` colors by clicking on the :u-icon{name="i 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`. +### CSS Variables + 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). 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. @@ -33,6 +37,10 @@ Likewise, you can't define a `primary` color in your `tailwind.config.ts` as it 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`. :: +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. :u-badge{label="Edge" class="!rounded-full" variant="subtle"} + +### Smart Safelisting + Components having a `color` prop like [Avatar](/elements/avatar#chip), [Badge](/elements/badge#style), [Button](/elements/button#style), [Input](/forms/input#style) (inherited in [Select](/forms/select) and [SelectMenu](/forms/select-menu)), [Radio](/forms/radio), [Checkbox](/forms/checkbox), [Toggle](/forms/toggle), [Range](/forms/range) and [Notification](/overlays/notification#timeout) will use the `primary` color by default but will handle all the colors defined in your `tailwind.config.ts` or the default Tailwind CSS colors. Variant classes of those components are defined with a syntax like `bg-{color}-500 dark:bg-{color}-400` so they can be used with any color. However, this means that Tailwind will not find those classes and therefore will not generate the corresponding CSS. @@ -67,33 +75,9 @@ export default defineNuxtConfig({ This can also happen when you bind a dynamic color to a component: ``, ``, etc. In this case, you'll need to safelist the possible color values manually as well. -## Dark mode - -All the components are styled with dark mode in mind. - -Thanks to [Tailwind CSS dark mode](https://tailwindcss.com/docs/dark-mode#toggling-dark-mode-manually) class strategy and the [@nuxtjs/color-mode](https://github.com/nuxt-modules/color-mode) module, you literally have nothing to do. - -::callout{icon="i-heroicons-puzzle-piece"} -Learn how to build a color mode button in the [Examples](/getting-started/examples#color-mode-button) page. -:: - -You can disable dark mode by setting the `preference` to `light` instead of `system` in your `nuxt.config.ts`. - -```ts [nuxt.config.ts] -export default defineNuxtConfig({ - colorMode: { - preference: 'light' - } -}) -``` - -::callout{icon="i-heroicons-light-bulb"} -If you're stuck in dark mode even after changing this setting, you might need to remove the `nuxt-color-mode` entry from your browser's local storage. -:: - ## Components -Components are styled with Tailwind CSS but classes are all defined in the default [app.config.ts](https://github.com/nuxtlabs/ui/blob/dev/src/runtime/app.config.ts) file. You can override them in your `app.config.ts`. +Components are styled with Tailwind CSS but classes are all defined in the default [app.config.ts](https://github.com/nuxtlabs/ui/blob/dev/src/runtime/app.config.ts) file. You can override those in your own `app.config.ts`. ```ts [app.config.ts] export default defineAppConfig({ @@ -135,6 +119,30 @@ export default defineAppConfig({ }) ``` +## Dark mode + +All the components are styled with dark mode in mind. + +Thanks to [Tailwind CSS dark mode](https://tailwindcss.com/docs/dark-mode#toggling-dark-mode-manually) class strategy and the [@nuxtjs/color-mode](https://github.com/nuxt-modules/color-mode) module, you literally have nothing to do. + +::callout{icon="i-heroicons-puzzle-piece"} +Learn how to build a color mode button in the [Examples](/getting-started/examples#color-mode-button) page. +:: + +You can disable dark mode by setting the `preference` to `light` instead of `system` in your `nuxt.config.ts`. + +```ts [nuxt.config.ts] +export default defineNuxtConfig({ + colorMode: { + preference: 'light' + } +}) +``` + +::callout{icon="i-heroicons-light-bulb"} +If you're stuck in dark mode even after changing this setting, you might need to remove the `nuxt-color-mode` entry from your browser's local storage. +:: + ## Icons You can use any icon (100,000+) from [Iconify](https://iconify.design/). diff --git a/src/module.ts b/src/module.ts index f64612aff9..39e7ccf537 100644 --- a/src/module.ts +++ b/src/module.ts @@ -90,7 +90,8 @@ export default defineNuxtModule({ 700: 'rgb(var(--color-primary-700) / )', 800: 'rgb(var(--color-primary-800) / )', 900: 'rgb(var(--color-primary-900) / )', - 950: 'rgb(var(--color-primary-950) / )' + 950: 'rgb(var(--color-primary-950) / )', + DEFAULT: 'rgb(var(--color-primary-DEFAULT) / )' } if (globalColors.gray) { diff --git a/src/runtime/app.config.ts b/src/runtime/app.config.ts index 43662ecd78..8b434f92f6 100644 --- a/src/runtime/app.config.ts +++ b/src/runtime/app.config.ts @@ -181,17 +181,17 @@ const button = { }, color: { white: { - solid: 'shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-700 text-gray-900 dark:text-white bg-white hover:bg-gray-50 disabled:bg-white dark:bg-gray-900 dark:hover:bg-gray-800/50 dark:disabled:bg-gray-900 focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400', - ghost: 'text-gray-900 dark:text-white hover:bg-white dark:hover:bg-gray-900 focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400' + solid: 'shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-700 text-gray-900 dark:text-white bg-white hover:bg-gray-50 disabled:bg-white dark:bg-gray-900 dark:hover:bg-gray-800/50 dark:disabled:bg-gray-900 focus-visible:ring-2 focus-visible:ring-primary', + ghost: 'text-gray-900 dark:text-white hover:bg-white dark:hover:bg-gray-900 focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary' }, gray: { - solid: 'shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-700 text-gray-700 dark:text-gray-200 bg-gray-50 hover:bg-gray-100 disabled:bg-gray-50 dark:bg-gray-800 dark:hover:bg-gray-700/50 dark:disabled:bg-gray-800 focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400', - ghost: 'text-gray-700 dark:text-gray-200 hover:text-gray-900 dark:hover:text-white hover:bg-gray-50 dark:hover:bg-gray-800 focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400', - link: 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 underline-offset-4 hover:underline focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400' + solid: 'shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-700 text-gray-700 dark:text-gray-200 bg-gray-50 hover:bg-gray-100 disabled:bg-gray-50 dark:bg-gray-800 dark:hover:bg-gray-700/50 dark:disabled:bg-gray-800 focus-visible:ring-2 focus-visible:ring-primary', + ghost: 'text-gray-700 dark:text-gray-200 hover:text-gray-900 dark:hover:text-white hover:bg-gray-50 dark:hover:bg-gray-800 focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary', + link: 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 underline-offset-4 hover:underline focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary' }, black: { - solid: 'shadow-sm text-white dark:text-gray-900 bg-gray-900 hover:bg-gray-800 disabled:bg-gray-900 dark:bg-white dark:hover:bg-gray-100 dark:disabled:bg-white focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400', - link: 'text-gray-900 dark:text-white underline-offset-4 hover:underline focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400' + solid: 'shadow-sm text-white dark:text-gray-900 bg-gray-900 hover:bg-gray-800 disabled:bg-gray-900 dark:bg-white dark:hover:bg-gray-100 dark:disabled:bg-white focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary', + link: 'text-gray-900 dark:text-white underline-offset-4 hover:underline focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary' } }, variant: { @@ -401,10 +401,10 @@ const input = { }, color: { white: { - outline: 'shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400' + outline: 'shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary' }, gray: { - outline: 'shadow-sm bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400' + outline: 'shadow-sm bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary' } }, variant: { @@ -701,8 +701,8 @@ const skeleton = { const verticalNavigation = { wrapper: 'relative', - base: 'group relative flex items-center gap-2 focus:outline-none focus-visible:outline-none dark:focus-visible:outline-none focus-visible:before:ring-inset focus-visible:before:ring-1 focus-visible:before:ring-primary-500 dark:focus-visible:before:ring-primary-400 before:absolute before:inset-px before:rounded-md disabled:cursor-not-allowed disabled:opacity-75', - ring: 'focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400', + base: 'group relative flex items-center gap-2 focus:outline-none focus-visible:outline-none dark:focus-visible:outline-none focus-visible:before:ring-inset focus-visible:before:ring-1 focus-visible:before:ring-primary before:absolute before:inset-px before:rounded-md disabled:cursor-not-allowed disabled:opacity-75', + ring: 'focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary', padding: 'px-3 py-1.5', width: 'w-full', rounded: 'rounded-md', diff --git a/src/runtime/plugins/colors.ts b/src/runtime/plugins/colors.ts index 140885ba5d..a2a52977d6 100644 --- a/src/runtime/plugins/colors.ts +++ b/src/runtime/plugins/colors.ts @@ -20,8 +20,15 @@ export default defineNuxtPlugin(() => { return `:root { ${Object.entries(primary || colors.green).map(([key, value]) => `--color-primary-${key}: ${hexToRgb(value)};`).join('\n')} +--color-primary-DEFAULT: var(--color-primary-500); + ${Object.entries(gray || colors.cool).map(([key, value]) => `--color-gray-${key}: ${hexToRgb(value)};`).join('\n')} -}` +} + +.dark { + --color-primary-DEFAULT: var(--color-primary-400); +} +` }) // Head diff --git a/src/runtime/ui.css b/src/runtime/ui.css index fdca2d6f6b..6f605d8525 100644 --- a/src/runtime/ui.css +++ b/src/runtime/ui.css @@ -3,10 +3,10 @@ } a:focus-visible { - @apply outline-primary-500 dark:outline-primary-400; + @apply outline-primary; } -::selection { @apply bg-primary-500/40 dark:bg-primary-400/40; } +::selection { @apply bg-primary/40; } select { background-image: none;