Skip to content

Commit

Permalink
feat(Stepper): implement stepper (unovue#669)
Browse files Browse the repository at this point in the history
  • Loading branch information
epr3 authored Jul 22, 2024
1 parent 6550f34 commit 6757908
Show file tree
Hide file tree
Showing 25 changed files with 695 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
5 changes: 5 additions & 0 deletions apps/www/.vitepress/theme/config/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,11 @@ export const docsConfig: DocsConfig = {
href: '/docs/components/sonner',
items: [],
},
{
title: 'Stepper',
href: '/docs/components/stepper',
label: 'New',
},
{
title: 'Switch',
href: '/docs/components/switch',
Expand Down
14 changes: 14 additions & 0 deletions apps/www/__registry__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,13 @@ export const Index = {
component: () => import("../src/lib/registry/default/example/SonnerWithDialog.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/SonnerWithDialog.vue"],
},
"StepperDemo": {
name: "StepperDemo",
type: "components:example",
registryDependencies: ["stepper"],
component: () => import("../src/lib/registry/default/example/StepperDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/StepperDemo.vue"],
},
"SwitchDemo": {
name: "SwitchDemo",
type: "components:example",
Expand Down Expand Up @@ -2433,6 +2440,13 @@ export const Index = {
component: () => import("../src/lib/registry/new-york/example/SonnerWithDialog.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/SonnerWithDialog.vue"],
},
"StepperDemo": {
name: "StepperDemo",
type: "components:example",
registryDependencies: ["stepper"],
component: () => import("../src/lib/registry/new-york/example/StepperDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/StepperDemo.vue"],
},
"SwitchDemo": {
name: "SwitchDemo",
type: "components:example",
Expand Down
50 changes: 50 additions & 0 deletions apps/www/src/content/docs/components/stepper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
title: Stepper
description: A set of steps that are used to indicate progress through a multi-step process.
source: apps/www/src/lib/registry/default/ui/stepper
primitive: https://www.radix-vue.com/components/stepper.html
---

<ComponentPreview name="StepperDemo" />

## Installation

```bash
npx shadcn-vue@latest add stepper
```

## Usage

```vue
<script setup lang="ts">
import {
Stepper,
StepperDescription,
StepperIndicator,
StepperItem,
StepperSeparator,
StepperTitle,
StepperTrigger,
} from '@/components/ui/stepper'
</script>
<template>
<Stepper>
<StepperItem :step="1" linear>
<StepperTrigger>
<StepperIndicator>1</StepperIndicator>
<StepperTitle>Step 1</StepperTitle>
<StepperDescription>This is the first step</StepperDescription>
</StepperTrigger>
<StepperSeparator />
</StepperItem>
<StepperItem :step="2">
<StepperTrigger>
<StepperIndicator>2</StepperIndicator>
<StepperTitle>Step 2</StepperTitle>
<StepperDescription>This is the second step</StepperDescription>
</StepperTrigger>
</StepperItem>
</Stepper>
</template>
```
55 changes: 55 additions & 0 deletions apps/www/src/lib/registry/default/example/StepperDemo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<script setup lang="ts">
import { BookUser, Check, CreditCard, Truck } from 'lucide-vue-next'
import { Stepper, StepperDescription, StepperIndicator, StepperItem, StepperSeparator, StepperTitle, StepperTrigger } from '@/lib/registry/default/ui/stepper'
const steps = [{
step: 1,
title: 'Address',
description: 'Add your address here',
icon: BookUser,
}, {
step: 2,
title: 'Shipping',
description: 'Set your preferred shipping method',
icon: Truck,
}, {
step: 3,
title: 'Payment',
description: 'Add any payment information you have',
icon: CreditCard,
}, {
step: 4,
title: 'Checkout',
description: 'Confirm your order',
icon: Check,
}]
</script>

<template>
<Stepper>
<StepperItem
v-for="item in steps"
:key="item.step"
class="basis-1/4"
:step="item.step"
>
<StepperTrigger>
<StepperIndicator>
<component :is="item.icon" class="w-4 h-4" />
</StepperIndicator>
<div class="flex flex-col">
<StepperTitle>
{{ item.title }}
</StepperTitle>
<StepperDescription>
{{ item.description }}
</StepperDescription>
</div>
</StepperTrigger>
<StepperSeparator
v-if="item.step !== steps[steps.length - 1].step"
/>
</StepperItem>
</Stepper>
</template>
30 changes: 30 additions & 0 deletions apps/www/src/lib/registry/default/ui/stepper/Stepper.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<script lang="ts" setup>
import { type HTMLAttributes, computed } from 'vue'
import type { StepperRootEmits, StepperRootProps } from 'radix-vue'
import { StepperRoot, useForwardPropsEmits } from 'radix-vue'
import { cn } from '@/lib/utils'
const props = defineProps<StepperRootProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<StepperRootEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>

<template>
<StepperRoot
:class="cn(
'flex gap-2 p-1',
props.class,
)"
v-bind="forwarded"
>
<slot />
</StepperRoot>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script lang="ts" setup>
import { type HTMLAttributes, computed } from 'vue'
import type { StepperDescriptionProps } from 'radix-vue'
import { StepperDescription, useForwardProps } from 'radix-vue'
import { cn } from '@/lib/utils'
const props = defineProps<StepperDescriptionProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardProps(delegatedProps)
</script>

<template>
<StepperDescription v-bind="forwarded" :class="cn('text-xs text-muted-foreground', props.class)">
<slot />
</StepperDescription>
</template>
35 changes: 35 additions & 0 deletions apps/www/src/lib/registry/default/ui/stepper/StepperIndicator.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script lang="ts" setup>
import { type HTMLAttributes, computed } from 'vue'
import type { StepperIndicatorProps } from 'radix-vue'
import { StepperIndicator, useForwardProps } from 'radix-vue'
import { cn } from '@/lib/utils'
const props = defineProps<StepperIndicatorProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardProps(delegatedProps)
</script>

<template>
<StepperIndicator
v-bind="forwarded"
:class="cn(
'inline-flex items-center justify-center rounded-full text-white w-10 h-10',
// Disabled
'group-data-[disabled]:text-muted-foreground group-data-[disabled]:opacity-50',
// Active
'group-data-[state=active]:bg-primary group-data-[state=active]:text-primary-foreground',
// Completed
'group-data-[state=completed]:bg-accent group-data-[state=completed]:text-accent-foreground',
props.class,
)"
>
<slot />
</StepperIndicator>
</template>
26 changes: 26 additions & 0 deletions apps/www/src/lib/registry/default/ui/stepper/StepperItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script lang="ts" setup>
import { type HTMLAttributes, computed } from 'vue'
import type { StepperItemProps } from 'radix-vue'
import { StepperItem, useForwardProps } from 'radix-vue'
import { cn } from '@/lib/utils'
const props = defineProps<StepperItemProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardProps(delegatedProps)
</script>

<template>
<StepperItem
v-bind="forwarded"
:class="cn('flex items-center gap-2 cursor-pointer group data-[disabled]:pointer-events-none', props.class)"
>
<slot />
</StepperItem>
</template>
31 changes: 31 additions & 0 deletions apps/www/src/lib/registry/default/ui/stepper/StepperSeparator.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<script lang="ts" setup>
import { type HTMLAttributes, computed } from 'vue'
import type { StepperSeparatorProps } from 'radix-vue'
import { StepperSeparator, useForwardProps } from 'radix-vue'
import { cn } from '@/lib/utils'
const props = defineProps<StepperSeparatorProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardProps(delegatedProps)
</script>

<template>
<StepperSeparator
v-bind="forwarded"
:class="cn(
'w-full h-[1px] bg-border',
// Disabled
'group-data-[disabled]:bg-muted group-data-[disabled]:opacity-50',
// Completed
'group-data-[state=completed]:bg-accent-foreground',
props.class,
)"
/>
</template>
23 changes: 23 additions & 0 deletions apps/www/src/lib/registry/default/ui/stepper/StepperTitle.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script lang="ts" setup>
import { type HTMLAttributes, computed } from 'vue'
import type { StepperTitleProps } from 'radix-vue'
import { StepperTitle, useForwardProps } from 'radix-vue'
import { cn } from '@/lib/utils'
const props = defineProps<StepperTitleProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardProps(delegatedProps)
</script>

<template>
<StepperTitle v-bind="forwarded" :class="cn('text-md font-semibold whitespace-nowrap', props.class)">
<slot />
</StepperTitle>
</template>
26 changes: 26 additions & 0 deletions apps/www/src/lib/registry/default/ui/stepper/StepperTrigger.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script lang="ts" setup>
import { type HTMLAttributes, computed } from 'vue'
import type { StepperTriggerProps } from 'radix-vue'
import { StepperTrigger, useForwardProps } from 'radix-vue'
import { cn } from '@/lib/utils'
const props = defineProps<StepperTriggerProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardProps(delegatedProps)
</script>

<template>
<StepperTrigger
v-bind="forwarded"
:class="cn('p-2 flex flex-col items-center text-center gap-2 rounded-md', props.class)"
>
<slot />
</StepperTrigger>
</template>
7 changes: 7 additions & 0 deletions apps/www/src/lib/registry/default/ui/stepper/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export { default as Stepper } from './Stepper.vue'
export { default as StepperItem } from './StepperItem.vue'
export { default as StepperIndicator } from './StepperIndicator.vue'
export { default as StepperTrigger } from './StepperTrigger.vue'
export { default as StepperTitle } from './StepperTitle.vue'
export { default as StepperDescription } from './StepperDescription.vue'
export { default as StepperSeparator } from './StepperSeparator.vue'
Loading

0 comments on commit 6757908

Please sign in to comment.