@@ -103,36 +103,48 @@ export function Stepper({
103103 ) ;
104104}
105105
106+ type StepListContextType = {
107+ alignment : 'center' | 'start' ;
108+ compact : boolean ;
109+ labelPlacement : 'top' | 'bottom' ;
110+ } ;
111+
112+ const StepListContext = React . createContext < StepListContextType > ( {
113+ alignment : 'center' ,
114+ compact : false ,
115+ labelPlacement : 'bottom' ,
116+ } ) ;
117+
106118export function StepList ( {
107119 className,
108- centered = true ,
120+ alignment = 'center' ,
121+ compact = false ,
122+ labelPlacement = 'bottom' ,
109123 ...props
110- } : React . JSX . IntrinsicElements [ 'ol' ] & {
111- centered ?: boolean ;
112- } ) {
124+ } : React . JSX . IntrinsicElements [ 'ol' ] & Partial < StepListContextType > ) {
113125 return (
114- < ol
115- { ...props }
116- { ...( centered && {
117- 'data-centered' : true ,
118- } ) }
119- className = { twMerge (
120- 'flex w-full gap-x-2 overflow-x-auto' ,
121- '[--separator-radius:calc(infinity_*_1px)]' ,
122- '[&.gap-x-0]:[--separator-radius:0]' ,
123- '[&.gap-x-0]:rounded-full' ,
124- '[--counter-size:--spacing(6)]' ,
125- '[--counter-padding:--spacing(1)]' ,
126- '[--counter:var(--color-zinc-200)]/75' ,
127- 'dark:[--counter:var(--color-zinc-700)]' ,
128- '[--counter-text:var(--muted)]' ,
129- '[--counter-highlight:var(--accent)]' ,
130- '[--counter-highlight-text:lch(from_var(--counter-highlight)_calc((49.44_-_l)_*_infinity)_0_0)]' ,
131- '[--separator-h:--spacing(0.5)]' ,
126+ < StepListContext . Provider value = { { alignment, compact, labelPlacement } } >
127+ < ol
128+ { ...props }
129+ className = { twMerge (
130+ 'flex w-full overflow-x-auto' ,
131+ ! compact && 'gap-x-2' ,
132+ '[--separator-radius:calc(infinity_*_1px)]' ,
133+ '[&.gap-x-0]:[--separator-radius:0]' ,
134+ '[&.gap-x-0]:rounded-full' ,
135+ '[--counter-size:--spacing(6)]' ,
136+ '[--counter-padding:--spacing(1)]' ,
137+ '[--counter:var(--color-zinc-200)]/75' ,
138+ 'dark:[--counter:var(--color-zinc-700)]' ,
139+ '[--counter-text:var(--muted)]' ,
140+ '[--counter-highlight:var(--accent)]' ,
141+ '[--counter-highlight-text:lch(from_var(--counter-highlight)_calc((49.44_-_l)_*_infinity)_0_0)]' ,
142+ '[--separator-h:--spacing(0.5)]' ,
132143
133- className ,
134- ) }
135- />
144+ className ,
145+ ) }
146+ />
147+ </ StepListContext . Provider >
136148 ) ;
137149}
138150
@@ -163,6 +175,7 @@ export function Step({
163175 const { value, steps } = useStepIndicator ( ) ;
164176 const completed = value >= step ;
165177 const current = value === step - 1 ;
178+ const { alignment, labelPlacement } = React . useContext ( StepListContext ) ;
166179
167180 return (
168181 < StepContext . Provider
@@ -172,35 +185,58 @@ export function Step({
172185 { ...props }
173186 className = { twMerge (
174187 'relative isolate flex flex-1 shrink-0 flex-col gap-2 text-sm/6' ,
175- 'in-[[data-centered]]: items-center in-[[data-centered]]: text-center',
188+ alignment === 'center' && [ ' items-center' , ' text-center'] ,
176189 typeof className == 'function'
177190 ? className ( { completed, current } )
178191 : className ,
179192 ) }
180193 >
181194 { counter ? (
182195 < >
196+ { labelPlacement === 'top' && (
197+ < span
198+ { ...( ariaLabel && { 'aria-label' : ariaLabel } ) }
199+ className = "contents"
200+ >
201+ { children }
202+ </ span >
203+ ) }
204+
183205 { typeof counter === 'function'
184206 ? counter ( { completed, step } )
185207 : counter }
186- < span
187- { ...( ariaLabel && { 'aria-label' : ariaLabel } ) }
188- className = "contents"
189- >
190- { children }
191- </ span >
208+
209+ { labelPlacement === 'bottom' && (
210+ < span
211+ { ...( ariaLabel && { 'aria-label' : ariaLabel } ) }
212+ className = "contents"
213+ >
214+ { children }
215+ </ span >
216+ ) }
192217
193218 { step < steps && ( separator ? separator : < StepSeparator /> ) }
194219 </ >
195220 ) : (
196221 < >
222+ { labelPlacement === 'top' && (
223+ < span
224+ { ...( ariaLabel && { 'aria-label' : ariaLabel } ) }
225+ className = "contents"
226+ >
227+ { children }
228+ </ span >
229+ ) }
197230 { separator ? separator : < StepSeparator /> }
198- < span
199- { ...( ariaLabel && { 'aria-label' : ariaLabel } ) }
200- className = "contents"
201- >
202- { children }
203- </ span >
231+
232+ { labelPlacement === 'bottom' && (
233+ < span
234+ { ...( ariaLabel && { 'aria-label' : ariaLabel } ) }
235+ className = "contents"
236+ >
237+ { children }
238+ </ span >
239+ ) }
204240 </ >
205241 ) }
206242
@@ -244,6 +280,8 @@ export function StepSeparator({
244280 ...props
245281} : Omit < React . JSX . IntrinsicElements [ 'div' ] , 'children' > ) {
246282 const { hasCounter, completed, current } = useStepContext ( ) ;
283+ const { alignment, labelPlacement, compact } =
284+ React . useContext ( StepListContext ) ;
247285
248286 return hasCounter ? (
249287 < div
@@ -252,11 +290,30 @@ export function StepSeparator({
252290 aria-hidden
253291 className = { twMerge (
254292 'transition-colors duration-300 ease-in-out' ,
255- 'absolute top-[calc(var(--counter-size)/2)] h-(--separator-h) -translate-y-1/2 rounded-(--separator-radius)' ,
256- 'left-[calc(var(--counter-size,0)+0.25rem)]' ,
293+ 'absolute h-(--separator-h) -translate-y-1/2 rounded-(--separator-radius)' ,
294+
295+ labelPlacement === 'top'
296+ ? 'bottom-[calc(var(--counter-size)/2)]'
297+ : 'top-[calc(var(--counter-size)/2)]' ,
298+
257299 'w-[calc(100%-var(--counter-size,0))]' ,
258- 'in-[[data-centered]]:left-[calc(50%+calc(var(--counter-size,0)/2)+0.125rem)]' ,
259- 'in-[[data-centered]]:w-[calc(100%-var(--counter-size,0)+0.5rem-0.25rem)]' ,
300+
301+ compact
302+ ? [
303+ 'left-[calc(var(--counter-size,0))]' ,
304+ alignment === 'center' && [
305+ 'left-[calc(50%+calc(var(--counter-size,0)/2))]' ,
306+ 'w-[calc(100%-var(--counter-size,0))]' ,
307+ ] ,
308+ ]
309+ : [
310+ 'left-[calc(var(--counter-size,0)+0.25rem)]' ,
311+ alignment === 'center' && [
312+ 'left-[calc(50%+calc(var(--counter-size,0)/2)+0.125rem)]' ,
313+ 'w-[calc(100%-var(--counter-size,0)+0.5rem-0.25rem)]' ,
314+ ] ,
315+ ] ,
316+
260317 'in-[.gap-x-0]:rounded-0' ,
261318 'bg-(--counter)' ,
262319 completed && 'bg-(--counter-highlight)' ,
0 commit comments