From 2c5559b73ea22f1021c18c2561de1e6cd6f9741f Mon Sep 17 00:00:00 2001 From: Italo Date: Fri, 27 Oct 2023 11:01:47 -0300 Subject: [PATCH] feat(Progress): new component (#697) Co-authored-by: Benjamin Canac --- .../examples/ProgressExampleAnimation.vue | 34 ++ .../examples/ProgressExampleSlotIndicator.vue | 25 ++ .../examples/ProgressExampleSlotStep.vue | 31 ++ docs/content/2.elements/10.progress.md | 153 +++++++++ src/colors.ts | 6 + src/runtime/components/elements/Progress.vue | 308 ++++++++++++++++++ src/runtime/types/index.d.ts | 1 + src/runtime/types/progress.ts | 4 + src/runtime/ui.config.ts | 72 ++++ 9 files changed, 634 insertions(+) create mode 100644 docs/components/content/examples/ProgressExampleAnimation.vue create mode 100644 docs/components/content/examples/ProgressExampleSlotIndicator.vue create mode 100644 docs/components/content/examples/ProgressExampleSlotStep.vue create mode 100644 docs/content/2.elements/10.progress.md create mode 100644 src/runtime/components/elements/Progress.vue create mode 100644 src/runtime/types/progress.ts diff --git a/docs/components/content/examples/ProgressExampleAnimation.vue b/docs/components/content/examples/ProgressExampleAnimation.vue new file mode 100644 index 0000000000..1c53867dcc --- /dev/null +++ b/docs/components/content/examples/ProgressExampleAnimation.vue @@ -0,0 +1,34 @@ + + + diff --git a/docs/components/content/examples/ProgressExampleSlotIndicator.vue b/docs/components/content/examples/ProgressExampleSlotIndicator.vue new file mode 100644 index 0000000000..8a5f2ca3e7 --- /dev/null +++ b/docs/components/content/examples/ProgressExampleSlotIndicator.vue @@ -0,0 +1,25 @@ + + + diff --git a/docs/components/content/examples/ProgressExampleSlotStep.vue b/docs/components/content/examples/ProgressExampleSlotStep.vue new file mode 100644 index 0000000000..709e484aa0 --- /dev/null +++ b/docs/components/content/examples/ProgressExampleSlotStep.vue @@ -0,0 +1,31 @@ + + + diff --git a/docs/content/2.elements/10.progress.md b/docs/content/2.elements/10.progress.md new file mode 100644 index 0000000000..dbebd8eb64 --- /dev/null +++ b/docs/content/2.elements/10.progress.md @@ -0,0 +1,153 @@ +--- +title: 'Progress' +description: Show a horizontal bar to indicate task progression. +navigation: + badge: New +links: + - label: GitHub + icon: i-simple-icons-github + to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Progress.vue +--- + +## Usage + +Pass an integer as the `value` from `0` to `100` to the Progress bar component. + +::component-card +--- +props: + value: 70 +--- +:: + +::callout{icon="i-heroicons-light-bulb"} +Check out the [Range](/forms/range) component for forms. +:: + +### Max + +You may also set the `max` number to set the maximum progress value, which will be relative to 100% percent. + +::component-card +--- +props: + value: 2 + max: 5 +options: + - name: max + restriction: only + values: + - 3 + - 4 + - 5 + - 6 + - 7 +--- +:: + +### Steps + +You can set an array of named steps in the `max` prop to show the active step, at the same time it sets the maximum value. + +The first step is always shown at `0%`, making the last `100%`. + +::component-card +--- +props: + value: 0 + max: + - Waiting to start + - Cloning... + - Migrating... + - Deployed! +excludedProps: + - max +--- +:: + +### Progress indicator + +You can add a numeric indicator, which will show the percent on top the progress track. + +::component-card +--- +props: + value: 20 + indicator: true +--- +:: + +### Indeterminate + +By not setting a `value`, or setting it as `null`, the progress bar becomes _indeterminate_. The bar will be animated as a carousel, but you can change it using the `animation` prop for an inverse carousel, a swinging bar or an elastic bar. + +::component-card +--- +baseProps: + value: null +props: + animation: 'carousel' +options: + - name: animation + restriction: only + values: + - 'carousel' + - 'carousel-inverse' + - 'swing' + - 'elastic' +--- +:: + +### Size + +Use the `size` prop to change the size of the progress bar. + +::component-card +--- +baseProps: + value: 70 +props: + size: 'sm' + indicator: false +excludedProps: + - value +--- +:: + +### Style + +Use the `color` prop to change the visual style of the Progress bar. The `color` can be any color from the `ui.colors` object. + +::component-card +--- +baseProps: + value: 70 +props: + color: 'primary' + indicator: false +excludedProps: + - modelValue +--- +:: + +## Slots + +### `indicator` + +You can use the `#indicator` slot to show a custom indicator above the progress bar. It receives the current `percent` of progress. + +:component-example{component="progress-example-slot-indicator"} + +### `step-` + +Use the `#step-` to alter the HTML being shown for each step. + +:component-example{component="progress-example-slot-step"} + +## Props + +:component-props + +## Preset + +:component-preset diff --git a/src/colors.ts b/src/colors.ts index 133c0c2804..707f49ad9c 100644 --- a/src/colors.ts +++ b/src/colors.ts @@ -171,6 +171,12 @@ const safelistByComponent = { pattern: new RegExp(`ring-(${colorsAsRegex})-500`), variants: ['focus-visible'] }], + progress: (colorsAsRegex) => [{ + pattern: new RegExp(`text-(${colorsAsRegex})-400`), + variants: ['dark'] + }, { + pattern: new RegExp(`text-(${colorsAsRegex})-500`) + }], notification: (colorsAsRegex) => [{ pattern: new RegExp(`bg-(${colorsAsRegex})-400`), variants: ['dark'] diff --git a/src/runtime/components/elements/Progress.vue b/src/runtime/components/elements/Progress.vue new file mode 100644 index 0000000000..bc3999df84 --- /dev/null +++ b/src/runtime/components/elements/Progress.vue @@ -0,0 +1,308 @@ + + + + + diff --git a/src/runtime/types/index.d.ts b/src/runtime/types/index.d.ts index c4d55fbcc8..7d2678bdd0 100644 --- a/src/runtime/types/index.d.ts +++ b/src/runtime/types/index.d.ts @@ -9,6 +9,7 @@ export * from './form' export * from './link' export * from './notification' export * from './popper' +export * from './progress' export * from './tabs' export * from './vertical-navigation' export * from './utils' diff --git a/src/runtime/types/progress.ts b/src/runtime/types/progress.ts new file mode 100644 index 0000000000..6a56ec52f0 --- /dev/null +++ b/src/runtime/types/progress.ts @@ -0,0 +1,4 @@ +import { progress } from '../ui.config' + +export type ProgressSize = keyof typeof progress.progress.size +export type ProgressAnimation = keyof typeof progress.animation diff --git a/src/runtime/ui.config.ts b/src/runtime/ui.config.ts index fce440458e..b5edf6753d 100644 --- a/src/runtime/ui.config.ts +++ b/src/runtime/ui.config.ts @@ -384,6 +384,78 @@ export const kbd = { } } +export const progress = { + wrapper: 'w-full flex flex-col gap-2', + indicator: { + container: { + base: 'flex flex-row justify-end', + width: 'min-w-fit', + transition: 'transition-all' + }, + align: 'text-end', + width: 'w-fit', + color: 'text-gray-400 dark:text-gray-500', + size: { + '2xs': 'text-xs', + xs: 'text-xs', + sm: 'text-sm', + md: 'text-sm', + lg: 'text-sm', + xl: 'text-base' + } + }, + progress: { + base: 'block appearance-none border-none overflow-hidden', + width: 'w-full [&::-webkit-progress-bar]:w-full', + size: { + xs: 'h-px', + sm: 'h-1', + md: 'h-2', + lg: 'h-3', + xl: 'h-4', + '2xl': 'h-6' + }, + rounded: 'rounded-full [&::-webkit-progress-bar]:rounded-full', + track: '[&::-webkit-progress-bar]:bg-gray-200 [&::-webkit-progress-bar]:dark:bg-gray-700 [@supports(selector(&::-moz-progress-bar))]:bg-gray-200 [@supports(selector(&::-moz-progress-bar))]:dark:bg-gray-700', + bar: '[&::-webkit-progress-value]:rounded-full [&::-webkit-progress-value]:transition-all [&::-webkit-progress-value]:ease-in-out [&::-moz-progress-bar]:rounded-full', + color: 'text-{color}-500 dark:text-{color}-400', + background: '[&::-webkit-progress-value]:bg-current [&::-moz-progress-bar]:bg-current', + indeterminate: { + base: 'indeterminate:relative', + rounded: 'indeterminate:after:rounded-full [&:indeterminate::-webkit-progress-value]:rounded-full [&:indeterminate::-moz-progress-bar]:rounded-full' + } + }, + steps: { + base: 'grid grid-cols-1', + color: 'text-{color}-500 dark:text-{color}-400', + size: { + '2xs': 'text-xs', + xs: 'text-xs', + sm: 'text-sm', + md: 'text-sm', + lg: 'text-sm', + xl: 'text-base' + } + }, + step: { + base: 'transition-all opacity-0 truncate row-start-1 col-start-1', + align: 'text-end', + active: 'opacity-100', + first: 'text-gray-500' + }, + animation: { + carousel: 'bar-animation-carousel', + 'carousel-inverse': 'bar-animation-carousel-inverse', + swing: 'bar-animation-swing', + elastic: 'bar-animation-elastic' + }, + default: { + color: 'primary', + size: 'md', + animation: 'carousel' + } +} + // Forms export const input = {