mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-14 12:14:41 +01:00
docs(getting-started): update
This commit is contained in:
230
docs/content/1.getting-started/3.theme.md
Normal file
230
docs/content/1.getting-started/3.theme.md
Normal file
@@ -0,0 +1,230 @@
|
||||
---
|
||||
description: 'Learn how to customize the appearance of Nuxt UI components using Tailwind CSS.'
|
||||
navigation:
|
||||
badge:
|
||||
label: Todo
|
||||
---
|
||||
|
||||
## Tailwind CSS
|
||||
|
||||
Since Nuxt UI v3 uses Tailwind CSS v4 alpha which doesn't have a documentation yet, let's have a look on how to use it.
|
||||
|
||||
Tailwind CSS v4 takes a CSS-first configuration approach, you now customize your theme with CSS variables inside a `@theme` directive:
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
|
||||
@theme {
|
||||
--font-family-display: "Inter", "sans-serif";
|
||||
|
||||
--breakpoint-3xl: 1920px;
|
||||
|
||||
--color-green-50: #EFFDF5;
|
||||
--color-green-100: #D9FBE8;
|
||||
--color-green-200: #B3F5D1;
|
||||
--color-green-300: #75EDAE;
|
||||
--color-green-400: #00DC82;
|
||||
--color-green-500: #00C16A;
|
||||
--color-green-600: #00A155;
|
||||
--color-green-700: #007F45;
|
||||
--color-green-800: #016538;
|
||||
--color-green-900: #0A5331;
|
||||
--color-green-950: #052e16;
|
||||
}
|
||||
```
|
||||
|
||||
The `@theme` directive tells Tailwind to make new utilities and variants available based on those variables. It's the equivalent of the `theme.extend` key in Tailwind CSS v3 `tailwind.config.ts` file.
|
||||
|
||||
This is exactly what the [`@nuxt/ui`](https://github.com/nuxt/ui/blob/v3/src/runtime/index.css) import is all about, it declares the `primary`, `error` and `gray` colors to be configurable through the [App Config](https://nuxt.com/docs/guide/directory-structure/app-config#app-config-file) but we'll talk more about that in the [Colors](/getting-started/colors) section.
|
||||
|
||||
::note
|
||||
You can learn more about this on https://tailwindcss.com/blog/tailwindcss-v4-alpha#css-first-configuration.
|
||||
::
|
||||
|
||||
## Tailwind Variants API
|
||||
|
||||
Nuxt UI components are styled using the [Tailwind Variants](https://www.tailwind-variants.org/) API, which provides a powerful way to create variants and manage component styles. Let's explore the key features of this API:
|
||||
|
||||
### Slots
|
||||
|
||||
Components in Nuxt UI can have multiple `slots`, each representing a distinct HTML element or section within the component. These slots allow for flexible content insertion and styling. Let's take the [Card](/components/card) component as an example:
|
||||
|
||||
::code-group
|
||||
|
||||
```ts [src/theme/card.ts]
|
||||
export default {
|
||||
slots: {
|
||||
root: 'bg-white dark:bg-gray-900 ring ring-gray-200 dark:ring-gray-800 divide-y divide-gray-200 dark:divide-gray-800 rounded-lg shadow',
|
||||
header: 'p-4 sm:px-6',
|
||||
body: 'p-4 sm:p-6',
|
||||
footer: 'p-4 sm:px-6'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```vue [src/runtime/components/Card.vue]
|
||||
<template>
|
||||
<div :class="ui.root({ class: [props.class, props.ui?.root] })">
|
||||
<div :class="ui.header({ class: props.ui?.header })">
|
||||
<slot name="header" />
|
||||
</div>
|
||||
|
||||
<div :class="ui.body({ class: props.ui?.body })">
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<div :class="ui.footer({ class: props.ui?.footer })">
|
||||
<slot name="footer" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
::
|
||||
|
||||
Some components don't have slots, they are just composed of a single root element. In this case, the theme only defines the `base` slot like the [Container](/components/container) component for example:
|
||||
|
||||
::code-group
|
||||
|
||||
```ts [src/theme/container.ts]
|
||||
export default {
|
||||
base: 'max-w-7xl mx-auto px-4 sm:px-6 lg:px-8'
|
||||
}
|
||||
```
|
||||
|
||||
```vue [src/runtime/components/Container.vue]
|
||||
<template>
|
||||
<div :class="container({ class: props.class })">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
::
|
||||
|
||||
::caution
|
||||
Components without slots don't have a [`ui` prop](#ui-prop), only the [`class` prop](#class-prop) is available to override styles.
|
||||
::
|
||||
|
||||
### Variants
|
||||
|
||||
Nuxt UI components use `variants` to change the `slots` styles based on props. Here's an example of the [Avatar](/components/avatar) component:
|
||||
|
||||
```ts [src/theme/avatar.ts]
|
||||
export default {
|
||||
slots: {
|
||||
root: 'inline-flex items-center justify-center shrink-0 select-none overflow-hidden rounded-full align-middle bg-gray-100 dark:bg-gray-800',
|
||||
image: 'h-full w-full rounded-[inherit] object-cover'
|
||||
},
|
||||
variants: {
|
||||
size: {
|
||||
'sm': {
|
||||
root: 'size-7 text-sm'
|
||||
},
|
||||
'md': {
|
||||
root: 'size-8 text-base'
|
||||
},
|
||||
'lg': {
|
||||
root: 'size-9 text-lg'
|
||||
}
|
||||
}
|
||||
},
|
||||
defaultVariants: {
|
||||
size: 'md'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This way, the `size` prop will apply the corresponding styles to the `root` slot:
|
||||
|
||||
::component-code{slug="avatar"}
|
||||
---
|
||||
ignore:
|
||||
- src
|
||||
props:
|
||||
src: 'https://github.com/benjamincanac.png'
|
||||
size: lg
|
||||
---
|
||||
::
|
||||
|
||||
The `defaultVariants` property specifies the default values for each variant. It determines how a component looks and behaves when no prop is provided. These default values can be customized in your [`app.config.ts`](#appconfigts) to adjust the standard appearance of components throughout your application.
|
||||
|
||||
::tip
|
||||
Since Tailwind Variants provides typing out of the box, you get autocomplete for your props in the editor.
|
||||
::
|
||||
|
||||
## Customize components
|
||||
|
||||
You have multiple ways to customize the appearance of Nuxt UI components, you can do it for all components at once or on a per-component basis.
|
||||
|
||||
Tailwind Variants uses [tailwind-merge](https://github.com/dcastil/tailwind-merge) under the hood to merge classes so you don't have to worry about conflicting classes.
|
||||
|
||||
::note
|
||||
You can explore the theme for each component in two ways:
|
||||
|
||||
- Check the `Theme` section in the documentation of each individual component.
|
||||
- Browse the source code directly in the GitHub repository at https://github.com/nuxt/ui/tree/v3/src/theme.
|
||||
::
|
||||
|
||||
### `app.config.ts`
|
||||
|
||||
You can override the theme of components inside your `app.config.ts` by using the exact same structure as the theme object.
|
||||
|
||||
Let's say you want to change the font weight of all your buttons, you can do it like this:
|
||||
|
||||
```ts [app.config.ts]
|
||||
export default defineAppConfig({
|
||||
ui: {
|
||||
button: {
|
||||
slots: {
|
||||
base: 'font-bold'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
In this example, the `font-bold` class will override the default `font-medium` class on all buttons.
|
||||
|
||||
### `ui` prop
|
||||
|
||||
You can also override a component's **slots** using the `ui` prop. This has priority over the `app.config.ts` configuration and `variants` resolution.
|
||||
|
||||
::component-code{slug="button"}
|
||||
---
|
||||
prettier: true
|
||||
ignore:
|
||||
- ui.leadingIcon
|
||||
- color
|
||||
- variant
|
||||
- size
|
||||
- icon
|
||||
props:
|
||||
icon: i-heroicons-magnifying-glass
|
||||
size: md
|
||||
color: gray
|
||||
variant: outline
|
||||
ui:
|
||||
leadingIcon: 'text-primary-500 dark:text-primary-400 size-3'
|
||||
slots:
|
||||
default: |
|
||||
|
||||
Button
|
||||
---
|
||||
::
|
||||
|
||||
In this example, the `leadingIcon` slot is overwritten even though the `md` size variant would apply a `size-5` class by default.
|
||||
|
||||
### `class` prop
|
||||
|
||||
The `class` prop allows you to override the classes of the `root` slot or the `base` slot when the component has no slots.
|
||||
|
||||
::component-code{slug="button"}
|
||||
---
|
||||
props:
|
||||
class: 'font-bold rounded-full'
|
||||
slots:
|
||||
default: Button
|
||||
---
|
||||
::
|
||||
@@ -5,64 +5,19 @@ navigation:
|
||||
label: Todo
|
||||
---
|
||||
|
||||
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).
|
||||
## Theme
|
||||
|
||||
### Configuration
|
||||
In the [Theme](/getting-started/theme) section, we've seen how to customize our Tailwind CSS theme and that each component has a theme defined with `slots` and `variants`.
|
||||
|
||||
Components are based on a `primary` and a `gray` color. You can change them in your `app.config.ts`.
|
||||
Some components also have a `color` prop, which allows you to customize the color of the component.
|
||||
|
||||
```ts [app.config.ts]
|
||||
export default defineAppConfig({
|
||||
ui: {
|
||||
primary: 'green',
|
||||
gray: 'cool'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
::tip
|
||||
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.
|
||||
::component-code{slug="button"}
|
||||
---
|
||||
props:
|
||||
color: 'green'
|
||||
slots:
|
||||
default: Button
|
||||
---
|
||||
::
|
||||
|
||||
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`.
|
||||
|
||||
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.
|
||||
|
||||
```ts [tailwind.config.ts]
|
||||
import type { Config } from 'tailwindcss'
|
||||
import defaultTheme from 'tailwindcss/defaultTheme'
|
||||
|
||||
export default <Partial<Config>>{
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
green: {
|
||||
50: '#EFFDF5',
|
||||
100: '#D9FBE8',
|
||||
200: '#B3F5D1',
|
||||
300: '#75EDAE',
|
||||
400: '#00DC82',
|
||||
500: '#00C16A',
|
||||
600: '#00A155',
|
||||
700: '#007F45',
|
||||
800: '#016538',
|
||||
900: '#0A5331',
|
||||
950: '#052e16'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 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.
|
||||
|
||||
::tip
|
||||
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.
|
||||
## Color Aliases
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
---
|
||||
description: ''
|
||||
links:
|
||||
- label: 'nuxt/icon'
|
||||
to: https://github.com/nuxt/icon
|
||||
target: _blank
|
||||
icon: i-simple-icons-github
|
||||
navigation:
|
||||
badge:
|
||||
label: Todo
|
||||
@@ -1,207 +0,0 @@
|
||||
---
|
||||
description: 'Learn how to customize the look and feel of the components.'
|
||||
navigation:
|
||||
badge:
|
||||
label: Todo
|
||||
---
|
||||
|
||||
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).
|
||||
|
||||
## 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]
|
||||
export default defineAppConfig({
|
||||
ui: {
|
||||
primary: 'green',
|
||||
gray: 'cool'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
::tip
|
||||
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`.
|
||||
|
||||
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.
|
||||
|
||||
```ts [tailwind.config.ts]
|
||||
import type { Config } from 'tailwindcss'
|
||||
import defaultTheme from 'tailwindcss/defaultTheme'
|
||||
|
||||
export default <Partial<Config>>{
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
green: {
|
||||
50: '#EFFDF5',
|
||||
100: '#D9FBE8',
|
||||
200: '#B3F5D1',
|
||||
300: '#75EDAE',
|
||||
400: '#00DC82',
|
||||
500: '#00C16A',
|
||||
600: '#00A155',
|
||||
700: '#007F45',
|
||||
800: '#016538',
|
||||
900: '#0A5331',
|
||||
950: '#052e16'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 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.
|
||||
|
||||
::tip
|
||||
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.
|
||||
|
||||
## Components
|
||||
|
||||
### `app.config.ts`
|
||||
|
||||
You can find the config of each component in the [`ui.config/`](https://github.com/nuxt/ui/tree/dev/src/runtime/ui.config) directory. You can override those classes in your own `app.config.ts`.
|
||||
|
||||
```ts [app.config.ts]
|
||||
export default defineAppConfig({
|
||||
ui: {
|
||||
container: {
|
||||
constrained: 'max-w-5xl'
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
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 behavior by setting `strategy` to `override` in your `app.config.ts`:
|
||||
|
||||
```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.
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<UContainer :ui="{ constrained: 'max-w-2xl' }">
|
||||
<slot />
|
||||
</UContainer>
|
||||
</template>
|
||||
```
|
||||
|
||||
::tip
|
||||
You can find the default classes for each component under the `Config` section.
|
||||
::
|
||||
|
||||
Thanks to [tailwind-merge](https://github.com/dcastil/tailwind-merge), the `ui` prop is smartly merged with the config. This means you don't have to rewrite everything.
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To change the font of the `label`, you only need to write:
|
||||
|
||||
```vue
|
||||
<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 behavior by setting `strategy` to `override` inside the `ui` prop:
|
||||
|
||||
```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.
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<UButton label="Button" class="rounded-full" />
|
||||
</template>
|
||||
```
|
||||
|
||||
Again, with [tailwind-merge](https://github.com/dcastil/tailwind-merge), this will smartly merge the classes with the `ui` prop and the config.
|
||||
|
||||
### Default values
|
||||
|
||||
Some component props like `size`, `color`, `variant`, etc. have a default value that you can override in your `app.config.ts`.
|
||||
|
||||
```ts [app.config.ts]
|
||||
export default defineAppConfig({
|
||||
ui: {
|
||||
button: {
|
||||
default: {
|
||||
size: 'md',
|
||||
color: 'gray',
|
||||
variant: 'ghost'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||
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'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
::tip
|
||||
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.
|
||||
::
|
||||
13
docs/content/1.getting-started/6.fonts.md
Normal file
13
docs/content/1.getting-started/6.fonts.md
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
description: ''
|
||||
links:
|
||||
- label: 'nuxt/fonts'
|
||||
to: https://github.com/nuxt/fonts
|
||||
target: _blank
|
||||
icon: i-simple-icons-github
|
||||
navigation:
|
||||
badge:
|
||||
label: Todo
|
||||
---
|
||||
|
||||
Thanks to [`@nuxt/fonts`](https://github.com/nuxt/fonts),
|
||||
31
docs/content/1.getting-started/7.color-mode.md
Normal file
31
docs/content/1.getting-started/7.color-mode.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
description: ''
|
||||
links:
|
||||
- label: 'nuxtjs/color-mode'
|
||||
to: https://github.com/nuxt-modules/color-mode
|
||||
target: _blank
|
||||
icon: i-simple-icons-github
|
||||
navigation:
|
||||
badge:
|
||||
label: Todo
|
||||
---
|
||||
|
||||
Thanks to [`@nuxtjs/color-mode`](https://github.com/nuxt-modules/color-mode), you can easily switch between light and dark themes.
|
||||
|
||||
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.
|
||||
|
||||
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'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
::tip
|
||||
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.
|
||||
::
|
||||
5
docs/content/1.getting-started/8.typescript.md
Normal file
5
docs/content/1.getting-started/8.typescript.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: TypeScript
|
||||
description: ''
|
||||
navigation: false
|
||||
---
|
||||
Reference in New Issue
Block a user