Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(module)!: use tailwind-merge for app.config & move config to components & type props #692

Merged
merged 23 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ jobs:
- name: Lint
run: pnpm run lint

- name: Build
run: pnpm run build

- name: Typecheck
run: pnpm run typecheck

- name: Build
run: pnpm run build

- name: Release Edge
if: github.event_name == 'push'
run: ./scripts/release-edge.sh
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ jobs:
- name: Lint
run: pnpm run lint

- name: Build
run: pnpm run build

- name: Typecheck
run: pnpm run typecheck

- name: Build
run: pnpm run build

- name: Version Check
id: check
uses: EndBug/version-check@v2
Expand Down
3 changes: 3 additions & 0 deletions .nuxtrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
imports.autoImport=false
typescript.includeWorkspace=true
typescript.strict=false
1 change: 1 addition & 0 deletions docs/.nuxtrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
imports.autoImport=true
12 changes: 8 additions & 4 deletions docs/components/Footer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,14 @@
</template>

<template #right>
<UButton aria-label="Nuxt Website" icon="i-simple-icons-nuxtdotjs" to="https://nuxt.com" target="_blank" v-bind="$elements.button.secondary" />
<UButton aria-label="Nuxt on X" icon="i-simple-icons-x" to="https://x.com/nuxt_js" target="_blank" v-bind="$elements.button.secondary" />
<UButton aria-label="Nuxt UI on Discord" icon="i-simple-icons-discord" to="https://discord.com/channels/473401852243869706/1153996761426300948" target="_blank" v-bind="$elements.button.secondary" />
<UButton aria-label="Nuxt UI on GitHub" icon="i-simple-icons-github" to="https://github.com/nuxt/ui" target="_blank" v-bind="$elements.button.secondary" />
<UButton aria-label="Nuxt Website" icon="i-simple-icons-nuxtdotjs" to="https://nuxt.com" target="_blank" v-bind="($elements.button.secondary as any)" />
<UButton aria-label="Nuxt on X" icon="i-simple-icons-x" to="https://x.com/nuxt_js" target="_blank" v-bind="($elements.button.secondary as any)" />
<UButton aria-label="Nuxt UI on Discord" icon="i-simple-icons-discord" to="https://discord.com/channels/473401852243869706/1153996761426300948" target="_blank" v-bind="($elements.button.secondary as any)" />
<UButton aria-label="Nuxt UI on GitHub" icon="i-simple-icons-github" to="https://github.com/nuxt/ui" target="_blank" v-bind="($elements.button.secondary as any)" />
</template>
</UFooter>
</template>

<script setup lang="ts">
// force typescript
</script>
2 changes: 1 addition & 1 deletion docs/components/Header.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
icon="i-simple-icons-github"
aria-label="GitHub"
class="hidden lg:inline-flex"
v-bind="$elements.button.secondary"
v-bind="($elements.button.secondary as any)"
/>
</template>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,15 @@ const links = [{
to: 'https://github.com/smarroufin',
target: '_blank'
}]

const { ui } = useAppConfig()
</script>

<template>
<UVerticalNavigation :links="links">
<template #avatar="{ link }">
<UAvatar
v-if="link.avatar"
v-bind="{ size: ui.verticalNavigation.avatar.size, ...link.avatar }"
:class="[ui.verticalNavigation.avatar.base]"
v-bind="link.avatar"
size="3xs"
loading="lazy"
/>
<UIcon v-else name="i-heroicons-user-circle-20-solid" class="text-lg" />
Expand Down
48 changes: 40 additions & 8 deletions docs/content/1.getting-started/3.theming.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
---
description: 'Learn how to customize the look and feel of the components.'
navigation:
badge: New
---

