-
Notifications
You must be signed in to change notification settings - Fork 573
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
Closed
Changes from all commits
Commits
Show all changes
77 commits
Select commit
Hold shift + click to select a range
b81eb9d
docs: update badges
benjamincanac a4141f9
docs: improve dynamic page
benjamincanac b696b15
docs(Form): fixed invalid state attributes in examples (#479)
romhml 9e5b8cc
fix(Popover): handle `hover` mode with padding like dropdown
benjamincanac 83c42cd
fix(FormGroup): `size` were invalid since default has been removed
benjamincanac ee0d13e
feat(module): add `DEFAULT` shade to `primary` color (#493)
benjamincanac 5c0b0cb
docs(ui): also add the `--color-primary-DEFAULT` variable
benjamincanac 409f20a
feat(Tabs): control selected index (#490)
benjamincanac 48c13ab
fix(AvatarGroup): use `ui.wrapper` as `inheritAttrs` is not false
benjamincanac 90586e0
feat(Avatar): add `icon` prop as fallback
benjamincanac 797cee4
docs(Avatar): add `edge` badge on `icon`
benjamincanac 7dcf591
fix(Form): use safeParseAsync for zod (#497)
graup 2d1a6f2
fix(Form): fix wrong type of validate (#496)
graup 5cdfd74
chore(Avatar): add `flex-shrink-0` to wrapper
benjamincanac 824ebb1
chore(Link): use `$route` instead of `useRoute()`
benjamincanac bf56a03
feat(Avatar): handle `icon` default from `app.config.ts`
benjamincanac 9ce3f49
docs: improve icon sections of Alert, Avatar and Notification
benjamincanac 70c79fa
fix(Alert): fix wrong type of `actions` (#507)
171h 00b6282
fix(Button): add missing prop types (#508)
171h fbb4482
chore(app.config): revert `-primary` shortcuts after #493
benjamincanac 56c01ae
docs: bump `@nuxt-themes/ui-kit`
benjamincanac feade3f
docs: bump `@nuxt-themes/ui-kit`
benjamincanac 82579cd
feat(Table): support nested keys in columns (#503)
vladyslav-mikhieiev d593c4c
docs: disable `@nuxt/devtools`
benjamincanac 91a2dc1
chore(Table): typecheck
benjamincanac fe95ffe
feat(Modal): add `fullscreen` prop (#523)
eduayme 5026379
fix(Tabs): recompute marker position when `v-model` changes (#524)
clopezpro b4a1099
docs: `@nuxt-themes/ui-kit` is now `@nuxthq/elements`
benjamincanac e9b23ad
docs: rebrand to `Nuxt UI`
benjamincanac 20556d3
chore: add eslint rules for spacing (#526)
Haythamasalama 6c42faf
chore(deps): update all non-major dependencies (#340)
renovate[bot] f87ae62
feat(Form): improve form control and input validation trigger (#487)
romhml 474dafc
feat(module)!: use `tailwind-merge` for class merging (#509)
benjamincanac 42a45fe
fix(FormGroup): add missing `ref` import from vue
benjamincanac a0e8d4a
chore(Dropdown): set default `open-delay` to 0
benjamincanac 2ac6789
chore(Popover): set default `open-delay` to 0
benjamincanac abc6fe6
fix(ButtonGroup): switch back to `ui` prop
benjamincanac 7242829
fix(SelectMenu): invalid `gap` values
benjamincanac d98e4c2
docs: bump `@nuxthq/elements`
benjamincanac d5c9ef0
fix(Table): empty state is displayed if null (#517)
eduayme 99cff69
chore(Table): handle `loading-state` prop merge like `empty-state`
benjamincanac 37cafa9
docs: add version select (#532)
benjamincanac b8b7d74
chore(deps): update all non-major dependencies (#530)
renovate[bot] 72b33a4
docs: dead links in `Form` and `FormGroup` pages (#544)
80366ee
feat: create Stepper component
eduayme 50212b6
docs: add colon before numeric props (#564)
rogepi eb9d423
chore(deps): update devdependency unbuild to v2 (#565)
renovate[bot] a9edcf2
docs(SelectMenu): add slots examples
benjamincanac 8d0ce47
docs: specify multi-word component titles
benjamincanac 4d77f66
docs(ComponentCard): prevent `label` prop as select (#568)
eduayme 9c24e7b
fix(Tooltip): hide on touch devices (#580)
vanling f4e072d
fix: use head instance from plugin
atinux 7412e62
docs: add missing component slots
benjamincanac c45d42a
docs: update readme
atinux 1da5ccd
docs: fix social card link
atinux ffd6d68
docs(deps): bump `@nuxthq/elements`
benjamincanac 8ce75a9
docs: improve performances (#570)
atinux bece7a1
chore(deps): bump
benjamincanac c952a26
chore(deps): pin `@nuxtjs/mdc`
benjamincanac ead87a9
docs: remove concurrency to 1
atinux 3ec0157
feat: add new badge on navigation
eduayme 44d98dd
Merge branch 'dev' into feat/180
eduayme 803c13f
Merge branch 'dev' into feat/180
eduayme 89a9617
Merge branch 'dev' into feat/180
eduayme 3842e9f
Merge branch 'dev' into feat/180
benjamincanac b0d5ac5
fix: changed loadesh, missing imports and stepper app config refactor
eduayme 622c229
feat: add `to` prop in StepperItem
eduayme 50a79df
Merge branch 'dev' into feat/180
eduayme 0c1d35f
Merge branch 'dev' into feat/180
eduayme 19ef399
Merge branch 'dev' into feat/180
eduayme 444c565
docs: remove `New` badges
benjamincanac a5264b2
Merge branch 'dev' into feat/180
eduayme 1403b81
fix: remove loadesh-es
eduayme 7d5c012
Merge branch 'dev' into feat/180
eduayme f5742cd
Merge branch 'dev' into feat/180
eduayme a0f9447
Merge branch 'dev' into feat/180
eduayme 77d6514
Merge branch 'dev' of https://github.com/nuxt/ui into pr/eduayme/549
ineshbose File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
18
docs/components/content/examples/StepperExampleCustomIcons.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
13
docs/components/content/examples/StepperExampleHideDivider.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
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 GitHub Actions / ci (ubuntu-latest, 18)
|
||
> | ||
<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' | ||
import { twMerge } from 'tailwind-merge' | ||
import { defuTwMerge } from '../../utils' | ||
Check warning on line 71 in src/runtime/components/navigation/Stepper.vue GitHub Actions / ci (ubuntu-latest, 18)
|
||
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)) | ||
|
||
const selectedIndex = ref(props.modelValue || props.defaultIndex) | ||
|
||
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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 theapp.config.ts
as you did, because here, most of the classes fromfont
,padding
,size
, etc. will be defined twice as theButton
already have them.There was a problem hiding this comment.
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?