Skip to content

Commit 902dffe

Browse files
authored
feat(stepper): add external controls using useTemplateRef with navigation functions and update docs (#1926)
1 parent f73da04 commit 902dffe

File tree

2 files changed

+86
-5
lines changed

2 files changed

+86
-5
lines changed

docs/content/docs/components/stepper.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,50 @@ import { StepperDescription, StepperIndicator, StepperItem, StepperRoot, Stepper
172172
</template>
173173
```
174174

175+
### With controls
176+
177+
You can add additional controls for the stepper using buttons and access the typed component instance using `useTemplateRef`.
178+
179+
```vue line=8
180+
<script setup lang="ts">
181+
const stepper = useTemplateRef('stepper')
182+
</script>
183+
184+
<template>
185+
<StepperRoot
186+
ref="stepper"
187+
:default-value="1"
188+
>
189+
<StepperItem>
190+
<StepperIndicator />
191+
<StepperTitle />
192+
<StepperDescription />
193+
</StepperItem>
194+
<StepperItem>
195+
<StepperIndicator />
196+
<StepperTitle />
197+
<StepperDescription />
198+
</StepperItem>
199+
</StepperRoot>
200+
201+
<div class="flex gap-2 justify-between mt-4">
202+
<button
203+
:disabled="!stepper?.hasPrev()"
204+
@click="stepper?.prevStep()"
205+
>
206+
Prev
207+
</button>
208+
209+
<button
210+
:disabled="!stepper?.hasNext()"
211+
@click="stepper?.nextStep()"
212+
>
213+
Next
214+
</button>
215+
</div>
216+
</template>
217+
```
218+
175219
## Accessibility
176220

177221
### Keyboard Interactions

packages/core/src/Stepper/StepperRoot.vue

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<script lang="ts">
2-
import type { PrimitiveProps } from '@/Primitive'
32
import type { Ref } from 'vue'
43
import type { DataOrientation, Direction } from '../shared/types'
5-
import { Primitive } from '@/Primitive'
6-
import { createContext, useDirection, useForwardExpose } from '@/shared'
4+
import type { PrimitiveProps } from '@/Primitive'
75
import { useVModel } from '@vueuse/core'
86
import { computed, nextTick, ref, toRefs, watch } from 'vue'
7+
import { Primitive } from '@/Primitive'
8+
import { createContext, useDirection, useForwardExpose } from '@/shared'
99
1010
export interface StepperRootContext {
1111
modelValue: Ref<number | undefined>
@@ -73,6 +73,10 @@ defineSlots<{
7373
nextStep: () => void
7474
/** Go to the previous step */
7575
prevStep: () => void
76+
/** Whether or not there is a next step */
77+
hasNext: () => boolean
78+
/** Whether or not there is a previous step */
79+
hasPrev: () => boolean
7680
}) => any
7781
}>()
7882
@@ -111,6 +115,23 @@ function goToStep(step: number) {
111115
112116
modelValue.value = step
113117
}
118+
119+
function nextStep() {
120+
goToStep((modelValue.value ?? 1) + 1)
121+
}
122+
123+
function prevStep() {
124+
goToStep((modelValue.value ?? 1) - 1)
125+
}
126+
127+
function hasNext() {
128+
return (modelValue.value ?? 1) < totalSteps.value
129+
}
130+
131+
function hasPrev() {
132+
return (modelValue.value ?? 1) > 1
133+
}
134+
114135
const nextStepperItem = ref<HTMLElement | null>(null)
115136
const prevStepperItem = ref<HTMLElement | null>(null)
116137
const isNextDisabled = computed(() => nextStepperItem.value ? nextStepperItem.value.getAttribute('disabled') === '' : true)
@@ -139,6 +160,20 @@ provideStepperRootContext({
139160
linear,
140161
totalStepperItems,
141162
})
163+
164+
defineExpose({
165+
goToStep,
166+
nextStep,
167+
prevStep,
168+
modelValue,
169+
totalSteps,
170+
isNextDisabled,
171+
isPrevDisabled,
172+
isFirstStep,
173+
isLastStep,
174+
hasNext,
175+
hasPrev,
176+
})
142177
</script>
143178

144179
<template>
@@ -158,8 +193,10 @@ provideStepperRootContext({
158193
:is-first-step="isFirstStep"
159194
:is-last-step="isLastStep"
160195
:go-to-step="goToStep"
161-
:next-step="() => goToStep((modelValue ?? 1) + 1)"
162-
:prev-step="() => goToStep((modelValue ?? 1) - 1)"
196+
:next-step="nextStep"
197+
:prev-step="prevStep"
198+
:has-next="hasNext"
199+
:has-prev="hasPrev"
163200
/>
164201

165202
<div

0 commit comments

Comments
 (0)