## Overview
Expand Down Expand Up @@ -79,7 +81,7 @@ This can also happen when you bind a dynamic color to a component: `<UBadge :col

### `app.config.ts`

Components are styled with Tailwind CSS but classes are all defined in the default [app.config.ts](https://github.com/nuxt/ui/blob/dev/src/runtime/app.config.ts) file. You can override those in your own `app.config.ts`.
Components are styled with Tailwind CSS but classes are all defined in the default [ui.config.ts](https://github.com/nuxt/ui/blob/dev/src/runtime/ui.config.ts) file. You can override those in your own `app.config.ts`.

```ts [app.config.ts]
export default defineAppConfig({
Expand All @@ -91,6 +93,25 @@ export default defineAppConfig({
})
```

Thanks to [tailwind-merge](https://github.com/dcastil/tailwind-merge), the `app.config.ts` is smartly merged with the default config. This means you don't have to rewrite everything.

You can change this behaviour by setting `strategy` to `override` in your `app.config.ts`: :u-badge{label="New" class="!rounded-full" variant="subtle"}

```ts [app.config.ts]
export default defineAppConfig({
ui: {
strategy: 'override',
button: {
color: {
white: {
solid: 'bg-white dark:bg-gray-900'
}
}
}
}
})
```

### `ui` prop

Each component has a `ui` prop that allows you to customize everything specifically.
Expand All @@ -113,25 +134,36 @@ For example, the default preset of the `FormGroup` component looks like this:

```json
{
...
"label": {
"base": "block font-medium text-gray-700 dark:text-gray-200",
...
"base": "block font-medium text-gray-700 dark:text-gray-200"
}
...
}
```

To change the font of the `label`, you only need to write:

```vue
<UFormGroup name="email" label="Email" :ui="{ label: { base: 'font-semibold' } }">
...
</UFormGroup>
<UFormGroup name="email" label="Email" :ui="{ label: { base: 'font-semibold' } }" />
```

This will smartly replace the `font-medium` by `font-semibold` and prevent any class duplication and any class priority issue.

You can change this behaviour by setting `strategy` to `override` inside the `ui` prop: :u-badge{label="New" class="!rounded-full" variant="subtle"}

```vue
<UButton
to="https://github.com/nuxt/ui"
:ui="{
strategy: 'override',
color: {
white: {
solid: 'bg-white dark:bg-gray-900'
}
}
}"
/>
```

### `class` attribute

You can also use the `class` attribute to add classes to the component.
Expand Down
6 changes: 2 additions & 4 deletions docs/content/5.navigation/1.vertical-navigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,17 +125,15 @@ const links = [{
to: 'https://github.com/benjamincanac',
target: '_blank'
}, ...]

const { ui } = useAppConfig()
</script>

<template>
<UVerticalNavigation :links="links">
<template #avatar="{ link }">
<UAvatar
v-if="link.avatar"
v-bind="{ size: ui.verticalNavigation.avatar.size, ...link.avatar }"
:class="[ui.verticalNavigation.avatar.base]"
v-bind="link.avatar"
size="3xs"
/>
<UIcon v-else name="i-heroicons-user-circle-20-solid" class="text-lg" />
</template>
Expand Down
4 changes: 0 additions & 4 deletions docs/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,6 @@ export default defineNuxtConfig({
exposed: false
}
},
typescript: {
strict: false,
includeWorkspace: true
},
hooks: {
// Related to https://github.com/nuxt/nuxt/pull/22558
'components:extend': (components) => {
Expand Down
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"@nuxt/content": "npm:@nuxt/content-edge@2.8.2-28246255.cae34d7",
"@nuxt/devtools": "^0.8.3",
"@nuxt/eslint-config": "^0.2.0",
"@nuxthq/elements": "npm:@nuxthq/elements-edge@0.0.1-28246521.0e46d44",
"@nuxthq/elements": "npm:@nuxthq/elements-edge@0.0.1-28253627.e4bd6ad",
"@nuxthq/studio": "^0.14.1",
"@nuxtjs/fontaine": "^0.4.1",
"@nuxtjs/google-fonts": "^3.0.2",
Expand Down
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
"build:docs": "nuxi generate docs",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"typecheck": "nuxi typecheck",
"prepare": "nuxi prepare docs",
"typecheck": "vue-tsc --noEmit && nuxi typecheck docs",
"prepare": "nuxt-module-build --stub && nuxt-module-build prepare && nuxi prepare docs",
"release": "release-it"
},
"dependencies": {
Expand All @@ -45,9 +45,10 @@
"@vueuse/integrations": "^10.4.1",
"@vueuse/math": "^10.4.1",
"defu": "^6.1.2",
"fuse.js": "^6.6.2",
"ohash": "^1.1.3",
"pathe": "^1.1.1",
"scule": "^1.0.0",
"fuse.js": "^6.6.2",
"tailwind-merge": "^1.14.0",
"tailwindcss": "^3.3.3"
},
Expand All @@ -61,9 +62,9 @@
"release-it": "^16.1.5",
"typescript": "^5.2.2",
"unbuild": "^2.0.0",
"valibot": "^0.15.0",
"vue-tsc": "^1.8.11",
"yup": "^1.2.0",
"zod": "^3.22.2",
"valibot": "^0.15.0"
"zod": "^3.22.2"
}
}
20 changes: 12 additions & 8 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 23 additions & 16 deletions src/module.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { defineNuxtModule, installModule, addComponentsDir, addImportsDir, createResolver, addPlugin, resolvePath } from '@nuxt/kit'
import { defineNuxtModule, installModule, addComponentsDir, addImportsDir, createResolver, addPlugin } from '@nuxt/kit'
import defaultColors from 'tailwindcss/colors.js'
import { defaultExtractor as createDefaultExtractor } from 'tailwindcss/lib/lib/defaultExtractor.js'
import { iconsPlugin, getIconCollections } from '@egoist/tailwindcss-icons'
import { name, version } from '../package.json'
import { generateSafelist, excludeColors, customSafelistExtractor } from './colors'
import appConfig from './runtime/app.config'

type DeepPartial<T> = Partial<{ [P in keyof T]: DeepPartial<T[P]> | { [key: string]: string } }>
import createTemplates from './templates'
import * as config from './runtime/ui.config'
import type { DeepPartial, Strategy } from './runtime/types/utils'

const defaultExtractor = createDefaultExtractor({ tailwindConfig: { separator: ':' } })

Expand All @@ -16,13 +16,21 @@ delete defaultColors.trueGray
delete defaultColors.coolGray
delete defaultColors.blueGray

type UI = {
primary?: string
gray?: string
colors?: string[]
strategy?: Strategy
} & DeepPartial<typeof config>

declare module 'nuxt/schema' {
interface AppConfigInput {
ui?: UI
}
}
declare module '@nuxt/schema' {
interface AppConfigInput {
ui?: {
primary?: string
gray?: string
colors?: string[]
} & DeepPartial<typeof appConfig.ui>
ui?: UI
}
}

Expand Down Expand Up @@ -64,12 +72,9 @@ export default defineNuxtModule<ModuleOptions>({
nuxt.options.build.transpile.push(runtimeDir)
nuxt.options.build.transpile.push('@popperjs/core', '@headlessui/vue')

nuxt.options.css.push(resolve(runtimeDir, 'ui.css'))
nuxt.options.alias['#ui'] = runtimeDir

const appConfigFile = await resolvePath(resolve(runtimeDir, 'app.config'))
nuxt.hook('app:resolve', (app) => {
app.configs.push(appConfigFile)
})
nuxt.options.css.push(resolve(runtimeDir, 'ui.css'))

nuxt.hook('tailwindcss:config', function (tailwindConfig) {
const globalColors: any = {
Expand Down Expand Up @@ -117,10 +122,10 @@ export default defineNuxtModule<ModuleOptions>({
const colors = excludeColors(globalColors)

nuxt.options.appConfig.ui = {
...nuxt.options.appConfig.ui,
primary: 'green',
gray: 'cool',
colors
colors,
strategy: 'merge'
}

tailwindConfig.safelist = tailwindConfig.safelist || []
Expand All @@ -130,6 +135,8 @@ export default defineNuxtModule<ModuleOptions>({
tailwindConfig.plugins.push(iconsPlugin({ collections: getIconCollections(options.icons as any[]) }))
})

createTemplates(nuxt)

// Modules

await installModule('@nuxtjs/color-mode', { classSuffix: '' })
Expand Down
Loading