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(VStepper): add new item-props prop #20651

Draft
wants to merge 2 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 11 additions & 2 deletions packages/vuetify/src/components/VStepper/VStepper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const makeStepperProps = propsFactory({
type: Array as PropType<readonly StepperItem[]>,
default: () => ([]),
},
itemProps: Boolean,
itemTitle: {
type: String,
default: 'title',
Expand Down Expand Up @@ -98,10 +99,18 @@ export const VStepper = genericComponent<VStepperSlots>()({
const items = computed(() => props.items.map((item, index) => {
const title = getPropertyFromItem(item, props.itemTitle, item)
const value = getPropertyFromItem(item, props.itemValue, index + 1)
const itemProps = props.itemProps ? item : getPropertyFromItem(item, props.itemProps)

return {
const _props = {
title,
value,
...itemProps,
}

return {
title: _props.title,
value: _props.value,
props: _props,
raw: item,
}
}))
Expand Down Expand Up @@ -164,7 +173,7 @@ export const VStepper = genericComponent<VStepperSlots>()({
{ !!index && (<VDivider />) }

<VStepperItem
{ ...item }
{ ...item.props }
v-slots={{
default: slots[`header-item.${item.value}`] ?? slots.header,
icon: slots.icon,
Expand Down
12 changes: 10 additions & 2 deletions packages/vuetify/src/labs/VStepperVertical/VStepperVertical.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,18 @@ export const VStepperVertical = genericComponent<VStepperVerticalSlots>()({
const items = computed(() => props.items.map((item, index) => {
const title = getPropertyFromItem(item, props.itemTitle, item)
const value = getPropertyFromItem(item, props.itemValue, index + 1)
const itemProps = props.itemProps ? item : getPropertyFromItem(item, props.itemProps)

return {
const _props = {
title,
value,
...itemProps,
}

return {
title: _props.title,
value: _props.value,
props: _props,
raw: item,
}
}))
Expand Down Expand Up @@ -115,7 +123,7 @@ export const VStepperVertical = genericComponent<VStepperVerticalSlots>()({
return (
<>
{ items.value.map(({ raw, ...item }) => (
<VStepperVerticalItem { ...item }>
<VStepperVerticalItem { ...item.props }>
{{
...slots,
default: slots[`item.${item.value}`],
Expand Down
140 changes: 75 additions & 65 deletions packages/vuetify/src/labs/VStepperVertical/VStepperVerticalItem.sass
Original file line number Diff line number Diff line change
Expand Up @@ -2,73 +2,83 @@
@use '../../styles/tools'
@use './variables' as *

.v-stepper-vertical-item
position: relative
transition-duration: $stepper-vertical-item-transition-duration
transition-property: $stepper-vertical-item-transition-property
transition-timing-function: $stepper-vertical-item-transition-timing-function

&__title
font-size: 1rem

&__subtitle
font-size: .75rem

.v-expansion-panel-text
padding-inline-start: 32px

&:not(:last-child):before
content: ''
position: absolute
width: 2px
height: calc(100% - 30px)
background: rgba(var(--v-border-color), var(--v-border-opacity))
left: 35px
top: 44px
z-index: 1
transition-duration: 300ms
transition-property: height

&:after
display: none

&.v-expansion-panel--disabled,
&:not(.v-stepper-vertical-item--editable)
.v-expansion-panel-title
pointer-events: none

.v-expansion-panel-title__overlay
opacity: 0

.v-stepper-vertical-item__avatar.v-avatar
background: rgba(var(--v-theme-surface-variant), var(--v-medium-emphasis-opacity))
color: rgb(var(--v-theme-on-surface-variant))
transition-property: background
@include tools.layer('components')
.v-stepper-vertical-item
position: relative
transition-duration: $stepper-vertical-item-transition-duration
transition-property: $stepper-vertical-item-transition-property
transition-timing-function: $stepper-vertical-item-transition-timing-function

.v-icon
font-size: .875rem
.v-stepper--non-linear &
opacity: var(--v-high-emphasis-opacity)

.v-expansion-panel--active &
background: rgb(var(--v-theme-surface-variant))
&--error
color: rgb(var(--v-theme-error))

.v-stepper-vertical-item--error &
background: rgb(var(--v-theme-error))
color: rgb(var(--v-theme-on-error))
&__title
font-size: 1rem

.v-stepper-vertical-item__title
.v-stepper-vertical-item--error &
color: rgb(var(--v-theme-error))
&__subtitle
font-size: .75rem

.v-stepper-vertical-item__subtitle
.v-stepper-vertical-item--error &
color: rgb(var(--v-theme-error))

.v-stepper-vertical-actions
&.v-stepper-actions
.v-btn
margin-inline-end: 8px

.v-stepper &
justify-content: flex-end
padding: 24px 0 0
flex-direction: row-reverse
.v-expansion-panel-title
opacity: var(--v-medium-emphasis-opacity)

.v-expansion-panel-text
padding-inline-start: 32px

&:not(:last-child):before
content: ''
position: absolute
width: 2px
height: calc(100% - 30px)
background: rgba(var(--v-border-color), var(--v-border-opacity))
left: 35px
top: 44px
z-index: 1
transition-duration: 300ms
transition-property: height

&:after
display: none

&.v-expansion-panel--disabled,
&:not(.v-stepper-vertical-item--editable)
.v-expansion-panel-title
pointer-events: none

.v-expansion-panel-title__overlay
opacity: 0

.v-stepper-vertical-item__avatar.v-avatar
background: rgba(var(--v-theme-surface-variant), var(--v-medium-emphasis-opacity))
color: rgb(var(--v-theme-on-surface-variant))
transition-property: background

.v-icon
font-size: .875rem

.v-expansion-panel--active &
background: rgb(var(--v-theme-surface-variant))

.v-stepper-vertical-item--error &
background: rgb(var(--v-theme-error))
color: rgb(var(--v-theme-on-error))

.v-stepper-vertical-item__title
.v-stepper-vertical-item--error &
color: rgb(var(--v-theme-error))

.v-stepper-vertical-item__subtitle
.v-stepper-vertical-item--error &
color: rgb(var(--v-theme-error))

.v-stepper-vertical-actions
&.v-stepper-actions
.v-btn
margin-inline-end: 8px

.v-stepper &
justify-content: flex-end
padding: 24px 0 0
flex-direction: row-reverse
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ export const VStepperVerticalItem = genericComponent<VStepperVerticalItemSlots>(
const step = computed(() => !isNaN(parseInt(props.value)) ? Number(props.value) : props.value)
const groupItem = computed(() => vExpansionPanelRef.value?.groupItem)
const isSelected = computed(() => groupItem.value?.isSelected.value ?? false)
const isValid = computed(() => isSelected.value ? props.rules.every(handler => handler() === true) : null)
const isValid = computed(() => props.rules.every(handler => handler() === true))
const canEdit = computed(() => !props.disabled && props.editable)
const hasError = computed(() => props.error || (isSelected.value && !isValid.value))
const hasCompleted = computed(() => props.complete || (props.rules.length > 0 && isValid.value === true))
const hasError = computed(() => props.error || !isValid.value)
const hasCompleted = computed(() => props.complete || (props.rules.length > 0 && isValid.value))

const disabled = computed(() => {
if (props.disabled) return props.disabled
Expand Down Expand Up @@ -107,8 +107,10 @@ export const VStepperVerticalItem = genericComponent<VStepperVerticalItemSlots>(

useRender(() => {
const hasColor = (
!groupItem.value ||
groupItem.value?.isSelected.value ||
hasCompleted.value ||
groupItem.value?.isSelected.value
canEdit.value
) && (
!hasError.value &&
!props.disabled
Expand Down
Loading