@youcan/celeste 0.6.49 → 0.6.50

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.
Files changed (91) hide show
  1. package/dist/celeste.css +310 -98
  2. package/dist/cjs/chunks/counter-input.vue_vue_type_style_index_0_lang.js +70 -0
  3. package/dist/cjs/chunks/index.js +684 -0
  4. package/dist/cjs/counter-input.js +3 -0
  5. package/dist/cjs/index.js +9 -0
  6. package/dist/cjs/modal-header.js +1 -1
  7. package/dist/cjs/radio-group-card.js +110 -0
  8. package/dist/cjs/radio-group-label.js +109 -0
  9. package/dist/components/counter-input/counter-input.d.ts +17 -0
  10. package/dist/components/counter-input/index.d.ts +2 -0
  11. package/dist/components/index.d.ts +1 -0
  12. package/dist/components/radio-group/index.d.ts +4 -0
  13. package/dist/components/radio-group/radio-group-card.d.ts +34 -0
  14. package/dist/components/radio-group/radio-group-label.d.ts +29 -0
  15. package/dist/es/button.js +1 -1
  16. package/dist/es/checkbox-card.js +1 -1
  17. package/dist/es/checkbox-label.js +1 -1
  18. package/dist/es/chunks/counter-input.vue_vue_type_style_index_0_lang.js +71 -0
  19. package/dist/es/chunks/index.js +754 -70
  20. package/dist/es/chunks/index3.js +1 -1
  21. package/dist/es/chunks/radio-group-item.vue_vue_type_style_index_0_lang.js +1 -1
  22. package/dist/es/chunks/switch.vue_vue_type_style_index_0_lang.js +1 -1
  23. package/dist/es/combobox-group.js +1 -1
  24. package/dist/es/combobox-input.js +1 -1
  25. package/dist/es/combobox-item.js +1 -1
  26. package/dist/es/combobox-list.js +1 -1
  27. package/dist/es/combobox-root.js +1 -1
  28. package/dist/es/combobox-separator.js +1 -1
  29. package/dist/es/combobox-trigger.js +1 -1
  30. package/dist/es/command-group.js +1 -1
  31. package/dist/es/command-input.js +1 -1
  32. package/dist/es/command-item.js +1 -1
  33. package/dist/es/command-list.js +1 -1
  34. package/dist/es/command-root.js +1 -1
  35. package/dist/es/command-separator.js +1 -1
  36. package/dist/es/compact-button.js +1 -1
  37. package/dist/es/context-menu-item.js +1 -1
  38. package/dist/es/counter-input.js +4 -0
  39. package/dist/es/digit-input-group.js +1 -1
  40. package/dist/es/digit-input-slot.js +1 -1
  41. package/dist/es/digit-input.js +1 -1
  42. package/dist/es/dropdown-menu-content.js +1 -1
  43. package/dist/es/dropdown-menu-group.js +1 -1
  44. package/dist/es/dropdown-menu-item.js +1 -1
  45. package/dist/es/dropdown-menu-label.js +1 -1
  46. package/dist/es/dropdown-menu-separator.js +1 -1
  47. package/dist/es/dropdown-menu-sub-content.js +1 -1
  48. package/dist/es/dropdown-menu-sub-trigger.js +1 -1
  49. package/dist/es/dropdown-menu-trigger.js +1 -1
  50. package/dist/es/dropdown-menu.js +1 -1
  51. package/dist/es/dropdown.js +1 -1
  52. package/dist/es/fancy-button.js +1 -1
  53. package/dist/es/index.js +48 -39
  54. package/dist/es/label.js +1 -1
  55. package/dist/es/link-button.js +1 -1
  56. package/dist/es/modal-content.js +1 -1
  57. package/dist/es/modal-header.js +2 -2
  58. package/dist/es/popover-content.js +1 -1
  59. package/dist/es/popover-trigger.js +1 -1
  60. package/dist/es/progress-bar.js +1 -1
  61. package/dist/es/progress-circle.js +1 -1
  62. package/dist/es/radio-group-card.js +111 -0
  63. package/dist/es/radio-group-label.js +110 -0
  64. package/dist/es/scroll-bar.js +1 -1
  65. package/dist/es/segmented-control-item.js +1 -1
  66. package/dist/es/segmented-control.js +1 -1
  67. package/dist/es/select-content.js +1 -1
  68. package/dist/es/select-item.js +1 -1
  69. package/dist/es/select-trigger.js +1 -1
  70. package/dist/es/select-value.js +1 -1
  71. package/dist/es/social-button.js +1 -1
  72. package/dist/es/tab-menu-content.js +1 -1
  73. package/dist/es/tab-menu-item.js +1 -1
  74. package/dist/es/tab-menu-list.js +1 -1
  75. package/dist/es/tab-menu.js +1 -1
  76. package/dist/es/tag.js +1 -1
  77. package/dist/es/text-input.js +1 -1
  78. package/dist/es/tooltip.js +1 -1
  79. package/package.json +3 -3
  80. package/src/components/counter-input/counter-input.vue +131 -0
  81. package/src/components/counter-input/index.ts +2 -0
  82. package/src/components/counter-input/stories/counter-input.stories.ts +149 -0
  83. package/src/components/digit-input/stories/digit-input.stories.ts +1 -1
  84. package/src/components/index.ts +1 -0
  85. package/src/components/modal/modal-header.vue +1 -1
  86. package/src/components/radio-group/index.ts +6 -0
  87. package/src/components/radio-group/radio-group-card.vue +221 -0
  88. package/src/components/radio-group/radio-group-label.vue +108 -0
  89. package/src/components/radio-group/stories/radio-group-card.stories.ts +297 -0
  90. package/src/components/radio-group/stories/radio-group.stories.ts +25 -15
  91. package/src/components/text-input/stories/text-input.stories.ts +1 -1
