Skip to content

Commit

Permalink
feat(module): add DEFAULT shade to primary color (#493)
Browse files Browse the repository at this point in the history
  • Loading branch information
benjamincanac committed Aug 3, 2023
1 parent 83c42cd commit ee0d13e
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 42 deletions.
4 changes: 2 additions & 2 deletions docs/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
<UHeader>
<template #left>
<NuxtLink to="/getting-started" class="flex items-end gap-1.5 font-bold text-xl text-gray-900 dark:text-white">
<Logo class="w-8 h-8 text-primary-500 dark:text-primary-400" />
<Logo class="w-8 h-8 text-primary" />

<span class="hidden sm:block">NuxtLabs</span><span class="sm:text-primary-500 dark:sm:text-primary-400">UI</span>
<span class="hidden sm:block">NuxtLabs</span><span class="sm:text-primary">UI</span>
</NuxtLink>
</template>

Expand Down
58 changes: 33 additions & 25 deletions docs/content/1.getting-started/3.theming.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -67,33 +75,9 @@ export default defineNuxtConfig({

This can also happen when you bind a dynamic color to a component: `<UBadge :color="color" />`, `<UAvatar :chip-color="statuses[user.status]" />`, 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({
Expand Down Expand Up @@ -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/).
Expand Down
3 changes: 2 additions & 1 deletion src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ export default defineNuxtModule<ModuleOptions>({
700: 'rgb(var(--color-primary-700) / <alpha-value>)',
800: 'rgb(var(--color-primary-800) / <alpha-value>)',
900: 'rgb(var(--color-primary-900) / <alpha-value>)',
950: 'rgb(var(--color-primary-950) / <alpha-value>)'
950: 'rgb(var(--color-primary-950) / <alpha-value>)',
DEFAULT: 'rgb(var(--color-primary-DEFAULT) / <alpha-value>)'
}

if (globalColors.gray) {
Expand Down
22 changes: 11 additions & 11 deletions src/runtime/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -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',
Expand Down
9 changes: 8 additions & 1 deletion src/runtime/plugins/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/ui.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

1 comment on commit ee0d13e

@vercel
Copy link

@vercel vercel bot commented on ee0d13e Aug 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

ui – ./

ui-nuxtlabs.vercel.app
ui-git-dev-nuxtlabs.vercel.app
ui.nuxtlabs.com

Please sign in to comment.