Skip to content

Commit 755d175

Browse files
author
Lasim
committed
feat(frontend): add white variant to card component styles
1 parent bdb2280 commit 755d175

File tree

4 files changed

+109
-82
lines changed

4 files changed

+109
-82
lines changed

services/frontend/src/components/ui/card/Card.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const cardVariants = cva(
1010
variant: {
1111
default: 'bg-card',
1212
gray: 'bg-zinc-100',
13+
white: 'bg-white',
1314
},
1415
},
1516
defaultVariants: {

services/frontend/src/components/ui/chart/LineChart.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ const chartOption = computed<EChartsOption>(() => ({
5959
right: '4%',
6060
bottom: '3%',
6161
top: '10%',
62-
containLabel: true,
6362
},
6463
xAxis: {
6564
type: 'category',

services/frontend/src/components/ui/progress-bars/ProgressBars.vue

Lines changed: 108 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import { computed } from 'vue'
3838
import { cva, type VariantProps } from 'class-variance-authority'
3939
import { cn } from '@/lib/utils'
40+
import Card from '@/components/ui/card/Card.vue'
4041
4142
export interface ProgressStep {
4243
id: string
@@ -117,7 +118,6 @@ interface Props {
117118
showSteps?: boolean
118119
hideTitle?: boolean
119120
interactive?: boolean
120-
styled?: boolean // New prop for styled container
121121
}
122122
123123
const props = withDefaults(defineProps<Props>(), {
@@ -126,8 +126,7 @@ const props = withDefaults(defineProps<Props>(), {
126126
size: 'md',
127127
showSteps: true,
128128
hideTitle: false,
129-
interactive: false,
130-
styled: false
129+
interactive: false
131130
})
132131
133132
const emit = defineEmits<{
@@ -158,13 +157,16 @@ const stepVariants = cva(
158157
159158
const clampedProgress = computed(() => Math.max(0, Math.min(100, props.progress)))
160159
161-
// Calculate the exact position percentage for each step
160+
// Calculate the exact position percentage for each step with padding
162161
function getStepPosition(index: number) {
163162
const totalSteps = props.steps.length
164-
if (totalSteps <= 1) return 50 // Center if only one step
165-
166-
// Calculate position as percentage (0% to 100%)
167-
return (index / (totalSteps - 1)) * 100
163+
if (totalSteps <= 1) return 50
164+
165+
const padding = 3 // 3% padding on each side
166+
const availableWidth = 100 - (padding * 2)
167+
const position = padding + (index / (totalSteps - 1)) * availableWidth
168+
169+
return position
168170
}
169171
170172
function handleStepClick(step: ProgressStep, index: number) {
@@ -176,7 +178,7 @@ function handleStepClick(step: ProgressStep, index: number) {
176178
// Get transform style to center text on the exact position
177179
function getStepTransform(index: number) {
178180
const position = getStepPosition(index)
179-
181+
180182
// Adjust transform to center the text on the position
181183
if (position === 0) return 'translateX(0%)' // First step: no adjustment needed
182184
if (position === 100) return 'translateX(-100%)' // Last step: move completely left
@@ -185,85 +187,111 @@ function getStepTransform(index: number) {
185187
</script>
186188

187189
<template>
188-
<div
189-
:class="[
190-
cn(progressBarsVariants({ variant, size })),
191-
styled ? 'rounded-lg bg-muted/50 px-4 py-6 sm:px-6' : ''
192-
]"
193-
>
194-
<!-- Title -->
195-
<div v-if="title" :class="styled ? 'mb-6' : 'mb-4'">
196-
<h4 v-if="hideTitle" class="sr-only">{{ title }}</h4>
197-
<p v-else class="text-sm font-medium text-foreground">{{ title }}</p>
198-
</div>
190+
<Card variant="white">
191+
<div class="px-6">
192+
<div :class="cn(progressBarsVariants({ variant, size }))">
193+
<!-- Title -->
194+
<div v-if="title" class="mb-4">
195+
<h4 v-if="hideTitle" class="sr-only">{{ title }}</h4>
196+
<p v-else class="text-sm font-medium text-foreground">{{ title }}</p>
197+
</div>
199198

200-
<!-- Progress Bar -->
201-
<div class="space-y-4">
202-
<div
203-
role="progressbar"
204-
:aria-valuenow="clampedProgress"
205-
aria-valuemin="0"
206-
aria-valuemax="100"
207-
:aria-label="title || 'Progress'"
208-
:class="cn(progressBarVariants({ variant, size }))"
209-
>
210-
<div
211-
:class="cn(progressFillVariants({ variant }))"
212-
:style="{ width: `${clampedProgress}%` }"
213-
/>
214-
</div>
199+
<!-- Progress Bar -->
200+
<div class="mt-6">
201+
<div class="relative">
202+
<div
203+
role="progressbar"
204+
:aria-valuenow="clampedProgress"
205+
aria-valuemin="0"
206+
aria-valuemax="100"
207+
:aria-label="title || 'Progress'"
208+
:class="cn(progressBarVariants({ variant, size }))"
209+
>
210+
<div
211+
:class="cn(progressFillVariants({ variant }))"
212+
:style="{ width: `${clampedProgress}%` }"
213+
/>
214+
</div>
215215

216-
<!-- Steps -->
217-
<div
218-
v-if="showSteps && steps.length > 0"
219-
class="hidden sm:block relative w-full pt-2"
220-
>
221-
<button
222-
v-for="(step, index) in steps"
223-
:key="step.id"
224-
:type="interactive && step.clickable ? 'button' : undefined"
225-
:disabled="!interactive || !step.clickable"
226-
:class="[
227-
cn(stepVariants({
228-
status: step.status,
229-
clickable: interactive && step.clickable
230-
})),
231-
'absolute text-sm font-medium whitespace-nowrap'
232-
]"
233-
:style="{
234-
left: `${getStepPosition(index)}%`,
235-
transform: getStepTransform(index)
236-
}"
237-
@click="handleStepClick(step, index)"
238-
>
239-
{{ step.label }}
240-
</button>
241-
</div>
216+
<!-- Step boxes overlaid on progress bar -->
217+
<div
218+
v-if="showSteps && steps.length > 0"
219+
class="hidden sm:block absolute inset-0 pointer-events-none"
220+
>
221+
<div
222+
v-for="(step, index) in steps"
223+
:key="step.id"
224+
class="absolute top-1/2"
225+
:style="{
226+
left: `${getStepPosition(index)}%`,
227+
transform: `translate(-50%, calc(-50% + 1px))`
228+
}"
229+
>
230+
<button
231+
:type="interactive && step.clickable ? 'button' : undefined"
232+
:disabled="!interactive || !step.clickable"
233+
:class="[
234+
'bg-white border border-gray-300 rounded px-2 py-1 text-sm font-medium pointer-events-auto',
235+
interactive && step.clickable ? 'cursor-pointer hover:bg-gray-50' : ''
236+
]"
237+
@click="handleStepClick(step, index)"
238+
>
239+
{{ index + 1 }}
240+
</button>
241+
</div>
242+
</div>
243+
</div>
242244

243-
<!-- Mobile Steps (Vertical List) -->
244-
<div v-if="showSteps && steps.length > 0" class="sm:hidden space-y-2">
245-
<div
246-
v-for="(step, index) in steps"
247-
:key="`mobile-${step.id}`"
248-
class="flex items-center justify-between"
249-
>
250-
<span :class="cn(stepVariants({ status: step.status }))">
251-
{{ step.label }}
252-
</span>
253-
<div class="flex items-center gap-2">
254-
<!-- Status Icon -->
245+
<!-- Step labels below -->
246+
<div
247+
v-if="showSteps && steps.length > 0"
248+
class="hidden sm:block relative w-full mt-2 py-5"
249+
>
255250
<div
251+
v-for="(step, index) in steps"
252+
:key="`label-${step.id}`"
256253
:class="[
257-
'w-2 h-2 rounded-full',
258-
step.status === 'completed' ? 'bg-primary' : '',
259-
step.status === 'current' ? 'bg-primary animate-pulse' : '',
260-
step.status === 'pending' ? 'bg-red-500' : '',
261-
step.status === 'error' ? 'bg-destructive' : ''
254+
cn(stepVariants({
255+
status: step.status,
256+
clickable: false
257+
})),
258+
'absolute text-sm font-medium whitespace-nowrap'
262259
]"
263-
/>
260+
:style="{
261+
left: `${getStepPosition(index)}%`,
262+
transform: getStepTransform(index)
263+
}"
264+
>
265+
{{ step.label }}
266+
</div>
267+
</div>
268+
269+
<!-- Mobile Steps (Vertical List) -->
270+
<div v-if="showSteps && steps.length > 0" class="sm:hidden space-y-2">
271+
<div
272+
v-for="(step, index) in steps"
273+
:key="`mobile-${step.id}`"
274+
class="flex items-center justify-between"
275+
>
276+
<span :class="cn(stepVariants({ status: step.status }))">
277+
{{ step.label }}
278+
</span>
279+
<div class="flex items-center gap-2">
280+
<!-- Status Icon -->
281+
<div
282+
:class="[
283+
'w-2 h-2 rounded-full',
284+
step.status === 'completed' ? 'bg-primary' : '',
285+
step.status === 'current' ? 'bg-primary animate-pulse' : '',
286+
step.status === 'pending' ? 'bg-red-500' : '',
287+
step.status === 'error' ? 'bg-destructive' : ''
288+
]"
289+
/>
290+
</div>
291+
</div>
264292
</div>
265293
</div>
266294
</div>
267295
</div>
268-
</div>
296+
</Card>
269297
</template>

services/frontend/src/components/ui/progress-bars/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ function handleStepClick(step, index) {
122122
| `showSteps` | `boolean` | `true` | Whether to show step labels |
123123
| `hideTitle` | `boolean` | `false` | Hide title visually (keeps for screen readers) |
124124
| `interactive` | `boolean` | `false` | Enable step click interactions |
125-
| `styled` | `boolean` | `false` | Add styled container with background and padding |
126125

127126
### ProgressStep Interface
128127

0 commit comments

Comments
 (0)