@youcan/celeste 0.6.31 → 0.6.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/celeste.css +570 -475
- package/dist/cjs/chunks/index.js +95 -0
- package/dist/cjs/chunks/sonner.js +2 -1
- package/dist/cjs/index.js +72 -0
- package/dist/cjs/progress-bar.js +84 -0
- package/dist/cjs/progress-circle.js +92 -0
- package/dist/cjs/sonner-alert.js +2 -2
- package/dist/components/index.d.ts +1 -0
- package/dist/components/progress/index.d.ts +4 -0
- package/dist/components/progress/progress-bar.d.ts +31 -0
- package/dist/components/progress/progress-circle.d.ts +27 -0
- package/dist/es/chunks/index.js +110 -15
- package/dist/es/chunks/sonner.js +3 -2
- package/dist/es/index.js +77 -5
- package/dist/es/progress-bar.js +85 -0
- package/dist/es/progress-circle.js +93 -0
- package/dist/es/select-content.js +1 -1
- package/dist/es/select-item.js +1 -1
- package/dist/es/select-trigger.js +1 -1
- package/dist/es/select-value.js +1 -1
- package/dist/es/sonner-alert.js +2 -2
- package/dist/es/tooltip.js +1 -1
- package/dist/index.d.ts +1 -0
- package/package.json +3 -3
- package/src/components/dropdown-menu/dropdown-menu-content.vue +2 -1
- package/src/components/index.ts +1 -0
- package/src/components/progress/index.ts +5 -0
- package/src/components/progress/progress-bar.vue +167 -0
- package/src/components/progress/progress-circle.vue +126 -0
- package/src/components/progress/stories/progress-bar.stories.ts +328 -0
- package/src/components/progress/stories/progress-circular.stories.ts +152 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from 'vue';
|
|
3
|
+
import { useDelegatedProps } from '@/composables/use-delegated-props';
|
|
4
|
+
import clsx from 'clsx';
|
|
5
|
+
import {
|
|
6
|
+
ProgressIndicator,
|
|
7
|
+
ProgressRoot,
|
|
8
|
+
type ProgressRootProps,
|
|
9
|
+
} from 'radix-vue';
|
|
10
|
+
import { computed } from 'vue';
|
|
11
|
+
|
|
12
|
+
const props = withDefaults(
|
|
13
|
+
defineProps<
|
|
14
|
+
ProgressRootProps & {
|
|
15
|
+
class?: HTMLAttributes['class'];
|
|
16
|
+
size?: 80 | 72 | 64 | 56 | 48;
|
|
17
|
+
}
|
|
18
|
+
>(),
|
|
19
|
+
{
|
|
20
|
+
modelValue: 0,
|
|
21
|
+
size: 80,
|
|
22
|
+
max: 100,
|
|
23
|
+
},
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const delegatedProps = useDelegatedProps(props, 'class');
|
|
27
|
+
|
|
28
|
+
const STROKE_WIDTH = 6.4;
|
|
29
|
+
const radius = computed(() => (props.size - STROKE_WIDTH) / 2);
|
|
30
|
+
const circumference = computed(() => 2 * Math.PI * radius.value);
|
|
31
|
+
|
|
32
|
+
const progress = computed(() => {
|
|
33
|
+
if (props.max === 0)
|
|
34
|
+
return 0;
|
|
35
|
+
|
|
36
|
+
const value = Math.min(Math.max(props.modelValue ?? 0, 0), props.max);
|
|
37
|
+
|
|
38
|
+
return Math.round((value / props.max) * 100);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const offset = computed(() => {
|
|
42
|
+
return circumference.value * (1 - progress.value / 100);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const circleSize = computed(() => `${props.size}px`);
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<template>
|
|
49
|
+
<ProgressRoot
|
|
50
|
+
v-bind="delegatedProps"
|
|
51
|
+
:value="props.modelValue"
|
|
52
|
+
:class="clsx('celeste-progress-circle', props.class)"
|
|
53
|
+
as="div"
|
|
54
|
+
>
|
|
55
|
+
<ProgressIndicator as-child>
|
|
56
|
+
<svg
|
|
57
|
+
class="celeste-progress-circle-svg"
|
|
58
|
+
:width="props.size"
|
|
59
|
+
:height="props.size"
|
|
60
|
+
>
|
|
61
|
+
<circle
|
|
62
|
+
class="celeste-progress-circle-track"
|
|
63
|
+
:cx="props.size / 2"
|
|
64
|
+
:cy="props.size / 2"
|
|
65
|
+
:r="radius"
|
|
66
|
+
:stroke-width="STROKE_WIDTH"
|
|
67
|
+
fill="transparent"
|
|
68
|
+
/>
|
|
69
|
+
<circle
|
|
70
|
+
class="celeste-progress-circle-indicator"
|
|
71
|
+
:cx="props.size / 2"
|
|
72
|
+
:cy="props.size / 2"
|
|
73
|
+
:r="radius"
|
|
74
|
+
:stroke-width="STROKE_WIDTH"
|
|
75
|
+
fill="transparent"
|
|
76
|
+
:stroke-dasharray="circumference"
|
|
77
|
+
:stroke-dashoffset="offset"
|
|
78
|
+
/>
|
|
79
|
+
</svg>
|
|
80
|
+
</ProgressIndicator>
|
|
81
|
+
<div
|
|
82
|
+
v-if="props.size !== 48"
|
|
83
|
+
class="celeste-progress-circle-label"
|
|
84
|
+
>
|
|
85
|
+
<slot>
|
|
86
|
+
{{ progress }}%
|
|
87
|
+
</slot>
|
|
88
|
+
</div>
|
|
89
|
+
</ProgressRoot>
|
|
90
|
+
</template>
|
|
91
|
+
|
|
92
|
+
<style scoped lang="scss">
|
|
93
|
+
.celeste-progress-circle {
|
|
94
|
+
display: inline-flex;
|
|
95
|
+
position: relative;
|
|
96
|
+
align-items: center;
|
|
97
|
+
justify-content: center;
|
|
98
|
+
width: v-bind('circleSize');
|
|
99
|
+
height: v-bind('circleSize');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.celeste-progress-circle-svg {
|
|
103
|
+
transform: rotate(-90deg);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.celeste-progress-circle-track {
|
|
107
|
+
stroke: var(--color-bg-soft-200);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.celeste-progress-circle-indicator {
|
|
111
|
+
transition: stroke-dashoffset 0.3s ease;
|
|
112
|
+
stroke: var(--color-primary-base);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.celeste-progress-circle-label {
|
|
116
|
+
position: absolute;
|
|
117
|
+
top: 50%;
|
|
118
|
+
left: 50%;
|
|
119
|
+
transform: translate(-50%, -50%);
|
|
120
|
+
color: var(--color-text-strong-950);
|
|
121
|
+
font: var(--label-sm);
|
|
122
|
+
text-align: center;
|
|
123
|
+
pointer-events: none;
|
|
124
|
+
user-select: none;
|
|
125
|
+
}
|
|
126
|
+
</style>
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
2
|
+
import ProgressBar from '../progress-bar.vue';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof ProgressBar> = {
|
|
5
|
+
title: 'Components/Progress/Progress Bar',
|
|
6
|
+
component: ProgressBar,
|
|
7
|
+
argTypes: {
|
|
8
|
+
color: {
|
|
9
|
+
control: { type: 'select' },
|
|
10
|
+
options: ['primary', 'blue', 'red', 'orange', 'green'],
|
|
11
|
+
},
|
|
12
|
+
layout: {
|
|
13
|
+
control: { type: 'select' },
|
|
14
|
+
options: ['default', 'no-description', 'inline', 'bare'],
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default meta;
|
|
20
|
+
|
|
21
|
+
type Story = StoryObj<typeof ProgressBar>;
|
|
22
|
+
|
|
23
|
+
export const Default: Story = {
|
|
24
|
+
args: {
|
|
25
|
+
layout: 'default',
|
|
26
|
+
title: 'Data Storage',
|
|
27
|
+
modelValue: 60,
|
|
28
|
+
color: 'primary',
|
|
29
|
+
},
|
|
30
|
+
render: args => ({
|
|
31
|
+
components: { ProgressBar },
|
|
32
|
+
setup() {
|
|
33
|
+
return { args };
|
|
34
|
+
},
|
|
35
|
+
template: `
|
|
36
|
+
<ProgressBar v-bind="args">
|
|
37
|
+
<template #description>
|
|
38
|
+
Upgrade to unlock unlimited data storage.
|
|
39
|
+
</template>
|
|
40
|
+
</ProgressBar>
|
|
41
|
+
`,
|
|
42
|
+
}),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const ZeroProgress: Story = {
|
|
46
|
+
args: {
|
|
47
|
+
layout: 'default',
|
|
48
|
+
title: 'Download Progress',
|
|
49
|
+
modelValue: 0,
|
|
50
|
+
},
|
|
51
|
+
render: args => ({
|
|
52
|
+
components: { ProgressBar },
|
|
53
|
+
setup() {
|
|
54
|
+
return { args };
|
|
55
|
+
},
|
|
56
|
+
template: `
|
|
57
|
+
<ProgressBar v-bind="args">
|
|
58
|
+
<template #description>
|
|
59
|
+
Waiting to start download...
|
|
60
|
+
</template>
|
|
61
|
+
</ProgressBar>
|
|
62
|
+
`,
|
|
63
|
+
}),
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const FullProgress: Story = {
|
|
67
|
+
args: {
|
|
68
|
+
layout: 'default',
|
|
69
|
+
title: 'Upload Complete',
|
|
70
|
+
modelValue: 100,
|
|
71
|
+
color: 'green',
|
|
72
|
+
},
|
|
73
|
+
render: args => ({
|
|
74
|
+
components: { ProgressBar },
|
|
75
|
+
setup() {
|
|
76
|
+
return { args };
|
|
77
|
+
},
|
|
78
|
+
template: `
|
|
79
|
+
<ProgressBar v-bind="args">
|
|
80
|
+
<template #description>
|
|
81
|
+
All files have been uploaded successfully.
|
|
82
|
+
</template>
|
|
83
|
+
</ProgressBar>
|
|
84
|
+
`,
|
|
85
|
+
}),
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export const WithCustomMax: Story = {
|
|
89
|
+
name: 'With Custom Max Value',
|
|
90
|
+
args: {
|
|
91
|
+
layout: 'default',
|
|
92
|
+
title: 'Memory Usage',
|
|
93
|
+
modelValue: 6144,
|
|
94
|
+
max: 8192,
|
|
95
|
+
},
|
|
96
|
+
render: args => ({
|
|
97
|
+
components: { ProgressBar },
|
|
98
|
+
setup() {
|
|
99
|
+
return { args };
|
|
100
|
+
},
|
|
101
|
+
template: `
|
|
102
|
+
<ProgressBar v-bind="args">
|
|
103
|
+
<template #label>
|
|
104
|
+
{{ args.modelValue }}MB / {{ args.max }}MB
|
|
105
|
+
</template>
|
|
106
|
+
<template #description>
|
|
107
|
+
System memory utilization is within normal range.
|
|
108
|
+
</template>
|
|
109
|
+
</ProgressBar>
|
|
110
|
+
`,
|
|
111
|
+
}),
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export const DifferentLayouts: Story = {
|
|
115
|
+
render: () => ({
|
|
116
|
+
components: { ProgressBar },
|
|
117
|
+
template: `
|
|
118
|
+
<div style="display: flex; flex-direction: column; gap: 32px;">
|
|
119
|
+
<div>
|
|
120
|
+
<h3 style="margin-bottom: 16px; font: var(--label-md);">Default Layout</h3>
|
|
121
|
+
<ProgressBar layout="default" title="Project Progress" :modelValue="75">
|
|
122
|
+
<template #description>
|
|
123
|
+
3 of 4 milestones completed
|
|
124
|
+
</template>
|
|
125
|
+
</ProgressBar>
|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
<div>
|
|
129
|
+
<h3 style="margin-bottom: 16px; font: var(--label-md);">No Description Layout</h3>
|
|
130
|
+
<ProgressBar layout="no-description" title="Sync Status" :modelValue="45" />
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
<div>
|
|
134
|
+
<h3 style="margin-bottom: 16px; font: var(--label-md);">Inline Layout</h3>
|
|
135
|
+
<ProgressBar layout="inline" :modelValue="80" />
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
<div>
|
|
139
|
+
<h3 style="margin-bottom: 16px; font: var(--label-md);">Bare Layout</h3>
|
|
140
|
+
<ProgressBar layout="bare" :modelValue="30" />
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
`,
|
|
144
|
+
}),
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
export const DifferentColors: Story = {
|
|
148
|
+
render: () => ({
|
|
149
|
+
components: { ProgressBar },
|
|
150
|
+
template: `
|
|
151
|
+
<div style="display: flex; flex-direction: column; gap: 24px;">
|
|
152
|
+
<div>
|
|
153
|
+
<p style="margin-bottom: 8px; font: var(--label-sm);">Primary</p>
|
|
154
|
+
<ProgressBar layout="inline" color="primary" :modelValue="60" />
|
|
155
|
+
</div>
|
|
156
|
+
<div>
|
|
157
|
+
<p style="margin-bottom: 8px; font: var(--label-sm);">Blue (Information)</p>
|
|
158
|
+
<ProgressBar layout="inline" color="blue" :modelValue="40" />
|
|
159
|
+
</div>
|
|
160
|
+
<div>
|
|
161
|
+
<p style="margin-bottom: 8px; font: var(--label-sm);">Green (Success)</p>
|
|
162
|
+
<ProgressBar layout="inline" color="green" :modelValue="85" />
|
|
163
|
+
</div>
|
|
164
|
+
<div>
|
|
165
|
+
<p style="margin-bottom: 8px; font: var(--label-sm);">Orange (Warning)</p>
|
|
166
|
+
<ProgressBar layout="inline" color="orange" :modelValue="25" />
|
|
167
|
+
</div>
|
|
168
|
+
<div>
|
|
169
|
+
<p style="margin-bottom: 8px; font: var(--label-sm);">Red (Error)</p>
|
|
170
|
+
<ProgressBar layout="inline" color="red" :modelValue="15" />
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
`,
|
|
174
|
+
}),
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
export const WithCustomLabel: Story = {
|
|
178
|
+
name: 'With Custom Label (Slot)',
|
|
179
|
+
args: {
|
|
180
|
+
layout: 'default',
|
|
181
|
+
title: 'File Transfer',
|
|
182
|
+
modelValue: 1024,
|
|
183
|
+
max: 2048,
|
|
184
|
+
},
|
|
185
|
+
render: args => ({
|
|
186
|
+
components: { ProgressBar },
|
|
187
|
+
setup() {
|
|
188
|
+
return { args };
|
|
189
|
+
},
|
|
190
|
+
template: `
|
|
191
|
+
<ProgressBar v-bind="args">
|
|
192
|
+
<template #label>
|
|
193
|
+
{{ Math.round(args.modelValue / 1024 * 10) / 10 }}GB of {{ args.max / 1024 }}GB
|
|
194
|
+
</template>
|
|
195
|
+
<template #description>
|
|
196
|
+
Transfer speed: 25 MB/s • Time remaining: 2 minutes
|
|
197
|
+
</template>
|
|
198
|
+
</ProgressBar>
|
|
199
|
+
`,
|
|
200
|
+
}),
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
export const InlineWithTitle: Story = {
|
|
204
|
+
name: 'Inline Layout with Title',
|
|
205
|
+
args: {
|
|
206
|
+
layout: 'inline',
|
|
207
|
+
title: 'CPU Usage',
|
|
208
|
+
modelValue: 68,
|
|
209
|
+
color: 'orange',
|
|
210
|
+
},
|
|
211
|
+
render: args => ({
|
|
212
|
+
components: { ProgressBar },
|
|
213
|
+
setup() {
|
|
214
|
+
return { args };
|
|
215
|
+
},
|
|
216
|
+
template: `
|
|
217
|
+
<ProgressBar v-bind="args" />
|
|
218
|
+
`,
|
|
219
|
+
}),
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
export const LoadingStates: Story = {
|
|
223
|
+
name: 'Loading States Example',
|
|
224
|
+
render: () => ({
|
|
225
|
+
components: { ProgressBar },
|
|
226
|
+
template: `
|
|
227
|
+
<div style="display: flex; flex-direction: column; gap: 24px;">
|
|
228
|
+
<div>
|
|
229
|
+
<h4 style="margin-bottom: 12px; font: var(--label-sm);">Initializing</h4>
|
|
230
|
+
<ProgressBar layout="default" title="Setup" :modelValue="5" color="blue">
|
|
231
|
+
<template #description>
|
|
232
|
+
Preparing environment...
|
|
233
|
+
</template>
|
|
234
|
+
</ProgressBar>
|
|
235
|
+
</div>
|
|
236
|
+
|
|
237
|
+
<div>
|
|
238
|
+
<h4 style="margin-bottom: 12px; font: var(--label-sm);">In Progress</h4>
|
|
239
|
+
<ProgressBar layout="default" title="Installation" :modelValue="47" color="primary">
|
|
240
|
+
<template #description>
|
|
241
|
+
Installing dependencies (23 of 49)
|
|
242
|
+
</template>
|
|
243
|
+
</ProgressBar>
|
|
244
|
+
</div>
|
|
245
|
+
|
|
246
|
+
<div>
|
|
247
|
+
<h4 style="margin-bottom: 12px; font: var(--label-sm);">Nearly Complete</h4>
|
|
248
|
+
<ProgressBar layout="default" title="Finalizing" :modelValue="92" color="green">
|
|
249
|
+
<template #description>
|
|
250
|
+
Running final checks...
|
|
251
|
+
</template>
|
|
252
|
+
</ProgressBar>
|
|
253
|
+
</div>
|
|
254
|
+
</div>
|
|
255
|
+
`,
|
|
256
|
+
}),
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
export const EdgeCases: Story = {
|
|
260
|
+
render: () => ({
|
|
261
|
+
components: { ProgressBar },
|
|
262
|
+
template: `
|
|
263
|
+
<div style="display: flex; flex-direction: column; gap: 24px;">
|
|
264
|
+
<div>
|
|
265
|
+
<p style="margin-bottom: 8px; font: var(--label-sm);">Over Max Value</p>
|
|
266
|
+
<ProgressBar layout="inline" :modelValue="150" :max="100" color="red" />
|
|
267
|
+
</div>
|
|
268
|
+
<div>
|
|
269
|
+
<p style="margin-bottom: 8px; font: var(--label-sm);">Negative Value</p>
|
|
270
|
+
<ProgressBar layout="inline" :modelValue="-20" color="red" />
|
|
271
|
+
</div>
|
|
272
|
+
<div>
|
|
273
|
+
<p style="margin-bottom: 8px; font: var(--label-sm);">Max is Zero</p>
|
|
274
|
+
<ProgressBar layout="inline" :modelValue="0" :max="0" />
|
|
275
|
+
</div>
|
|
276
|
+
<div>
|
|
277
|
+
<p style="margin-bottom: 8px; font: var(--label-sm);">Very Small Progress</p>
|
|
278
|
+
<ProgressBar layout="inline" :modelValue="0.5" :max="100" />
|
|
279
|
+
</div>
|
|
280
|
+
</div>
|
|
281
|
+
`,
|
|
282
|
+
}),
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
export const RealWorldExamples: Story = {
|
|
286
|
+
name: 'Real World Use Cases',
|
|
287
|
+
render: () => ({
|
|
288
|
+
components: { ProgressBar },
|
|
289
|
+
template: `
|
|
290
|
+
<div style="display: flex; flex-direction: column; gap: 32px; max-width: 400px;">
|
|
291
|
+
<div>
|
|
292
|
+
<h4 style="margin-bottom: 16px; font: var(--label-md);">Storage Quota</h4>
|
|
293
|
+
<ProgressBar layout="default" title="Cloud Storage" :modelValue="1847" :max="2000" color="orange">
|
|
294
|
+
<template #label>
|
|
295
|
+
1.8GB of 2GB used
|
|
296
|
+
</template>
|
|
297
|
+
<template #description>
|
|
298
|
+
You're running low on storage space. Consider upgrading your plan.
|
|
299
|
+
</template>
|
|
300
|
+
</ProgressBar>
|
|
301
|
+
</div>
|
|
302
|
+
|
|
303
|
+
<div>
|
|
304
|
+
<h4 style="margin-bottom: 16px; font: var(--label-md);">Profile Completion</h4>
|
|
305
|
+
<ProgressBar layout="default" title="Profile Setup" :modelValue="6" :max="8" color="blue">
|
|
306
|
+
<template #label>
|
|
307
|
+
6 of 8 steps completed
|
|
308
|
+
</template>
|
|
309
|
+
<template #description>
|
|
310
|
+
Complete your profile to unlock all features.
|
|
311
|
+
</template>
|
|
312
|
+
</ProgressBar>
|
|
313
|
+
</div>
|
|
314
|
+
|
|
315
|
+
<div>
|
|
316
|
+
<h4 style="margin-bottom: 16px; font: var(--label-md);">System Health</h4>
|
|
317
|
+
<ProgressBar layout="no-description" title="CPU Usage" :modelValue="23" color="green" />
|
|
318
|
+
<div style="margin-top: 8px;">
|
|
319
|
+
<ProgressBar layout="no-description" title="Memory" :modelValue="67" color="primary" />
|
|
320
|
+
</div>
|
|
321
|
+
<div style="margin-top: 8px;">
|
|
322
|
+
<ProgressBar layout="no-description" title="Disk Space" :modelValue="89" color="orange" />
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
326
|
+
`,
|
|
327
|
+
}),
|
|
328
|
+
};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
2
|
+
import ProgressCircle from '../progress-circle.vue';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof ProgressCircle> = {
|
|
5
|
+
title: 'Components/Progress/Progress Circle',
|
|
6
|
+
component: ProgressCircle,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export default meta;
|
|
10
|
+
|
|
11
|
+
type Story = StoryObj<typeof ProgressCircle>;
|
|
12
|
+
|
|
13
|
+
export const Default: Story = {
|
|
14
|
+
args: {
|
|
15
|
+
modelValue: 45,
|
|
16
|
+
},
|
|
17
|
+
render: args => ({
|
|
18
|
+
components: { ProgressCircle },
|
|
19
|
+
setup() {
|
|
20
|
+
return { args };
|
|
21
|
+
},
|
|
22
|
+
template: `
|
|
23
|
+
<ProgressCircle v-bind="args" />
|
|
24
|
+
`,
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const ZeroProgress: Story = {
|
|
29
|
+
args: {
|
|
30
|
+
modelValue: 0,
|
|
31
|
+
},
|
|
32
|
+
render: args => ({
|
|
33
|
+
components: { ProgressCircle },
|
|
34
|
+
setup() {
|
|
35
|
+
return { args };
|
|
36
|
+
},
|
|
37
|
+
template: `<ProgressCircle v-bind="args" />`,
|
|
38
|
+
}),
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const FullProgress: Story = {
|
|
42
|
+
args: {
|
|
43
|
+
modelValue: 100,
|
|
44
|
+
},
|
|
45
|
+
render: args => ({
|
|
46
|
+
components: { ProgressCircle },
|
|
47
|
+
setup() {
|
|
48
|
+
return { args };
|
|
49
|
+
},
|
|
50
|
+
template: `<ProgressCircle v-bind="args" />`,
|
|
51
|
+
}),
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const WithValueAndMax: Story = {
|
|
55
|
+
name: 'With Custom Max Value',
|
|
56
|
+
args: {
|
|
57
|
+
modelValue: 256,
|
|
58
|
+
max: 1024,
|
|
59
|
+
},
|
|
60
|
+
render: args => ({
|
|
61
|
+
components: { ProgressCircle },
|
|
62
|
+
setup() {
|
|
63
|
+
return { args };
|
|
64
|
+
},
|
|
65
|
+
template: `<ProgressCircle v-bind="args" />`,
|
|
66
|
+
}),
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const WithCustomLabelInSlot: Story = {
|
|
70
|
+
name: 'With Custom Label (Slot)',
|
|
71
|
+
args: {
|
|
72
|
+
modelValue: 5,
|
|
73
|
+
max: 10,
|
|
74
|
+
size: 80,
|
|
75
|
+
},
|
|
76
|
+
render: args => ({
|
|
77
|
+
components: { ProgressCircle },
|
|
78
|
+
setup() {
|
|
79
|
+
return { args };
|
|
80
|
+
},
|
|
81
|
+
template: `
|
|
82
|
+
<ProgressCircle v-bind="args">
|
|
83
|
+
5/10 Done
|
|
84
|
+
</ProgressCircle>
|
|
85
|
+
`,
|
|
86
|
+
}),
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const WithCustomIconInSlot: Story = {
|
|
90
|
+
name: 'With Custom Icon (Slot)',
|
|
91
|
+
args: {
|
|
92
|
+
modelValue: 100,
|
|
93
|
+
max: 100,
|
|
94
|
+
size: 80,
|
|
95
|
+
},
|
|
96
|
+
render: args => ({
|
|
97
|
+
components: { ProgressCircle },
|
|
98
|
+
setup() {
|
|
99
|
+
return { args };
|
|
100
|
+
},
|
|
101
|
+
template: `
|
|
102
|
+
<ProgressCircle v-bind="args">
|
|
103
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
|
|
104
|
+
<path d="M5 13l4 4L19 7" />
|
|
105
|
+
</svg>
|
|
106
|
+
</ProgressCircle>
|
|
107
|
+
`,
|
|
108
|
+
}),
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export const DifferentSizes: Story = {
|
|
112
|
+
args: {
|
|
113
|
+
modelValue: 75,
|
|
114
|
+
},
|
|
115
|
+
render: args => ({
|
|
116
|
+
components: { ProgressCircle },
|
|
117
|
+
setup() {
|
|
118
|
+
return { args };
|
|
119
|
+
},
|
|
120
|
+
template: `
|
|
121
|
+
<div style="display: flex; align-items: center; gap: 16px;">
|
|
122
|
+
<ProgressCircle v-bind="args" :size="80" />
|
|
123
|
+
<ProgressCircle v-bind="args" :size="72" />
|
|
124
|
+
<ProgressCircle v-bind="args" :size="64" />
|
|
125
|
+
<ProgressCircle v-bind="args" :size="56" />
|
|
126
|
+
<ProgressCircle v-bind="args" :size="48" />
|
|
127
|
+
</div>
|
|
128
|
+
`,
|
|
129
|
+
}),
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export const EdgeCases: Story = {
|
|
133
|
+
render: () => ({
|
|
134
|
+
components: { ProgressCircle },
|
|
135
|
+
template: `
|
|
136
|
+
<div style="display: flex; align-items: center; gap: 24px;">
|
|
137
|
+
<div>
|
|
138
|
+
<p style="text-align: center; margin-bottom: 8px; font: var(--label-sm);">Over Max</p>
|
|
139
|
+
<ProgressCircle :modelValue="150" :max="100" />
|
|
140
|
+
</div>
|
|
141
|
+
<div>
|
|
142
|
+
<p style="text-align: center; margin-bottom: 8px; font: var(--label-sm);">Negative Value</p>
|
|
143
|
+
<ProgressCircle :modelValue="-50" />
|
|
144
|
+
</div>
|
|
145
|
+
<div>
|
|
146
|
+
<p style="text-align: center; margin-bottom: 8px; font: var(--label-sm);">Max is Zero</p>
|
|
147
|
+
<ProgressCircle :modelValue="0" :max="0" />
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|
|
150
|
+
`,
|
|
151
|
+
}),
|
|
152
|
+
};
|
package/src/index.ts
CHANGED