@@ -5,7 +5,7 @@ import DigitInputSlot from '../digit-input-slot.vue';
5
5
  import DigitInput from '../digit-input.vue';
6
6
 
7
7
  const meta: Meta<typeof DigitInput> = {
8
- title: 'Components/DigitInput',
8
+ title: 'Components/Input/Digit Input',
9
9
  component: DigitInput,
10
10
  argTypes: {
11
11
  modelValue: {
@@ -4,6 +4,7 @@ export * from './button';
4
4
  export * from './checkbox';
5
5
  export * from './combobox';
6
6
  export * from './content-divider';
7
+ export * from './counter-input';
7
8
  export * from './digit-input';
8
9
  export * from './dropdown';
9
10
  export * from './dropdown-menu';
@@ -57,7 +57,7 @@ const props = withDefaults(defineProps<{
57
57
 
58
58
  display: flex;
59
59
  gap: var(--spacing-14);
60
- align-items: center;
60
+ align-items: flex-start;
61
61
  justify-content: space-between;
62
62
  padding: var(--spacing-16);
63
63
  border-block-end: 1px solid var(--color-stroke-soft-200);
@@ -1,5 +1,11 @@
1
+ export * from './radio-group-card.vue';
2
+ export { default as RadioGroupCard } from './radio-group-card.vue';
3
+
1
4
  export * from './radio-group-item.vue';
2
5
  export { default as RadioGroupItem } from './radio-group-item.vue';
3
6
 
7
+ export * from './radio-group-label.vue';
8
+ export { default as RadioGroupLabel } from './radio-group-label.vue';
9
+
4
10
  export * from './radio-group.vue';
5
11
  export { default as RadioGroup } from './radio-group.vue';
@@ -0,0 +1,221 @@
1
+ <script setup lang="ts">
2
+ import type { LabelProps } from 'radix-vue';
3
+ import type { HTMLAttributes } from 'vue';
4
+ import { useDelegatedProps } from '@/composables/use-delegated-props';
5
+ import clsx from 'clsx';
6
+ import { Label, Primitive } from 'radix-vue';
7
+
8
+ const props = defineProps<LabelProps & {
9
+ required?: boolean;
10
+ disabled?: boolean;
11
+ class?: HTMLAttributes['class'];
12
+ }>();
13
+
14
+ const delegatedProps = useDelegatedProps(props, 'class');
15
+ </script>
16
+
17
+ <template>
18
+ <Label
19
+ v-bind="delegatedProps"
20
+ :aria-required="required"
21
+ :aria-disabled="disabled"
22
+ :class="
23
+ clsx('celeste-radio-card', props.class, {
24
+ 'celeste-radio-card-disabled': disabled,
25
+ })
26
+ "
27
+ >
28
+ <div
29
+ v-if="$slots.image || $slots.icon"
30
+ role="presentation"
31
+ class="celeste-radio-card-preview"
32
+ :class="[$slots.image ? 'celeste-radio-card-preview-image' : 'celeste-radio-card-preview-icon']"
33
+ >
34
+ <template v-if="$slots.image">
35
+ <i class="celeste-radio-card-preview-fallback" i-celeste-image-circle-fill />
36
+ <slot class="i-celeste-image-circle-fill?bg" name="image" />
37
+ </template>
38
+
39
+ <template v-else-if="$slots.icon">
40
+ <slot name="icon" />
41
+ </template>
42
+ </div>
43
+
44
+ <div class="celeste-radio-card-content">
45
+ <div role="presentation">
46
+ <div role="presentation" class="celeste-radio-card-row">
47
+ <Primitive as="span" class="celeste-radio-card-label">
48
+ <slot name="label" />
49
+ </Primitive>
50
+
51
+ <Primitive
52
+ v-if="$slots.sublabel"
53
+ as="span"
54
+ class="celeste-radio-card-sublabel"
55
+ >
56
+ <slot name="sublabel" />
57
+ </Primitive>
58
+ <Primitive
59
+ v-if="$slots.badge"
60
+ as-child
61
+ class="celeste-radio-card-badge"
62
+ >
63
+ <slot :disabled="disabled" name="badge" />
64
+ </Primitive>
65
+ </div>
66
+ </div>
67
+
68
+ <Primitive
69
+ v-if="$slots.description"
70
+ as="span"
71
+ class="celeste-radio-card-description"
72
+ >
73
+ <slot name="description" />
74
+ </Primitive>
75
+ </div>
76
+
77
+ <Primitive
78
+ :disabled="disabled"
79
+ as-child
80
+ class="celeste-radio-card-radio"
81
+ >
82
+ <slot />
83
+ </Primitive>
84
+
85
+ </Label>
86
+ </template>
87
+
88
+ <style lang="scss" scoped>
89
+ * {
90
+ box-sizing: border-box;
91
+ }
92
+
93
+ .celeste-radio-card {
94
+ display: flex;
95
+ align-items: flex-start;
96
+ padding: var(--spacing-16);
97
+ transition: all var(--animation-fast) ease-out;
98
+ border: 1px solid var(--color-stroke-soft-200);
99
+ border-radius: var(--radius-12);
100
+ background-color: var(--color-bg-white-0);
101
+ box-shadow: var(--shadow-regular-xs);
102
+ color: var(--color-text-strong-950);
103
+ font: var(--paragraph-sm);
104
+ gap: var(--spacing-14);
105
+
106
+ &:not(.celeste-radio-card-disabled) {
107
+ cursor: pointer;
108
+ }
109
+
110
+ &:has([data-state='checked']):not(.celeste-radio-card-disabled) {
111
+ border-color: var(--color-primary-base);
112
+ box-shadow: none;
113
+ }
114
+
115
+ &:hover:not(.celeste-radio-card-disabled),
116
+ &:focus-visible:not(.celeste-radio-card-disabled) {
117
+ background-color: var(--color-bg-weak-50);
118
+ box-shadow: none;
119
+
120
+ &:not(:has([data-state='checked'])) {
121
+ border-color: transparent;
122
+ }
123
+ }
124
+ }
125
+
126
+ .celeste-radio-card-preview {
127
+ display: flex;
128
+ position: relative;
129
+ flex-shrink: 0;
130
+ align-items: center;
131
+ justify-content: center;
132
+ width: 40px;
133
+ height: 40px;
134
+ overflow: hidden;
135
+ border: 1px solid var(--color-stroke-soft-200);
136
+ border-radius: var(--radius-full);
137
+ background-color: var(--color-bg-white-0);
138
+ box-shadow: var(--shadow-regular-xs);
139
+ }
140
+
141
+ .celeste-radio-card-preview-icon {
142
+ i {
143
+ width: 20px;
144
+ height: 20px;
145
+ color: var(--color-icon-sub-600);
146
+ }
147
+ }
148
+
149
+ .celeste-radio-card-preview-image {
150
+ border: none;
151
+
152
+ i {
153
+ position: absolute;
154
+ z-index: 0;
155
+ top: 50%;
156
+ left: 50%;
157
+ width: 20px;
158
+ height: 20px;
159
+ transform: translate(-50%, -50%);
160
+ color: var(--color-icon-sub-600);
161
+ }
162
+
163
+ :deep(img) {
164
+ z-index: 1000;
165
+ }
166
+ }
167
+
168
+ .celeste-radio-card-content {
169
+ display: flex;
170
+ flex-direction: column;
171
+ gap: var(--spacing-4);
172
+ }
173
+
174
+ .celeste-radio-card-row {
175
+ display: flex;
176
+ flex-shrink: 1;
177
+ align-items: center;
178
+ gap: var(--spacing-8);
179
+ }
180
+
181
+ .celeste-radio-card-label {
182
+ flex-shrink: 1;
183
+ min-width: 0;
184
+ overflow: hidden;
185
+ color: var(--color-text-strong-950);
186
+ font: var(--label-sm);
187
+ text-overflow: ellipsis;
188
+ white-space: nowrap;
189
+ }
190
+
191
+ .celeste-radio-card-sublabel {
192
+ flex-shrink: 1;
193
+ min-width: 0;
194
+ overflow: hidden;
195
+ color: var(--color-text-sub-600);
196
+ font: var(--paragraph-xs);
197
+ text-overflow: ellipsis;
198
+ white-space: nowrap;
199
+ }
200
+
201
+ .celeste-radio-card-description {
202
+ color: var(--color-text-sub-600);
203
+ font: var(--paragraph-xs);
204
+ }
205
+
206
+ .celeste-radio-card-disabled {
207
+ cursor: not-allowed;
208
+
209
+ .celeste-radio-card-label {
210
+ color: var(--color-text-sub-600);
211
+ }
212
+
213
+ .celeste-radio-card-sublabel {
214
+ color: var(--color-text-soft-400);
215
+ }
216
+
217
+ .celeste-radio-card-description {
218
+ color: var(--color-text-soft-400);
219
+ }
220
+ }
221
+ </style>
@@ -0,0 +1,108 @@
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 { Label, type LabelProps, Primitive } from 'radix-vue';
6
+
7
+ const props = defineProps<LabelProps & {
8
+ required?: boolean;
9
+ disabled?: boolean;
10
+ class?: HTMLAttributes['class'];
11
+ }>();
12
+
13
+ const delegatedProps = useDelegatedProps(props, 'class');
14
+ </script>
15
+
16
+ <template>
17
+ <Label
18
+ v-bind="delegatedProps"
19
+ :aria-required="required"
20
+ :aria-disabled="disabled"
21
+ :class="clsx('celeste-radio-label', props.class)"
22
+ >
23
+ <Primitive as-child class="celeste-radio-label-radio">
24
+ <slot />
25
+ </Primitive>
26
+
27
+ <div role="presentation">
28
+ <div role="presentation" class="celeste-radio-label-row">
29
+ <div>
30
+ <Primitive as="span" class="celeste-radio-label-label">
31
+ <slot name="label" />
32
+ </Primitive>
33
+
34
+ <Primitive
35
+ v-if="$slots.sublabel"
36
+ as="span"
37
+ class="celeste-radio-label-sublabel"
38
+ >
39
+ <slot name="sublabel" />
40
+ </Primitive>
41
+ </div>
42
+
43
+ <Primitive
44
+ v-if="$slots.badge"
45
+ as-child
46
+ class="celeste-radio-label-badge"
47
+ >
48
+ <slot name="badge" />
49
+ </Primitive>
50
+ </div>
51
+
52
+ <div role="presentation" class="celeste-radio-label-content">
53
+ <Primitive
54
+ v-if="$slots.description"
55
+ as="span"
56
+ class="celeste-radio-label-description"
57
+ >
58
+ <slot name="description" />
59
+ </Primitive>
60
+
61
+ <Primitive
62
+ v-if="$slots.linkButton"
63
+ as-child
64
+ class="celeste-radio-label-link-button"
65
+ >
66
+ <slot name="linkButton" />
67
+ </Primitive>
68
+ </div>
69
+ </div>
70
+ </Label>
71
+ </template>
72
+
73
+ <style scoped lang="scss">
74
+ .celeste-radio-label {
75
+ display: flex;
76
+ color: var(--color-text-strong-950);
77
+ font: var(--paragraph-sm);
78
+ gap: var(--spacing-8);
79
+ }
80
+
81
+ :deep(.celeste-radio-label-radio) {
82
+ margin-top: var(--spacing-2);
83
+ }
84
+
85
+ .celeste-radio-label-row {
86
+ display: flex;
87
+ align-items: center;
88
+ gap: var(--spacing-8);
89
+ }
90
+
91
+ .celeste-radio-label-sublabel {
92
+ color: var(--color-text-sub-600);
93
+ font: var(--paragraph-xs);
94
+ }
95
+
96
+ .celeste-radio-label-content {
97
+ display: flex;
98
+ flex-direction: column;
99
+ align-items: flex-start;
100
+ margin-top: var(--spacing-4);
101
+ color: var(--color-text-sub-600);
102
+ font: var(--paragraph-xs);
103
+ }
104
+
105
+ .celeste-radio-label-link-button {
106
+ margin-top: var(--spacing-10);
107
+ }
108
+ </style>
@@ -0,0 +1,297 @@
1
+ // @unocss-include
2
+
3
+ import type { Meta, StoryObj } from '@storybook/vue3-vite';
4
+ import Badge from '@/components/badge/badge.vue';
5
+ import { ref } from 'vue';
6
+ import RadioGroupCard from '../radio-group-card.vue';
7
+ import RadioGroupItem from '../radio-group-item.vue';
8
+ import RadioGroup from '../radio-group.vue';
9
+
10
+ const meta: Meta<typeof RadioGroupCard> = {
11
+ title: 'Components/Radio Group/RadioGroupCard',
12
+ component: RadioGroupCard,
13
+ };
14
+
15
+ export default meta;
16
+
17
+ type Story = StoryObj<typeof RadioGroupCard>;
18
+
19
+ export const Default: Story = {
20
+ args: {},
21
+
22
+ render: args => ({
23
+ components: { RadioGroup, RadioGroupCard, RadioGroupItem },
24
+ setup() {
25
+ const selectedValue = ref();
26
+ return { args, selectedValue };
27
+ },
28
+ template: `
29
+ <div style="display: flex; justify-content: center;">
30
+ <div style="max-width: 400px;">
31
+ <RadioGroup v-model="selectedValue">
32
+ <RadioGroupCard v-bind="args">
33
+ <RadioGroupItem value="option1" />
34
+
35
+ <template #label>
36
+ Basic Label
37
+ </template>
38
+ </RadioGroupCard>
39
+ </RadioGroup>
40
+ <div style="margin-top: 16px; padding: 12px; background: #f5f5f5; border-radius: 8px; font-family: monospace;">
41
+ <strong>Selected:</strong> {{ selectedValue ? selectedValue : 'None' }}
42
+ </div>
43
+ </div>
44
+ </div>
45
+ `,
46
+ }),
47
+ };
48
+
49
+ export const WithIcon: Story = {
50
+ args: {},
51
+
52
+ render: args => ({
53
+ components: { RadioGroup, RadioGroupCard, RadioGroupItem },
54
+ setup() {
55
+ const selectedValue = ref();
56
+ return { args, selectedValue };
57
+ },
58
+ template: `
59
+ <div style="display: flex; justify-content: center;">
60
+ <div style="max-width: 400px;">
61
+ <RadioGroup v-model="selectedValue">
62
+ <RadioGroupCard v-bind="args">
63
+ <RadioGroupItem value="option1" />
64
+
65
+ <template #icon>
66
+ <i i-celeste-user-6-line />
67
+ </template>
68
+
69
+ <template #label>
70
+ Settings
71
+ </template>
72
+
73
+ <template #sublabel>
74
+ (Configure options)
75
+ </template>
76
+
77
+ <template #description>
78
+ Customize your application settings and preferences.
79
+ </template>
80
+ </RadioGroupCard>
81
+ </RadioGroup>
82
+ <div style="margin-top: 16px; padding: 12px; background: #f5f5f5; border-radius: 8px; font-family: monospace;">
83
+ <strong>Selected:</strong> {{ selectedValue ? selectedValue : 'None' }}
84
+ </div>
85
+ </div>
86
+ </div>
87
+ `,
88
+ }),
89
+ };
90
+
91
+ export const WithImage: Story = {
92
+ args: {},
93
+
94
+ render: args => ({
95
+ components: { RadioGroup, RadioGroupCard, RadioGroupItem },
96
+ setup() {
97
+ const selectedValue = ref();
98
+ return { args, selectedValue };
99
+ },
100
+ template: `
101
+ <div style="display: flex; justify-content: center;">
102
+ <div style="max-width: 400px;">
103
+ <RadioGroup v-model="selectedValue">
104
+ <RadioGroupCard v-bind="args">
105
+ <RadioGroupItem value="option1" />
106
+
107
+ <template #image>
108
+ <img src="https://placehold.co/48" alt="Preview" />
109
+ </template>
110
+
111
+ <template #label>
112
+ Image Option
113
+ </template>
114
+
115
+ <template #description>
116
+ An option with an image preview.
117
+ </template>
118
+ </RadioGroupCard>
119
+ </RadioGroup>
120
+ <div style="margin-top: 16px; padding: 12px; background: #f5f5f5; border-radius: 8px; font-family: monospace;">
121
+ <strong>Selected:</strong> {{ selectedValue ? selectedValue : 'None' }}
122
+ </div>
123
+ </div>
124
+ </div>
125
+ `,
126
+ }),
127
+ };
128
+
129
+ export const WithBadge: Story = {
130
+ args: {},
131
+
132
+ render: args => ({
133
+ components: { RadioGroup, RadioGroupCard, RadioGroupItem, Badge },
134
+ setup() {
135
+ const selectedValue = ref();
136
+ return { args, selectedValue };
137
+ },
138
+ template: `
139
+ <div style="display: flex; justify-content: center;">
140
+ <div style="max-width: 400px;">
141
+ <RadioGroup v-model="selectedValue">
142
+ <RadioGroupCard v-bind="args">
143
+ <RadioGroupItem value="option1" />
144
+
145
+ <template #label>
146
+ Label
147
+ </template>
148
+
149
+ <template #sublabel>
150
+ (Sublabel)
151
+ </template>
152
+
153
+ <template #badge>
154
+ <Badge
155
+ label="NEW"
156
+ state="information"
157
+ variant="light"
158
+ size="sm"
159
+ />
160
+ </template>
161
+
162
+ <template #description>
163
+ Access premium features with advanced capabilities.
164
+ </template>
165
+ </RadioGroupCard>
166
+ </RadioGroup>
167
+ <div style="margin-top: 16px; padding: 12px; background: #f5f5f5; border-radius: 8px; font-family: monospace;">
168
+ <strong>Selected:</strong> {{ selectedValue ? selectedValue : 'None' }}
169
+ </div>
170
+ </div>
171
+ </div>
172
+ `,
173
+ }),
174
+ };
175
+
176
+ export const Disabled: Story = {
177
+ args: {
178
+ disabled: true,
179
+ },
180
+
181
+ render: args => ({
182
+ components: { RadioGroup, RadioGroupCard, RadioGroupItem, Badge },
183
+ setup() {
184
+ const selectedValue = ref();
185
+ return { args, selectedValue };
186
+ },
187
+ template: `
188
+ <div style="display: flex; justify-content: center;">
189
+ <div style="max-width: 400px;">
190
+ <RadioGroup v-model="selectedValue">
191
+ <RadioGroupCard v-bind="args">
192
+ <RadioGroupItem value="option1" disabled />
193
+
194
+ <template #icon>
195
+ <i i-celeste-lock-line />
196
+ </template>
197
+
198
+ <template #label>
199
+ Disabled Option
200
+ </template>
201
+
202
+ <template #description>
203
+ This option is currently disabled and cannot be selected.
204
+ </template>
205
+ </RadioGroupCard>
206
+ </RadioGroup>
207
+ <div style="margin-top: 16px; padding: 12px; background: #f5f5f5; border-radius: 8px; font-family: monospace;">
208
+ <strong>Selected:</strong> {{ selectedValue ? selectedValue : 'None' }}
209
+ </div>
210
+ </div>
211
+ </div>
212
+ `,
213
+ }),
214
+ };
215
+
216
+ export const Multiple: Story = {
217
+ args: {},
218
+
219
+ render: args => ({
220
+ components: { RadioGroup, RadioGroupCard, RadioGroupItem, Badge },
221
+ setup() {
222
+ const selectedValue = ref();
223
+ return { args, selectedValue };
224
+ },
225
+ template: `
226
+ <div style="display: flex; justify-content: center;">
227
+ <div style="max-width: 400px; display: flex; flex-direction: column; gap: 1rem;">
228
+ <RadioGroup v-model="selectedValue">
229
+ <RadioGroupCard v-bind="args">
230
+ <RadioGroupItem value="email" />
231
+
232
+ <template #icon>
233
+ <i i-celeste-mail-line />
234
+ </template>
235
+
236
+ <template #label>
237
+ Email Notifications
238
+ </template>
239
+
240
+ <template #description>
241
+ Receive updates via email.
242
+ </template>
243
+ </RadioGroupCard>
244
+
245
+ <RadioGroupCard v-bind="args">
246
+ <RadioGroupItem value="push" />
247
+
248
+ <template #icon>
249
+ <i i-celeste-notification-line />
250
+ </template>
251
+
252
+ <template #label>
253
+ Push Notifications
254
+ </template>
255
+
256
+ <template #badge>
257
+ <Badge
258
+ label="RECOMMENDED"
259
+ state="success"
260
+ variant="light"
261
+ size="sm"
262
+ />
263
+ </template>
264
+
265
+ <template #description>
266
+ Get instant push notifications on your device.
267
+ </template>
268
+ </RadioGroupCard>
269
+
270
+ <RadioGroupCard v-bind="args">
271
+ <RadioGroupItem value="sms" />
272
+
273
+ <template #icon>
274
+ <i i-celeste-message-line />
275
+ </template>
276
+
277
+ <template #label>
278
+ SMS Notifications
279
+ </template>
280
+
281
+ <template #sublabel>
282
+ (Required)
283
+ </template>
284
+
285
+ <template #description>
286
+ Receive notifications via SMS text messages.
287
+ </template>
288
+ </RadioGroupCard>
289
+ </RadioGroup>
290
+ <div style="margin-top: 16px; padding: 12px; background: #f5f5f5; border-radius: 8px; font-family: monospace;">
291
+ <strong>Selected:</strong> {{ selectedValue ? selectedValue : 'None' }}
292
+ </div>
293
+ </div>
294
+ </div>
295
+ `,
296
+ }),
297
+ };