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(Stepper): new component #549

Closed
wants to merge 77 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
b81eb9d
docs: update badges
benjamincanac Aug 1, 2023
a4141f9
docs: improve dynamic page
benjamincanac Aug 1, 2023
b696b15
docs(Form): fixed invalid state attributes in examples (#479)
romhml Aug 1, 2023
9e5b8cc
fix(Popover): handle `hover` mode with padding like dropdown
benjamincanac Aug 2, 2023
83c42cd
fix(FormGroup): `size` were invalid since default has been removed
benjamincanac Aug 3, 2023
ee0d13e
feat(module): add `DEFAULT` shade to `primary` color (#493)
benjamincanac Aug 3, 2023
5c0b0cb
docs(ui): also add the `--color-primary-DEFAULT` variable
benjamincanac Aug 3, 2023
409f20a
feat(Tabs): control selected index (#490)
benjamincanac Aug 4, 2023
48c13ab
fix(AvatarGroup): use `ui.wrapper` as `inheritAttrs` is not false
benjamincanac Aug 4, 2023
90586e0
feat(Avatar): add `icon` prop as fallback
benjamincanac Aug 4, 2023
797cee4
docs(Avatar): add `edge` badge on `icon`
benjamincanac Aug 4, 2023
7dcf591
fix(Form): use safeParseAsync for zod (#497)
graup Aug 4, 2023
2d1a6f2
fix(Form): fix wrong type of validate (#496)
graup Aug 4, 2023
5cdfd74
chore(Avatar): add `flex-shrink-0` to wrapper
benjamincanac Aug 4, 2023
824ebb1
chore(Link): use `$route` instead of `useRoute()`
benjamincanac Aug 4, 2023
bf56a03
feat(Avatar): handle `icon` default from `app.config.ts`
benjamincanac Aug 4, 2023
9ce3f49
docs: improve icon sections of Alert, Avatar and Notification
benjamincanac Aug 4, 2023
70c79fa
fix(Alert): fix wrong type of `actions` (#507)
171h Aug 6, 2023
00b6282
fix(Button): add missing prop types (#508)
171h Aug 6, 2023
fbb4482
chore(app.config): revert `-primary` shortcuts after #493
benjamincanac Aug 7, 2023
56c01ae
docs: bump `@nuxt-themes/ui-kit`
benjamincanac Aug 7, 2023
feade3f
docs: bump `@nuxt-themes/ui-kit`
benjamincanac Aug 8, 2023
82579cd
feat(Table): support nested keys in columns (#503)
vladyslav-mikhieiev Aug 9, 2023
d593c4c
docs: disable `@nuxt/devtools`
benjamincanac Aug 9, 2023
91a2dc1
chore(Table): typecheck
benjamincanac Aug 9, 2023
fe95ffe
feat(Modal): add `fullscreen` prop (#523)
eduayme Aug 10, 2023
5026379
fix(Tabs): recompute marker position when `v-model` changes (#524)
clopezpro Aug 11, 2023
b4a1099
docs: `@nuxt-themes/ui-kit` is now `@nuxthq/elements`
benjamincanac Aug 11, 2023
e9b23ad
docs: rebrand to `Nuxt UI`
benjamincanac Aug 11, 2023
20556d3
chore: add eslint rules for spacing (#526)
Haythamasalama Aug 11, 2023
6c42faf
chore(deps): update all non-major dependencies (#340)
renovate[bot] Aug 11, 2023
f87ae62
feat(Form): improve form control and input validation trigger (#487)
romhml Aug 12, 2023
474dafc
feat(module)!: use `tailwind-merge` for class merging (#509)
benjamincanac Aug 12, 2023
42a45fe
fix(FormGroup): add missing `ref` import from vue
benjamincanac Aug 12, 2023
a0e8d4a
chore(Dropdown): set default `open-delay` to 0
benjamincanac Aug 12, 2023
2ac6789
chore(Popover): set default `open-delay` to 0
benjamincanac Aug 12, 2023
abc6fe6
fix(ButtonGroup): switch back to `ui` prop
benjamincanac Aug 12, 2023
7242829
fix(SelectMenu): invalid `gap` values
benjamincanac Aug 12, 2023
d98e4c2
docs: bump `@nuxthq/elements`
benjamincanac Aug 12, 2023
d5c9ef0
fix(Table): empty state is displayed if null (#517)
eduayme Aug 14, 2023
99cff69
chore(Table): handle `loading-state` prop merge like `empty-state`
benjamincanac Aug 14, 2023
37cafa9
docs: add version select (#532)
benjamincanac Aug 14, 2023
b8b7d74
chore(deps): update all non-major dependencies (#530)
renovate[bot] Aug 14, 2023
72b33a4
docs: dead links in `Form` and `FormGroup` pages (#544)
Aug 16, 2023
80366ee
feat: create Stepper component
eduayme Aug 18, 2023
50212b6
docs: add colon before numeric props (#564)
rogepi Aug 23, 2023
eb9d423
chore(deps): update devdependency unbuild to v2 (#565)
renovate[bot] Aug 28, 2023
a9edcf2
docs(SelectMenu): add slots examples
benjamincanac Aug 28, 2023
8d0ce47
docs: specify multi-word component titles
benjamincanac Aug 28, 2023
4d77f66
docs(ComponentCard): prevent `label` prop as select (#568)
eduayme Aug 28, 2023
9c24e7b
fix(Tooltip): hide on touch devices (#580)
vanling Aug 28, 2023
f4e072d
fix: use head instance from plugin
atinux Aug 29, 2023
7412e62
docs: add missing component slots
benjamincanac Aug 29, 2023
c45d42a
docs: update readme
atinux Aug 30, 2023
1da5ccd
docs: fix social card link
atinux Aug 30, 2023
ffd6d68
docs(deps): bump `@nuxthq/elements`
benjamincanac Aug 30, 2023
8ce75a9
docs: improve performances (#570)
atinux Aug 30, 2023
bece7a1
chore(deps): bump
benjamincanac Aug 30, 2023
c952a26
chore(deps): pin `@nuxtjs/mdc`
benjamincanac Aug 30, 2023
ead87a9
docs: remove concurrency to 1
atinux Aug 30, 2023
3ec0157
feat: add new badge on navigation
eduayme Aug 30, 2023
44d98dd
Merge branch 'dev' into feat/180
eduayme Aug 30, 2023
803c13f
Merge branch 'dev' into feat/180
eduayme Sep 11, 2023
89a9617
Merge branch 'dev' into feat/180
eduayme Sep 13, 2023
3842e9f
Merge branch 'dev' into feat/180
benjamincanac Sep 14, 2023
b0d5ac5
fix: changed loadesh, missing imports and stepper app config refactor
eduayme Sep 19, 2023
622c229
feat: add `to` prop in StepperItem
eduayme Sep 19, 2023
50a79df
Merge branch 'dev' into feat/180
eduayme Sep 19, 2023
0c1d35f
Merge branch 'dev' into feat/180
eduayme Sep 22, 2023
19ef399
Merge branch 'dev' into feat/180
eduayme Sep 28, 2023
444c565
docs: remove `New` badges
benjamincanac Oct 2, 2023
a5264b2
Merge branch 'dev' into feat/180
eduayme Oct 2, 2023
1403b81
fix: remove loadesh-es
eduayme Oct 2, 2023
7d5c012
Merge branch 'dev' into feat/180
eduayme Oct 27, 2023
f5742cd
Merge branch 'dev' into feat/180
eduayme Nov 2, 2023
a0f9447
Merge branch 'dev' into feat/180
eduayme Nov 10, 2023
77d6514
Merge branch 'dev' of https://github.com/nuxt/ui into pr/eduayme/549
ineshbose Nov 30, 2023
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
14 changes: 14 additions & 0 deletions docs/components/content/examples/StepperExampleBasic.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script setup>
const items = [{
label: 'Step1'
}, {
label: 'Step2',
disabled: true
}, {
label: 'Step3'
}]
</script>

<template>
<UStepper :items="items" />
</template>
19 changes: 19 additions & 0 deletions docs/components/content/examples/StepperExampleChange.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script setup>
const items = [{
label: 'Step1'
}, {
label: 'Step2'
}, {
label: 'Step3'
}]

function onChange (index) {
const item = items[index]

alert(`${item.label} was clicked!`)
}
</script>

<template>
<UStepper :items="items" @change="onChange" />
</template>
18 changes: 18 additions & 0 deletions docs/components/content/examples/StepperExampleCustomIcons.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script setup>
const items = [{
label: 'Step1'
}, {
label: 'Step2'
}, {
label: 'Step3'
}]
</script>

<template>
<UStepper
:items="items"
completed-icon="i-heroicons-check-circle"
active-icon="i-heroicons-stop-circle-solid"
pending-icon="i-heroicons-information-circle"
/>
</template>
13 changes: 13 additions & 0 deletions docs/components/content/examples/StepperExampleHideDivider.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<script setup>
const items = [{
label: 'Step1'
}, {
label: 'Step2'
}, {
label: 'Step3'
}]
</script>

<template>
<UStepper :items="items" :display-divider="false" />
</template>
13 changes: 13 additions & 0 deletions docs/components/content/examples/StepperExampleIndex.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<script setup>
const items = [{
label: 'Step1'
}, {
label: 'Step2'
}, {
label: 'Step3'
}]
</script>

<template>
<UStepper :items="items" :default-index="2" />
</template>
140 changes: 140 additions & 0 deletions docs/content/5.navigation/5.stepper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
---
description: Layout indicator for the steps in a workflow.
links:
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxtlabs/ui/blob/dev/src/runtime/components/navigation/Stepper.vue
navigation:
badge: New
---

## Usage

Pass an array to the `items` prop of the Stepper component. Each item can have the following properties:

- `label` - The label of the item.
- `disabled` - Determines whether the item is disabled or not.
- `to`- Redirects to the specific url.

::component-example
#default
:stepper-example-basic{class="w-full"}

#code
```vue
<script setup>
const items = [{
label: 'Step1'
}, {
label: 'Step2',
disabled: true
}, {
label: 'Step3',
to: '#step-3'
}]
</script>

<template>
<UStepper :items="items" />
</template>
```
::

### Default index

You can set the default index of the stepper by setting the `default-index` prop.

::component-example
#default
:stepper-example-index{class="w-full"}

#code
```vue
<script setup>
const items = [...]
</script>

<template>
<UStepper :items="items" :default-index="2" />
</template>
```
::

### Custom icons

You can set the custom icons of the stepper by setting the `completed-icon`, `active-icon` and `pending-icon` props.

::component-example
#default
:stepper-example-custom-icons{class="w-full"}

#code
```vue
<script setup>
const items = [...]
</script>

<template>
<UStepper
:items="items"
completed-icon="i-heroicons-check-circle"
active-icon="i-heroicons-stop-circle-solid"
pending-icon="i-heroicons-information-circle"
/>
</template>
```
::

### Hide divider

You can hide the divider of the stepper by setting the `display-divider` prop to `false`.

::component-example
#default
:stepper-example-hide-divider{class="w-full"}

#code
```vue
<script setup>
const items = [...]
</script>

<template>
<UStepper :items="items" :display-divider="false" />
</template>
```
::

### Listen to changes

You can listen to changes by using the `@change` event. The event will emit the index of the selected item.

::component-example
#default
:stepper-example-change{class="w-full"}

#code
```vue
<script setup>
const items = [...]

function onChange (index) {
const item = items[index]

alert(`${item.label} was clicked!`)
}
</script>

<template>
<UStepper :items="items" @change="onChange" />
</template>
```
::

## Props

:component-props

## Preset

:component-preset
153 changes: 153 additions & 0 deletions src/runtime/components/navigation/Stepper.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
<template>
<ol
:class="wrapperClass"
v-bind="attrs"
>
<li
v-for="(item, index) of items"
:key="index"
ref="itemRefs"
:class="[ui.base]"
>
<div
v-if="displayDivider"
:class="[index > 0 ? 'visible' : 'invisible', ui.step.divider]"
/>
<UButton
color="white"
Copy link
Member

@benjamincanac benjamincanac Sep 14, 2023

Choose a reason for hiding this comment

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

To customize how the button look, we might need to do something similar to the Accordion component: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Accordion.vue#L6, https://github.com/nuxt/ui/blob/dev/src/runtime/app.config.ts#L307.

Or we could only use a ULink and define all the styles in the app.config.ts as you did, because here, most of the classes from font, padding, size, etc. will be defined twice as the Button already have them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So use a ULink instead of UButton?

variant="ghost"
:disabled="item.disabled"
:class="[
ui.step.base,
ui.step.background,
ui.step.padding,
ui.step.size,
ui.step.font,
selectedIndex === index ? ui.step.active : ui.step.inactive,
]"
@click="onChange(index)"
:to="item.to"

Check warning on line 29 in src/runtime/components/navigation/Stepper.vue

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest, 18)

Attribute ":to" should go before "@click"
>
<div :class="[ui.step.leading.wrapper]">
<UIcon
v-if="(selectedIndex > index && completedIcon)"
:name="completedIcon"
:class="[ui.step.leading.icon]"
/>
<UIcon
v-else-if="(selectedIndex === index && activeIcon)"
:name="activeIcon"
:class="[ui.step.leading.icon]"
/>
<UIcon
v-else-if="(selectedIndex < index && pendingIcon)"
:name="pendingIcon"
:class="[ui.step.leading.icon]"
/>
<UAvatar
v-else
:alt="(index + 1).toString()"
:size="ui.step.leading.size"
/>
</div>
{{ item?.label }}
</UButton>
<div
v-if="displayDivider"
:class="[index + 1 < items.length ? 'visible' : 'invisible', ui.step.divider]"
/>
</li>
</ol>
</template>

<script lang="ts">
import { computed, defineComponent } from 'vue'
import type { PropType } from 'vue'
import UIcon from '../elements/Icon.vue'
import UAvatar from '../elements/Avatar.vue'
import UButton from '../elements/Button.vue'
import { omit } from './runtime/utils/lodash'

Check failure on line 69 in src/runtime/components/navigation/Stepper.vue

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest, 18)

Cannot find module './runtime/utils/lodash' or its corresponding type declarations.
import { twMerge } from 'tailwind-merge'
import { defuTwMerge } from '../../utils'

Check warning on line 71 in src/runtime/components/navigation/Stepper.vue

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest, 18)

'defuTwMerge' is defined but never used

Check failure on line 71 in src/runtime/components/navigation/Stepper.vue

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest, 18)

Module '"../../utils"' declares 'defuTwMerge' locally, but it is not exported.
import type { StepperItem } from '../../types/stepper'
// TODO: Remove
// @ts-expect-error
import appConfig from '#build/app.config'

// const appConfig = useAppConfig()

export default defineComponent({
components: {
UIcon,
UAvatar,
UButton
},
inheritAttrs: false,
props: {
modelValue: {
type: Number,
default: undefined
},
defaultIndex: {
type: Number,
default: 0
},
items: {
type: Array as PropType<StepperItem[]>,
default: () => []
},
ui: {
type: Object as PropType<Partial<typeof appConfig.ui.stepper>>,
default: () => ({})
},
completedIcon: {
type: String,
default: null
},
activeIcon: {
type: String,
default: null
},
pendingIcon: {
type: String,
default: null
},
displayDivider: {
type: Boolean,
default: true
}
},
emits: ['update:modelValue', 'change'],
setup (props, { attrs, emit }) {
// TODO: Remove
const appConfig = useAppConfig()

const ui = computed<Partial<typeof appConfig.ui.stepper>>(() => twMerge(props.ui, appConfig.ui.stepper))

Check failure on line 125 in src/runtime/components/navigation/Stepper.vue

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest, 18)

No overload matches this call.

const selectedIndex = ref(props.modelValue || props.defaultIndex)

Check failure on line 127 in src/runtime/components/navigation/Stepper.vue

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest, 18)

Cannot find name 'ref'.

const wrapperClass = computed(() => twMerge(ui.value.wrapper, attrs.class as string))

// Methods

function onChange (index: number) {
selectedIndex.value = index

emit('change', index)

if (props.modelValue !== undefined) {
emit('update:modelValue', index)
}
}

return {
eduayme marked this conversation as resolved.
Show resolved Hide resolved
attrs: computed(() => omit(attrs, ['class'])),
// eslint-disable-next-line vue/no-dupe-keys
ui,
selectedIndex,
onChange,
wrapperClass
}
}
})
</script>
1 change: 1 addition & 0 deletions src/runtime/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export * from './link'
export * from './meter'
export * from './notification'
export * from './popper'
export * from './stepper'
export * from './progress'
export * from './range'
export * from './select'
Expand Down
6 changes: 6 additions & 0 deletions src/runtime/types/stepper.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface StepperItem {
label?: string
disabled?: boolean
content?: string
to?: string
}
Loading
Loading