refactor: make stepper responsive (#1144)

This PR adds a responsive layout for the Stepper component on small
screens. There's a vertical orientation version but the changes here
won't be compatible. If we need a verticle version we can just create a
separate component folder for the vertical only version.

<img width="171" alt="image"
src="https://github.com/user-attachments/assets/4e38ac68-ca17-400a-b07b-2bfcb2c0a192"
/>

 
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Summary by CodeRabbit

- **Style**
- Enhanced the visual design of the stepper components with improved
responsive layouts—displaying vertically on smaller screens and
horizontally on medium and larger screens.
- **New Features**
- Added an interactive demo showcasing the stepper workflow in
Storybook.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: mdatelle <mike@datelle.net>
This commit is contained in:
Michael Datelle
2025-02-19 14:40:11 -05:00
committed by GitHub
parent 7588e0e3cf
commit 62dc8294e8
5 changed files with 92 additions and 4 deletions

View File

@@ -17,7 +17,11 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
</script>
<template>
<StepperRoot v-slot="slotProps" :class="cn('flex gap-2', props.class)" v-bind="forwarded">
<StepperRoot
v-slot="slotProps"
:class="cn('flex flex-col gap-2 md:flex-row', props.class)"
v-bind="forwarded"
>
<slot v-bind="slotProps" />
</StepperRoot>
</template>

View File

@@ -19,7 +19,15 @@ const forwarded = useForwardProps(delegatedProps);
<StepperItem
v-slot="slotProps"
v-bind="forwarded"
:class="cn('flex items-center gap-2 group data-[disabled]:pointer-events-none', props.class)"
:class="
cn(
'flex flex-col items-start gap-1',
'md:flex-row md:items-center md:gap-2',
'group transition-all duration-200',
'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
props.class
)
"
>
<slot v-bind="slotProps" />
</StepperItem>

View File

@@ -20,7 +20,7 @@ const forwarded = useForwardProps(delegatedProps);
v-bind="forwarded"
:class="
cn(
'bg-muted',
'hidden md:block bg-muted md:w-24 md:h-px md:my-0',
// Disabled
'group-data-[disabled]:bg-muted group-data-[disabled]:opacity-75',
// Completed

View File

@@ -18,7 +18,12 @@ const forwarded = useForwardProps(delegatedProps);
<template>
<StepperTrigger
v-bind="forwarded"
:class="cn('p-2 flex flex-col items-center text-center gap-2 rounded-md', props.class)"
:class="
cn(
'flex flex-col items-center justify-center text-center gap-2 rounded-md w-full md:w-auto',
props.class
)
"
>
<slot />
</StepperTrigger>

View File

@@ -0,0 +1,71 @@
import type { Meta, StoryObj } from '@storybook/vue3';
import {
Stepper as StepperComponent,
StepperDescription,
StepperIndicator,
StepperItem,
StepperSeparator,
StepperTitle,
StepperTrigger,
} from '../../../src/components/common/stepper';
const meta = {
title: 'Components/Common',
component: StepperComponent,
parameters: {
layout: 'padded',
viewport: {
defaultViewport: 'responsive',
viewports: {
responsive: {
name: 'Responsive',
styles: { width: '100%', height: '100%' },
},
mobile: {
name: 'Mobile',
styles: { width: '320px', height: '100%' },
},
},
},
},
} satisfies Meta<typeof StepperComponent>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Stepper: Story = {
render: () => ({
components: {
StepperComponent,
StepperItem,
StepperTitle,
StepperDescription,
StepperIndicator,
StepperSeparator,
StepperTrigger,
},
template: `
<StepperComponent>
<template v-for="(step, index) in steps" :key="index">
<StepperItem :step="index + 1">
<StepperTrigger>
<StepperIndicator>{{ index + 1 }}</StepperIndicator>
<StepperTitle>{{ step.title }}</StepperTitle>
<StepperDescription>{{ step.description }}</StepperDescription>
</StepperTrigger>
<StepperSeparator v-if="index < steps.length - 1" />
</StepperItem>
</template>
</StepperComponent>
`,
setup() {
const steps = [
{ title: 'Account Setup', description: 'Create your account' },
{ title: 'Server Details', description: 'Configure your server' },
{ title: 'Review', description: 'Review and confirm' },
];
return { steps };
},
}),
};