@aleph-alpha/ui-library 1.16.1 → 1.17.0
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/system/index.d.ts +585 -402
- package/dist/system/lib.js +13060 -12822
- package/package.json +2 -2
- package/src/components/UiChip/UiChip.stories.ts +239 -0
- package/src/components/UiChip/UiChip.vue +128 -0
- package/src/components/UiChip/__tests__/UiChip.test.ts +102 -0
- package/src/components/UiChip/index.ts +2 -0
- package/src/components/UiChip/types.ts +50 -0
- package/src/components/UiDropdownMenu/UiDropdownMenu.stories.ts +259 -1
- package/src/components/UiField/UiField.stories.ts +589 -249
- package/src/components/UiField/UiField.vue +87 -2
- package/src/components/UiField/UiFieldDescription.vue +22 -1
- package/src/components/UiField/UiFieldLabel.vue +2 -0
- package/src/components/UiField/UiFieldLabelInfo.vue +22 -0
- package/src/components/UiField/index.ts +1 -0
- package/src/components/UiField/keys.ts +5 -0
- package/src/components/UiField/types.ts +86 -1
- package/src/components/UiSelect/__tests__/UiSelectTrigger.test.ts +47 -2
- package/src/components/UiToggle/UiToggle.stories.ts +54 -1
- package/src/components/UiToggle/__tests__/UiToggle.test.ts +15 -0
- package/src/components/UiToggle/types.ts +1 -1
- package/src/components/UiToggleGroup/__tests__/UiToggleGroup.test.ts +21 -0
- package/src/components/UiToggleGroup/types.ts +2 -2
- package/src/components/core/button/index.ts +5 -0
- package/src/components/core/field/FieldLabel.vue +1 -1
- package/src/components/core/field/index.ts +5 -5
- package/src/components/core/select/SelectTrigger.vue +1 -1
- package/src/components/core/toggle/Toggle.vue +3 -3
- package/src/components/core/toggle/index.ts +6 -3
- package/src/components/core/toggle-group/index.ts +6 -3
- package/src/components/index.ts +1 -0
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
UiFieldTitle,
|
|
13
13
|
} from '.';
|
|
14
14
|
import { UiCheckbox } from '../UiCheckbox';
|
|
15
|
+
import { UiChip } from '../UiChip';
|
|
16
|
+
import { UiIcon } from '../UiIcon';
|
|
15
17
|
import { UiInput } from '../UiInput';
|
|
16
18
|
import { UiRadioGroup, UiRadioGroupItem } from '../UiRadioGroup';
|
|
17
19
|
import {
|
|
@@ -38,13 +40,24 @@ const meta: Meta<typeof UiField> = {
|
|
|
38
40
|
argTypes: {
|
|
39
41
|
orientation: {
|
|
40
42
|
control: 'select',
|
|
41
|
-
options: ['vertical', '
|
|
43
|
+
options: ['vertical', 'responsive'],
|
|
42
44
|
description:
|
|
43
45
|
'Layout orientation of the field. Use `responsive` to switch layout based on viewport size.',
|
|
44
46
|
},
|
|
47
|
+
descriptionPlacement: {
|
|
48
|
+
control: 'select',
|
|
49
|
+
options: ['under-label', 'under-input'],
|
|
50
|
+
description: 'Where the description is placed relative to the field layout.',
|
|
51
|
+
},
|
|
52
|
+
descriptionCheckbox: {
|
|
53
|
+
control: 'boolean',
|
|
54
|
+
description: 'When true, the child UiFieldDescription renders with a checkbox.',
|
|
55
|
+
},
|
|
45
56
|
},
|
|
46
57
|
args: {
|
|
47
58
|
orientation: 'vertical',
|
|
59
|
+
descriptionPlacement: 'under-input',
|
|
60
|
+
descriptionCheckbox: false,
|
|
48
61
|
},
|
|
49
62
|
};
|
|
50
63
|
|
|
@@ -97,11 +110,15 @@ export const Default: Story = {
|
|
|
97
110
|
return { args, value, errors };
|
|
98
111
|
},
|
|
99
112
|
template: `
|
|
100
|
-
<UiField
|
|
113
|
+
<UiField
|
|
114
|
+
:orientation="args.orientation"
|
|
115
|
+
:description-placement="args.descriptionPlacement"
|
|
116
|
+
:description-checkbox="args.descriptionCheckbox"
|
|
117
|
+
>
|
|
101
118
|
<UiFieldLabel for="email">Email</UiFieldLabel>
|
|
119
|
+
<UiFieldDescription>We'll never share your email.</UiFieldDescription>
|
|
102
120
|
<UiFieldContent>
|
|
103
121
|
<UiInput id="email" v-model="value" name="email" placeholder="name@company.com" />
|
|
104
|
-
<UiFieldDescription>We'll never share your email.</UiFieldDescription>
|
|
105
122
|
<UiFieldError :errors="errors" />
|
|
106
123
|
</UiFieldContent>
|
|
107
124
|
</UiField>
|
|
@@ -112,6 +129,127 @@ export const Default: Story = {
|
|
|
112
129
|
},
|
|
113
130
|
};
|
|
114
131
|
|
|
132
|
+
const descriptionWithCheckboxTemplateSource = `<script setup lang="ts">
|
|
133
|
+
import { ref } from 'vue'
|
|
134
|
+
import {
|
|
135
|
+
UiField,
|
|
136
|
+
UiFieldLabel,
|
|
137
|
+
UiFieldContent,
|
|
138
|
+
UiFieldDescription,
|
|
139
|
+
UiInput,
|
|
140
|
+
} from '@aleph-alpha/ui-library'
|
|
141
|
+
|
|
142
|
+
const value = ref('')
|
|
143
|
+
const subscribe = ref(false)
|
|
144
|
+
</script>
|
|
145
|
+
|
|
146
|
+
<template>
|
|
147
|
+
<UiField>
|
|
148
|
+
<UiFieldLabel for="email">Email</UiFieldLabel>
|
|
149
|
+
<UiFieldContent>
|
|
150
|
+
<UiInput id="email" v-model="value" name="email" placeholder="name@company.com" />
|
|
151
|
+
<UiFieldDescription variant="input" v-model="subscribe" name="newsletter">
|
|
152
|
+
Subscribe to our newsletter
|
|
153
|
+
</UiFieldDescription>
|
|
154
|
+
</UiFieldContent>
|
|
155
|
+
</UiField>
|
|
156
|
+
</template>`;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Description with an inline checkbox (`variant="input"`).
|
|
160
|
+
* Useful for opt-in toggles tied to a field (e.g. newsletter subscription, terms agreement).
|
|
161
|
+
*/
|
|
162
|
+
export const DescriptionWithCheckbox: Story = {
|
|
163
|
+
render: () => ({
|
|
164
|
+
components: {
|
|
165
|
+
UiField,
|
|
166
|
+
UiFieldContent,
|
|
167
|
+
UiFieldDescription,
|
|
168
|
+
UiFieldLabel,
|
|
169
|
+
UiInput,
|
|
170
|
+
},
|
|
171
|
+
setup() {
|
|
172
|
+
const value = ref('');
|
|
173
|
+
const subscribe = ref(false);
|
|
174
|
+
return { value, subscribe };
|
|
175
|
+
},
|
|
176
|
+
template: `
|
|
177
|
+
<UiField>
|
|
178
|
+
<UiFieldLabel for="email">Email</UiFieldLabel>
|
|
179
|
+
<UiFieldContent>
|
|
180
|
+
<UiInput id="email" v-model="value" name="email" placeholder="name@company.com" />
|
|
181
|
+
<UiFieldDescription variant="input" v-model="subscribe" name="newsletter">
|
|
182
|
+
Subscribe to our newsletter
|
|
183
|
+
</UiFieldDescription>
|
|
184
|
+
</UiFieldContent>
|
|
185
|
+
</UiField>
|
|
186
|
+
`,
|
|
187
|
+
}),
|
|
188
|
+
parameters: {
|
|
189
|
+
controls: { disable: true },
|
|
190
|
+
docs: { source: { code: descriptionWithCheckboxTemplateSource } },
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
const withLabelInfoTemplateSource = `<script setup lang="ts">
|
|
195
|
+
import { ref } from 'vue'
|
|
196
|
+
import {
|
|
197
|
+
UiField,
|
|
198
|
+
UiFieldLabel,
|
|
199
|
+
UiFieldContent,
|
|
200
|
+
UiFieldDescription,
|
|
201
|
+
UiInput,
|
|
202
|
+
} from '@aleph-alpha/ui-library'
|
|
203
|
+
|
|
204
|
+
const value = ref('')
|
|
205
|
+
</script>
|
|
206
|
+
|
|
207
|
+
<template>
|
|
208
|
+
<UiField>
|
|
209
|
+
<UiFieldLabel for="api-key" tooltip="Your unique API key for authentication.">
|
|
210
|
+
API Key
|
|
211
|
+
</UiFieldLabel>
|
|
212
|
+
<UiFieldContent>
|
|
213
|
+
<UiInput id="api-key" v-model="value" name="apiKey" placeholder="sk-..." />
|
|
214
|
+
<UiFieldDescription>Keep this secret and do not share it.</UiFieldDescription>
|
|
215
|
+
</UiFieldContent>
|
|
216
|
+
</UiField>
|
|
217
|
+
</template>`;
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Label with an interactive info tooltip icon.
|
|
221
|
+
* Pass a `tooltip` prop to `UiFieldLabel` to render a ghost icon button with a tooltip.
|
|
222
|
+
*/
|
|
223
|
+
export const WithLabelInfo: Story = {
|
|
224
|
+
render: (args) => ({
|
|
225
|
+
components: {
|
|
226
|
+
UiField,
|
|
227
|
+
UiFieldContent,
|
|
228
|
+
UiFieldDescription,
|
|
229
|
+
UiFieldLabel,
|
|
230
|
+
UiInput,
|
|
231
|
+
},
|
|
232
|
+
setup() {
|
|
233
|
+
const value = ref('');
|
|
234
|
+
return { args, value };
|
|
235
|
+
},
|
|
236
|
+
template: `
|
|
237
|
+
<UiField :orientation="args.orientation">
|
|
238
|
+
<UiFieldLabel for="api-key" tooltip="Your unique API key for authentication.">
|
|
239
|
+
API Key
|
|
240
|
+
</UiFieldLabel>
|
|
241
|
+
<UiFieldContent>
|
|
242
|
+
<UiInput id="api-key" v-model="value" name="apiKey" placeholder="sk-..." />
|
|
243
|
+
<UiFieldDescription>Keep this secret and do not share it.</UiFieldDescription>
|
|
244
|
+
</UiFieldContent>
|
|
245
|
+
</UiField>
|
|
246
|
+
`,
|
|
247
|
+
}),
|
|
248
|
+
parameters: {
|
|
249
|
+
docs: { source: { code: withLabelInfoTemplateSource } },
|
|
250
|
+
},
|
|
251
|
+
};
|
|
252
|
+
|
|
115
253
|
const withErrorTemplateSource = `<script setup lang="ts">
|
|
116
254
|
import { ref } from 'vue'
|
|
117
255
|
import {
|
|
@@ -260,7 +398,157 @@ export const Group: Story = {
|
|
|
260
398
|
},
|
|
261
399
|
};
|
|
262
400
|
|
|
263
|
-
const
|
|
401
|
+
const chipGroupFieldTemplateSource = `<script setup lang="ts">
|
|
402
|
+
import { ref } from 'vue'
|
|
403
|
+
import {
|
|
404
|
+
UiChip,
|
|
405
|
+
UiField,
|
|
406
|
+
UiFieldContent,
|
|
407
|
+
UiFieldDescription,
|
|
408
|
+
UiFieldLabel,
|
|
409
|
+
UiIcon,
|
|
410
|
+
} from '@aleph-alpha/ui-library'
|
|
411
|
+
|
|
412
|
+
const chips = ref([
|
|
413
|
+
'Data Analysis',
|
|
414
|
+
'Report Generation',
|
|
415
|
+
'Workflow Automation',
|
|
416
|
+
'Predictive Modeling',
|
|
417
|
+
'Sentiment Analysis',
|
|
418
|
+
'Risk Management',
|
|
419
|
+
'Fraud Detection',
|
|
420
|
+
])
|
|
421
|
+
|
|
422
|
+
const selectedAddChip = ref(false)
|
|
423
|
+
|
|
424
|
+
const ChipIcon = {
|
|
425
|
+
components: { UiIcon },
|
|
426
|
+
template: '<UiIcon name="tag" :size="14" />',
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const AddIcon = {
|
|
430
|
+
components: { UiIcon },
|
|
431
|
+
template: '<UiIcon name="plus" :size="14" />',
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function removeChip(label: string) {
|
|
435
|
+
chips.value = chips.value.filter((chip) => chip !== label)
|
|
436
|
+
}
|
|
437
|
+
</script>
|
|
438
|
+
|
|
439
|
+
<template>
|
|
440
|
+
<UiField>
|
|
441
|
+
<UiFieldLabel for="focus-areas">Focus Areas</UiFieldLabel>
|
|
442
|
+
<UiFieldContent>
|
|
443
|
+
<div id="focus-areas" class="flex flex-wrap items-center gap-2">
|
|
444
|
+
<UiChip
|
|
445
|
+
v-for="chip in chips"
|
|
446
|
+
:key="chip"
|
|
447
|
+
variant="removable"
|
|
448
|
+
:start-icon="ChipIcon"
|
|
449
|
+
@remove="removeChip(chip)"
|
|
450
|
+
>
|
|
451
|
+
{{ chip }}
|
|
452
|
+
</UiChip>
|
|
453
|
+
|
|
454
|
+
<UiChip
|
|
455
|
+
v-model="selectedAddChip"
|
|
456
|
+
variant="removable"
|
|
457
|
+
selectable
|
|
458
|
+
:start-icon="AddIcon"
|
|
459
|
+
remove-label="Remove add action"
|
|
460
|
+
>
|
|
461
|
+
Add
|
|
462
|
+
</UiChip>
|
|
463
|
+
</div>
|
|
464
|
+
<UiFieldDescription>
|
|
465
|
+
Chip group inside a field. Use Tab to navigate interactive chip actions in order.
|
|
466
|
+
</UiFieldDescription>
|
|
467
|
+
</UiFieldContent>
|
|
468
|
+
</UiField>
|
|
469
|
+
</template>`;
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Field with a chip group value area (Figma chips-group style).
|
|
473
|
+
* Demonstrates removable chips and an interactive "Add" chip in a field context.
|
|
474
|
+
*/
|
|
475
|
+
export const ChipGroup: Story = {
|
|
476
|
+
render: () => ({
|
|
477
|
+
components: {
|
|
478
|
+
UiChip,
|
|
479
|
+
UiField,
|
|
480
|
+
UiFieldContent,
|
|
481
|
+
UiFieldDescription,
|
|
482
|
+
UiFieldLabel,
|
|
483
|
+
UiIcon,
|
|
484
|
+
},
|
|
485
|
+
setup() {
|
|
486
|
+
const chips = ref([
|
|
487
|
+
'Data Analysis',
|
|
488
|
+
'Report Generation',
|
|
489
|
+
'Workflow Automation',
|
|
490
|
+
'Predictive Modeling',
|
|
491
|
+
'Sentiment Analysis',
|
|
492
|
+
'Risk Management',
|
|
493
|
+
'Fraud Detection',
|
|
494
|
+
]);
|
|
495
|
+
const selectedAddChip = ref(false);
|
|
496
|
+
|
|
497
|
+
const ChipIcon = {
|
|
498
|
+
components: { UiIcon },
|
|
499
|
+
template: '<UiIcon name="tag" :size="14" />',
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
const AddIcon = {
|
|
503
|
+
components: { UiIcon },
|
|
504
|
+
template: '<UiIcon name="plus" :size="14" />',
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
function removeChip(label: string) {
|
|
508
|
+
chips.value = chips.value.filter((chip) => chip !== label);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
return { chips, selectedAddChip, ChipIcon, AddIcon, removeChip };
|
|
512
|
+
},
|
|
513
|
+
template: `
|
|
514
|
+
<UiField>
|
|
515
|
+
<UiFieldLabel for="focus-areas">Focus Areas</UiFieldLabel>
|
|
516
|
+
<UiFieldContent>
|
|
517
|
+
<div id="focus-areas" class="flex flex-wrap items-center gap-2">
|
|
518
|
+
<UiChip
|
|
519
|
+
v-for="chip in chips"
|
|
520
|
+
:key="chip"
|
|
521
|
+
variant="removable"
|
|
522
|
+
:start-icon="ChipIcon"
|
|
523
|
+
@remove="removeChip(chip)"
|
|
524
|
+
>
|
|
525
|
+
{{ chip }}
|
|
526
|
+
</UiChip>
|
|
527
|
+
|
|
528
|
+
<UiChip
|
|
529
|
+
v-model="selectedAddChip"
|
|
530
|
+
variant="removable"
|
|
531
|
+
selectable
|
|
532
|
+
:start-icon="AddIcon"
|
|
533
|
+
remove-label="Remove add action"
|
|
534
|
+
>
|
|
535
|
+
Add
|
|
536
|
+
</UiChip>
|
|
537
|
+
</div>
|
|
538
|
+
<UiFieldDescription>
|
|
539
|
+
Chip group inside a field. Use Tab to navigate interactive chip actions in order.
|
|
540
|
+
</UiFieldDescription>
|
|
541
|
+
</UiFieldContent>
|
|
542
|
+
</UiField>
|
|
543
|
+
`,
|
|
544
|
+
}),
|
|
545
|
+
parameters: {
|
|
546
|
+
controls: { disable: true },
|
|
547
|
+
docs: { source: { code: chipGroupFieldTemplateSource } },
|
|
548
|
+
},
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
const responsiveOrientationInlineTemplateSource = `<script setup lang="ts">
|
|
264
552
|
import { ref } from 'vue'
|
|
265
553
|
import {
|
|
266
554
|
UiField,
|
|
@@ -274,7 +562,7 @@ const value = ref('')
|
|
|
274
562
|
</script>
|
|
275
563
|
|
|
276
564
|
<template>
|
|
277
|
-
<UiField orientation="
|
|
565
|
+
<UiField orientation="responsive">
|
|
278
566
|
<UiFieldLabel for="username">Username</UiFieldLabel>
|
|
279
567
|
<UiFieldContent>
|
|
280
568
|
<UiInput id="username" v-model="value" name="username" placeholder="shadcn" />
|
|
@@ -284,11 +572,11 @@ const value = ref('')
|
|
|
284
572
|
</template>`;
|
|
285
573
|
|
|
286
574
|
/**
|
|
287
|
-
*
|
|
575
|
+
* Responsive layout: horizontal by default, collapses to vertical on small screens.
|
|
288
576
|
* Useful when you want labels aligned on the left and controls on the right.
|
|
289
577
|
*/
|
|
290
|
-
export const
|
|
291
|
-
args: { orientation: '
|
|
578
|
+
export const ResponsiveInline: Story = {
|
|
579
|
+
args: { orientation: 'responsive' },
|
|
292
580
|
render: (args) => ({
|
|
293
581
|
components: {
|
|
294
582
|
UiField,
|
|
@@ -312,7 +600,7 @@ export const HorizontalOrientation: Story = {
|
|
|
312
600
|
`,
|
|
313
601
|
}),
|
|
314
602
|
parameters: {
|
|
315
|
-
docs: { source: { code:
|
|
603
|
+
docs: { source: { code: responsiveOrientationInlineTemplateSource } },
|
|
316
604
|
},
|
|
317
605
|
};
|
|
318
606
|
|
|
@@ -652,7 +940,7 @@ const enabled = ref(true)
|
|
|
652
940
|
</script>
|
|
653
941
|
|
|
654
942
|
<template>
|
|
655
|
-
<UiField orientation="
|
|
943
|
+
<UiField orientation="responsive">
|
|
656
944
|
<UiCheckbox id="notifications" v-model="enabled" name="notifications" />
|
|
657
945
|
<UiFieldContent>
|
|
658
946
|
<UiFieldLabel for="notifications">Enable notifications</UiFieldLabel>
|
|
@@ -663,7 +951,7 @@ const enabled = ref(true)
|
|
|
663
951
|
|
|
664
952
|
/**
|
|
665
953
|
* Checkbox field layout (checkbox + text content).
|
|
666
|
-
* The checkbox is a direct child of `UiField` so the
|
|
954
|
+
* The checkbox is a direct child of `UiField` so the responsive styles can align it nicely.
|
|
667
955
|
*/
|
|
668
956
|
export const Checkbox: Story = {
|
|
669
957
|
render: () => ({
|
|
@@ -673,7 +961,7 @@ export const Checkbox: Story = {
|
|
|
673
961
|
return { enabled };
|
|
674
962
|
},
|
|
675
963
|
template: `
|
|
676
|
-
<UiField orientation="
|
|
964
|
+
<UiField orientation="responsive">
|
|
677
965
|
<UiCheckbox id="notifications" v-model="enabled" name="notifications" />
|
|
678
966
|
<UiFieldContent>
|
|
679
967
|
<UiFieldLabel for="notifications">Enable notifications</UiFieldLabel>
|
|
@@ -702,7 +990,7 @@ const enabled = ref(false)
|
|
|
702
990
|
</script>
|
|
703
991
|
|
|
704
992
|
<template>
|
|
705
|
-
<UiField orientation="
|
|
993
|
+
<UiField orientation="responsive">
|
|
706
994
|
<UiSwitch id="airplane" v-model="enabled" name="airplane" />
|
|
707
995
|
<UiFieldContent>
|
|
708
996
|
<UiFieldLabel for="airplane">Airplane mode</UiFieldLabel>
|
|
@@ -722,7 +1010,7 @@ export const Switch: Story = {
|
|
|
722
1010
|
return { enabled };
|
|
723
1011
|
},
|
|
724
1012
|
template: `
|
|
725
|
-
<UiField orientation="
|
|
1013
|
+
<UiField orientation="responsive">
|
|
726
1014
|
<UiSwitch id="airplane" v-model="enabled" name="airplane" />
|
|
727
1015
|
<UiFieldContent>
|
|
728
1016
|
<UiFieldLabel for="airplane">Airplane mode</UiFieldLabel>
|
|
@@ -761,7 +1049,7 @@ const plan = ref('pro')
|
|
|
761
1049
|
<UiFieldLegend variant="label">Choose your plan</UiFieldLegend>
|
|
762
1050
|
|
|
763
1051
|
<UiRadioGroup v-model="plan" name="plan">
|
|
764
|
-
<UiField orientation="
|
|
1052
|
+
<UiField orientation="responsive">
|
|
765
1053
|
<UiRadioGroupItem id="plan-free" value="free" />
|
|
766
1054
|
<UiFieldContent>
|
|
767
1055
|
<label for="plan-free" class="text-sm font-medium">Free</label>
|
|
@@ -769,7 +1057,7 @@ const plan = ref('pro')
|
|
|
769
1057
|
</UiFieldContent>
|
|
770
1058
|
</UiField>
|
|
771
1059
|
|
|
772
|
-
<UiField orientation="
|
|
1060
|
+
<UiField orientation="responsive">
|
|
773
1061
|
<UiRadioGroupItem id="plan-pro" value="pro" />
|
|
774
1062
|
<UiFieldContent>
|
|
775
1063
|
<label for="plan-pro" class="text-sm font-medium">Pro</label>
|
|
@@ -777,7 +1065,7 @@ const plan = ref('pro')
|
|
|
777
1065
|
</UiFieldContent>
|
|
778
1066
|
</UiField>
|
|
779
1067
|
|
|
780
|
-
<UiField orientation="
|
|
1068
|
+
<UiField orientation="responsive" data-disabled="true">
|
|
781
1069
|
<UiRadioGroupItem id="plan-enterprise" value="enterprise" disabled />
|
|
782
1070
|
<UiFieldContent>
|
|
783
1071
|
<label for="plan-enterprise" class="text-sm font-medium text-muted-foreground">Enterprise</label>
|
|
@@ -816,7 +1104,7 @@ export const RadioGroupInFieldSet: Story = {
|
|
|
816
1104
|
<UiFieldLegend variant="label">Choose your plan</UiFieldLegend>
|
|
817
1105
|
|
|
818
1106
|
<UiRadioGroup v-model="plan" name="plan">
|
|
819
|
-
<UiField orientation="
|
|
1107
|
+
<UiField orientation="responsive">
|
|
820
1108
|
<UiRadioGroupItem id="plan-free" value="free" />
|
|
821
1109
|
<UiFieldContent>
|
|
822
1110
|
<label for="plan-free" class="text-sm font-medium">Free</label>
|
|
@@ -824,7 +1112,7 @@ export const RadioGroupInFieldSet: Story = {
|
|
|
824
1112
|
</UiFieldContent>
|
|
825
1113
|
</UiField>
|
|
826
1114
|
|
|
827
|
-
<UiField orientation="
|
|
1115
|
+
<UiField orientation="responsive">
|
|
828
1116
|
<UiRadioGroupItem id="plan-pro" value="pro" />
|
|
829
1117
|
<UiFieldContent>
|
|
830
1118
|
<label for="plan-pro" class="text-sm font-medium">Pro</label>
|
|
@@ -832,7 +1120,7 @@ export const RadioGroupInFieldSet: Story = {
|
|
|
832
1120
|
</UiFieldContent>
|
|
833
1121
|
</UiField>
|
|
834
1122
|
|
|
835
|
-
<UiField orientation="
|
|
1123
|
+
<UiField orientation="responsive" data-disabled="true">
|
|
836
1124
|
<UiRadioGroupItem id="plan-enterprise" value="enterprise" disabled />
|
|
837
1125
|
<UiFieldContent>
|
|
838
1126
|
<label for="plan-enterprise" class="text-sm font-medium text-muted-foreground">Enterprise</label>
|
|
@@ -1006,14 +1294,14 @@ const email = ref(false)
|
|
|
1006
1294
|
</UiFieldDescription>
|
|
1007
1295
|
|
|
1008
1296
|
<UiFieldGroup data-slot="checkbox-group">
|
|
1009
|
-
<UiField orientation="
|
|
1297
|
+
<UiField orientation="responsive">
|
|
1010
1298
|
<UiCheckbox id="push-tasks" v-model="push" name="push-tasks" />
|
|
1011
1299
|
<UiFieldLabel for="push-tasks" class="font-normal">
|
|
1012
1300
|
Push notifications
|
|
1013
1301
|
</UiFieldLabel>
|
|
1014
1302
|
</UiField>
|
|
1015
1303
|
|
|
1016
|
-
<UiField orientation="
|
|
1304
|
+
<UiField orientation="responsive">
|
|
1017
1305
|
<UiCheckbox id="email-tasks" v-model="email" name="email-tasks" />
|
|
1018
1306
|
<UiFieldLabel for="email-tasks" class="font-normal">
|
|
1019
1307
|
Email notifications
|
|
@@ -1054,14 +1342,14 @@ export const CheckboxGroup: Story = {
|
|
|
1054
1342
|
</UiFieldDescription>
|
|
1055
1343
|
|
|
1056
1344
|
<UiFieldGroup data-slot="checkbox-group">
|
|
1057
|
-
<UiField orientation="
|
|
1345
|
+
<UiField orientation="responsive">
|
|
1058
1346
|
<UiCheckbox id="push-tasks" v-model="push" name="push-tasks" />
|
|
1059
1347
|
<UiFieldLabel for="push-tasks" class="font-normal">
|
|
1060
1348
|
Push notifications
|
|
1061
1349
|
</UiFieldLabel>
|
|
1062
1350
|
</UiField>
|
|
1063
1351
|
|
|
1064
|
-
<UiField orientation="
|
|
1352
|
+
<UiField orientation="responsive">
|
|
1065
1353
|
<UiCheckbox id="email-tasks" v-model="email" name="email-tasks" />
|
|
1066
1354
|
<UiFieldLabel for="email-tasks" class="font-normal">
|
|
1067
1355
|
Email notifications
|
|
@@ -1106,29 +1394,31 @@ const message = ref('')
|
|
|
1106
1394
|
<UiFieldDescription>Fill in your profile information.</UiFieldDescription>
|
|
1107
1395
|
<UiFieldSeparator />
|
|
1108
1396
|
<UiFieldGroup>
|
|
1109
|
-
<UiField orientation="responsive">
|
|
1397
|
+
<UiField orientation="responsive" description-placement="under-label">
|
|
1398
|
+
<UiFieldLabel for="profile-name" tooltip="Used on your public profile page.">
|
|
1399
|
+
Name
|
|
1400
|
+
</UiFieldLabel>
|
|
1401
|
+
<UiFieldDescription>Provide your full name for identification</UiFieldDescription>
|
|
1110
1402
|
<UiFieldContent>
|
|
1111
|
-
<
|
|
1112
|
-
<UiFieldDescription>Provide your full name for identification</UiFieldDescription>
|
|
1403
|
+
<UiInput id="profile-name" v-model="name" name="name" placeholder="Evil Rabbit" required />
|
|
1113
1404
|
</UiFieldContent>
|
|
1114
|
-
<UiInput id="profile-name" v-model="name" name="name" placeholder="Evil Rabbit" required />
|
|
1115
1405
|
</UiField>
|
|
1116
1406
|
<UiFieldSeparator />
|
|
1117
|
-
<UiField orientation="responsive">
|
|
1407
|
+
<UiField orientation="responsive" description-placement="under-label">
|
|
1408
|
+
<UiFieldLabel for="profile-message">Message</UiFieldLabel>
|
|
1409
|
+
<UiFieldDescription>
|
|
1410
|
+
You can write your message here. Keep it short, preferably under 100 characters.
|
|
1411
|
+
</UiFieldDescription>
|
|
1118
1412
|
<UiFieldContent>
|
|
1119
|
-
<
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1413
|
+
<UiTextarea
|
|
1414
|
+
id="profile-message"
|
|
1415
|
+
v-model="message"
|
|
1416
|
+
name="message"
|
|
1417
|
+
placeholder="Hello, world!"
|
|
1418
|
+
required
|
|
1419
|
+
class="min-h-[100px] resize-none sm:min-w-[300px]"
|
|
1420
|
+
/>
|
|
1123
1421
|
</UiFieldContent>
|
|
1124
|
-
<UiTextarea
|
|
1125
|
-
id="profile-message"
|
|
1126
|
-
v-model="message"
|
|
1127
|
-
name="message"
|
|
1128
|
-
placeholder="Hello, world!"
|
|
1129
|
-
required
|
|
1130
|
-
class="min-h-[100px] resize-none sm:min-w-[300px]"
|
|
1131
|
-
/>
|
|
1132
1422
|
</UiField>
|
|
1133
1423
|
<UiFieldSeparator />
|
|
1134
1424
|
<UiField orientation="responsive">
|
|
@@ -1143,7 +1433,8 @@ const message = ref('')
|
|
|
1143
1433
|
|
|
1144
1434
|
/**
|
|
1145
1435
|
* Full responsive form layout, mirroring the “Responsive Layout” example from shadcn-vue field docs.
|
|
1146
|
-
* Uses `
|
|
1436
|
+
* Uses `descriptionPlacement="under-label"` to group the label and description together,
|
|
1437
|
+
* and `tooltip` prop on `UiFieldLabel` for inline help.
|
|
1147
1438
|
*/
|
|
1148
1439
|
export const ResponsiveProfileForm: Story = {
|
|
1149
1440
|
render: () => ({
|
|
@@ -1173,29 +1464,31 @@ export const ResponsiveProfileForm: Story = {
|
|
|
1173
1464
|
<UiFieldDescription>Fill in your profile information.</UiFieldDescription>
|
|
1174
1465
|
<UiFieldSeparator />
|
|
1175
1466
|
<UiFieldGroup>
|
|
1176
|
-
<UiField orientation="responsive">
|
|
1467
|
+
<UiField orientation="responsive" description-placement="under-label">
|
|
1468
|
+
<UiFieldLabel for="profile-name" tooltip="Used on your public profile page.">
|
|
1469
|
+
Name
|
|
1470
|
+
</UiFieldLabel>
|
|
1471
|
+
<UiFieldDescription>Provide your full name for identification</UiFieldDescription>
|
|
1177
1472
|
<UiFieldContent>
|
|
1178
|
-
<
|
|
1179
|
-
<UiFieldDescription>Provide your full name for identification</UiFieldDescription>
|
|
1473
|
+
<UiInput id="profile-name" v-model="name" name="name" placeholder="Evil Rabbit" required />
|
|
1180
1474
|
</UiFieldContent>
|
|
1181
|
-
<UiInput id="profile-name" v-model="name" name="name" placeholder="Evil Rabbit" required />
|
|
1182
1475
|
</UiField>
|
|
1183
1476
|
<UiFieldSeparator />
|
|
1184
|
-
<UiField orientation="responsive">
|
|
1477
|
+
<UiField orientation="responsive" description-placement="under-label">
|
|
1478
|
+
<UiFieldLabel for="profile-message">Message</UiFieldLabel>
|
|
1479
|
+
<UiFieldDescription>
|
|
1480
|
+
You can write your message here. Keep it short, preferably under 100 characters.
|
|
1481
|
+
</UiFieldDescription>
|
|
1185
1482
|
<UiFieldContent>
|
|
1186
|
-
<
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1483
|
+
<UiTextarea
|
|
1484
|
+
id="profile-message"
|
|
1485
|
+
v-model="message"
|
|
1486
|
+
name="message"
|
|
1487
|
+
placeholder="Hello, world!"
|
|
1488
|
+
required
|
|
1489
|
+
class="min-h-[100px] resize-none sm:min-w-[300px]"
|
|
1490
|
+
/>
|
|
1190
1491
|
</UiFieldContent>
|
|
1191
|
-
<UiTextarea
|
|
1192
|
-
id="profile-message"
|
|
1193
|
-
v-model="message"
|
|
1194
|
-
name="message"
|
|
1195
|
-
placeholder="Hello, world!"
|
|
1196
|
-
required
|
|
1197
|
-
class="min-h-[100px] resize-none sm:min-w-[300px]"
|
|
1198
|
-
/>
|
|
1199
1492
|
</UiField>
|
|
1200
1493
|
<UiFieldSeparator />
|
|
1201
1494
|
<UiField orientation="responsive">
|
|
@@ -1214,146 +1507,11 @@ export const ResponsiveProfileForm: Story = {
|
|
|
1214
1507
|
},
|
|
1215
1508
|
};
|
|
1216
1509
|
|
|
1217
|
-
const checkoutPaymentFormTemplateSource = `<script setup lang="ts">
|
|
1218
|
-
import { ref } from 'vue'
|
|
1219
|
-
import {
|
|
1220
|
-
UiButton,
|
|
1221
|
-
UiCheckbox,
|
|
1222
|
-
UiField,
|
|
1223
|
-
UiFieldDescription,
|
|
1224
|
-
UiFieldGroup,
|
|
1225
|
-
UiFieldLabel,
|
|
1226
|
-
UiFieldLegend,
|
|
1227
|
-
UiFieldSeparator,
|
|
1228
|
-
UiFieldSet,
|
|
1229
|
-
UiInput,
|
|
1230
|
-
UiSelect,
|
|
1231
|
-
UiSelectContent,
|
|
1232
|
-
UiSelectItem,
|
|
1233
|
-
UiSelectTrigger,
|
|
1234
|
-
UiSelectValue,
|
|
1235
|
-
UiTextarea,
|
|
1236
|
-
} from '@aleph-alpha/ui-library'
|
|
1237
|
-
|
|
1238
|
-
const cardName = ref('')
|
|
1239
|
-
const cardNumber = ref('')
|
|
1240
|
-
const cvv = ref('')
|
|
1241
|
-
const month = ref('')
|
|
1242
|
-
const year = ref('')
|
|
1243
|
-
const sameAsShipping = ref(true)
|
|
1244
|
-
const comments = ref('')
|
|
1245
|
-
</script>
|
|
1246
|
-
|
|
1247
|
-
<template>
|
|
1248
|
-
<div class="w-full max-w-md">
|
|
1249
|
-
<form>
|
|
1250
|
-
<UiFieldGroup>
|
|
1251
|
-
<UiFieldSet>
|
|
1252
|
-
<UiFieldLegend>Payment Method</UiFieldLegend>
|
|
1253
|
-
<UiFieldDescription>All transactions are secure and encrypted</UiFieldDescription>
|
|
1254
|
-
|
|
1255
|
-
<UiFieldGroup>
|
|
1256
|
-
<UiField>
|
|
1257
|
-
<UiFieldLabel for="card-name">Name on Card</UiFieldLabel>
|
|
1258
|
-
<UiInput id="card-name" v-model="cardName" name="cardName" placeholder="Evil Rabbit" required />
|
|
1259
|
-
</UiField>
|
|
1260
|
-
|
|
1261
|
-
<UiField>
|
|
1262
|
-
<UiFieldLabel for="card-number">Card Number</UiFieldLabel>
|
|
1263
|
-
<UiInput id="card-number" v-model="cardNumber" name="cardNumber" placeholder="1234 5678 9012 3456" required />
|
|
1264
|
-
<UiFieldDescription>Enter your 16-digit card number</UiFieldDescription>
|
|
1265
|
-
</UiField>
|
|
1266
|
-
|
|
1267
|
-
<div class="grid grid-cols-3 gap-4">
|
|
1268
|
-
<UiField>
|
|
1269
|
-
<UiFieldLabel for="exp-month">Month</UiFieldLabel>
|
|
1270
|
-
<UiSelect v-model="month">
|
|
1271
|
-
<UiSelectTrigger id="exp-month">
|
|
1272
|
-
<UiSelectValue placeholder="MM" />
|
|
1273
|
-
</UiSelectTrigger>
|
|
1274
|
-
<UiSelectContent>
|
|
1275
|
-
<UiSelectItem value="01">01</UiSelectItem>
|
|
1276
|
-
<UiSelectItem value="02">02</UiSelectItem>
|
|
1277
|
-
<UiSelectItem value="03">03</UiSelectItem>
|
|
1278
|
-
<UiSelectItem value="04">04</UiSelectItem>
|
|
1279
|
-
<UiSelectItem value="05">05</UiSelectItem>
|
|
1280
|
-
<UiSelectItem value="06">06</UiSelectItem>
|
|
1281
|
-
<UiSelectItem value="07">07</UiSelectItem>
|
|
1282
|
-
<UiSelectItem value="08">08</UiSelectItem>
|
|
1283
|
-
<UiSelectItem value="09">09</UiSelectItem>
|
|
1284
|
-
<UiSelectItem value="10">10</UiSelectItem>
|
|
1285
|
-
<UiSelectItem value="11">11</UiSelectItem>
|
|
1286
|
-
<UiSelectItem value="12">12</UiSelectItem>
|
|
1287
|
-
</UiSelectContent>
|
|
1288
|
-
</UiSelect>
|
|
1289
|
-
</UiField>
|
|
1290
|
-
|
|
1291
|
-
<UiField>
|
|
1292
|
-
<UiFieldLabel for="exp-year">Year</UiFieldLabel>
|
|
1293
|
-
<UiSelect v-model="year">
|
|
1294
|
-
<UiSelectTrigger id="exp-year">
|
|
1295
|
-
<UiSelectValue placeholder="YYYY" />
|
|
1296
|
-
</UiSelectTrigger>
|
|
1297
|
-
<UiSelectContent>
|
|
1298
|
-
<UiSelectItem value="2026">2026</UiSelectItem>
|
|
1299
|
-
<UiSelectItem value="2027">2027</UiSelectItem>
|
|
1300
|
-
<UiSelectItem value="2028">2028</UiSelectItem>
|
|
1301
|
-
<UiSelectItem value="2029">2029</UiSelectItem>
|
|
1302
|
-
<UiSelectItem value="2030">2030</UiSelectItem>
|
|
1303
|
-
</UiSelectContent>
|
|
1304
|
-
</UiSelect>
|
|
1305
|
-
</UiField>
|
|
1306
|
-
|
|
1307
|
-
<UiField>
|
|
1308
|
-
<UiFieldLabel for="cvv">CVV</UiFieldLabel>
|
|
1309
|
-
<UiInput id="cvv" v-model="cvv" name="cvv" placeholder="123" required />
|
|
1310
|
-
</UiField>
|
|
1311
|
-
</div>
|
|
1312
|
-
</UiFieldGroup>
|
|
1313
|
-
</UiFieldSet>
|
|
1314
|
-
|
|
1315
|
-
<UiFieldSeparator />
|
|
1316
|
-
|
|
1317
|
-
<UiFieldSet>
|
|
1318
|
-
<UiFieldLegend>Billing Address</UiFieldLegend>
|
|
1319
|
-
<UiFieldDescription>The billing address associated with your payment method</UiFieldDescription>
|
|
1320
|
-
<UiFieldGroup>
|
|
1321
|
-
<UiField orientation="horizontal">
|
|
1322
|
-
<UiCheckbox id="same-as-shipping" v-model="sameAsShipping" name="same-as-shipping" />
|
|
1323
|
-
<UiFieldLabel for="same-as-shipping" class="font-normal">Same as shipping address</UiFieldLabel>
|
|
1324
|
-
</UiField>
|
|
1325
|
-
</UiFieldGroup>
|
|
1326
|
-
</UiFieldSet>
|
|
1327
|
-
|
|
1328
|
-
<UiFieldSet>
|
|
1329
|
-
<UiFieldGroup>
|
|
1330
|
-
<UiField>
|
|
1331
|
-
<UiFieldLabel for="comments">Comments</UiFieldLabel>
|
|
1332
|
-
<UiTextarea
|
|
1333
|
-
id="comments"
|
|
1334
|
-
v-model="comments"
|
|
1335
|
-
name="comments"
|
|
1336
|
-
placeholder="Add any additional comments"
|
|
1337
|
-
class="resize-none"
|
|
1338
|
-
/>
|
|
1339
|
-
</UiField>
|
|
1340
|
-
</UiFieldGroup>
|
|
1341
|
-
</UiFieldSet>
|
|
1342
|
-
|
|
1343
|
-
<UiField orientation="horizontal">
|
|
1344
|
-
<UiButton type="submit">Submit</UiButton>
|
|
1345
|
-
<UiButton variant="outline" type="button">Cancel</UiButton>
|
|
1346
|
-
</UiField>
|
|
1347
|
-
</UiFieldGroup>
|
|
1348
|
-
</form>
|
|
1349
|
-
</div>
|
|
1350
|
-
</template>`;
|
|
1351
|
-
|
|
1352
1510
|
/**
|
|
1353
|
-
*
|
|
1354
|
-
*
|
|
1511
|
+
* Payment form with card details, billing address, and comments.
|
|
1512
|
+
* Demonstrates `tooltip` on labels, select inputs, checkbox, and textarea.
|
|
1355
1513
|
*/
|
|
1356
|
-
export const
|
|
1514
|
+
export const PaymentMethodForm: Story = {
|
|
1357
1515
|
render: () => ({
|
|
1358
1516
|
components: {
|
|
1359
1517
|
UiButton,
|
|
@@ -1374,9 +1532,9 @@ export const CheckoutPaymentForm: Story = {
|
|
|
1374
1532
|
UiTextarea,
|
|
1375
1533
|
},
|
|
1376
1534
|
setup() {
|
|
1377
|
-
const cardName = ref('');
|
|
1378
|
-
const cardNumber = ref('');
|
|
1379
|
-
const cvv = ref('');
|
|
1535
|
+
const cardName = ref('John Doe');
|
|
1536
|
+
const cardNumber = ref('1234 5678 9012 3456');
|
|
1537
|
+
const cvv = ref('123');
|
|
1380
1538
|
const month = ref('');
|
|
1381
1539
|
const year = ref('');
|
|
1382
1540
|
const sameAsShipping = ref(true);
|
|
@@ -1384,67 +1542,45 @@ export const CheckoutPaymentForm: Story = {
|
|
|
1384
1542
|
return { cardName, cardNumber, cvv, month, year, sameAsShipping, comments };
|
|
1385
1543
|
},
|
|
1386
1544
|
template: `
|
|
1387
|
-
<div class="w-full max-w-
|
|
1545
|
+
<div class="w-full max-w-sm">
|
|
1388
1546
|
<form>
|
|
1389
1547
|
<UiFieldGroup>
|
|
1390
1548
|
<UiFieldSet>
|
|
1391
1549
|
<UiFieldLegend>Payment Method</UiFieldLegend>
|
|
1392
|
-
<UiFieldDescription>All transactions are secure and encrypted
|
|
1550
|
+
<UiFieldDescription>All transactions are secure and encrypted.</UiFieldDescription>
|
|
1393
1551
|
|
|
1394
1552
|
<UiFieldGroup>
|
|
1395
1553
|
<UiField>
|
|
1396
|
-
<UiFieldLabel for="card-name">Name on
|
|
1397
|
-
<UiInput id="card-name" v-model="cardName" name="cardName" placeholder="
|
|
1554
|
+
<UiFieldLabel for="card-name" tooltip="The name printed on your card.">Name on card</UiFieldLabel>
|
|
1555
|
+
<UiInput id="card-name" v-model="cardName" name="cardName" placeholder="John Doe" required />
|
|
1398
1556
|
</UiField>
|
|
1399
1557
|
|
|
1400
1558
|
<UiField>
|
|
1401
|
-
<UiFieldLabel for="card-number">Card
|
|
1559
|
+
<UiFieldLabel for="card-number" tooltip="Your 16-digit card number.">Card number</UiFieldLabel>
|
|
1402
1560
|
<UiInput id="card-number" v-model="cardNumber" name="cardNumber" placeholder="1234 5678 9012 3456" required />
|
|
1403
|
-
<UiFieldDescription>Enter your 16-digit card number</UiFieldDescription>
|
|
1404
1561
|
</UiField>
|
|
1405
1562
|
|
|
1406
1563
|
<div class="grid grid-cols-3 gap-4">
|
|
1407
1564
|
<UiField>
|
|
1408
|
-
<UiFieldLabel for="exp-month">Month</UiFieldLabel>
|
|
1565
|
+
<UiFieldLabel for="exp-month" tooltip="Expiry month.">Month</UiFieldLabel>
|
|
1409
1566
|
<UiSelect v-model="month">
|
|
1410
|
-
<UiSelectTrigger id="exp-month">
|
|
1411
|
-
<UiSelectValue placeholder="MM" />
|
|
1412
|
-
</UiSelectTrigger>
|
|
1567
|
+
<UiSelectTrigger id="exp-month"><UiSelectValue placeholder="MM" /></UiSelectTrigger>
|
|
1413
1568
|
<UiSelectContent>
|
|
1414
|
-
<UiSelectItem
|
|
1415
|
-
<UiSelectItem value="02">02</UiSelectItem>
|
|
1416
|
-
<UiSelectItem value="03">03</UiSelectItem>
|
|
1417
|
-
<UiSelectItem value="04">04</UiSelectItem>
|
|
1418
|
-
<UiSelectItem value="05">05</UiSelectItem>
|
|
1419
|
-
<UiSelectItem value="06">06</UiSelectItem>
|
|
1420
|
-
<UiSelectItem value="07">07</UiSelectItem>
|
|
1421
|
-
<UiSelectItem value="08">08</UiSelectItem>
|
|
1422
|
-
<UiSelectItem value="09">09</UiSelectItem>
|
|
1423
|
-
<UiSelectItem value="10">10</UiSelectItem>
|
|
1424
|
-
<UiSelectItem value="11">11</UiSelectItem>
|
|
1425
|
-
<UiSelectItem value="12">12</UiSelectItem>
|
|
1569
|
+
<UiSelectItem v-for="m in ['01','02','03','04','05','06','07','08','09','10','11','12']" :key="m" :value="m">{{ m }}</UiSelectItem>
|
|
1426
1570
|
</UiSelectContent>
|
|
1427
1571
|
</UiSelect>
|
|
1428
1572
|
</UiField>
|
|
1429
|
-
|
|
1430
1573
|
<UiField>
|
|
1431
|
-
<UiFieldLabel for="exp-year">Year</UiFieldLabel>
|
|
1574
|
+
<UiFieldLabel for="exp-year" tooltip="Expiry year.">Year</UiFieldLabel>
|
|
1432
1575
|
<UiSelect v-model="year">
|
|
1433
|
-
<UiSelectTrigger id="exp-year">
|
|
1434
|
-
<UiSelectValue placeholder="YYYY" />
|
|
1435
|
-
</UiSelectTrigger>
|
|
1576
|
+
<UiSelectTrigger id="exp-year"><UiSelectValue placeholder="YYYY" /></UiSelectTrigger>
|
|
1436
1577
|
<UiSelectContent>
|
|
1437
|
-
<UiSelectItem
|
|
1438
|
-
<UiSelectItem value="2027">2027</UiSelectItem>
|
|
1439
|
-
<UiSelectItem value="2028">2028</UiSelectItem>
|
|
1440
|
-
<UiSelectItem value="2029">2029</UiSelectItem>
|
|
1441
|
-
<UiSelectItem value="2030">2030</UiSelectItem>
|
|
1578
|
+
<UiSelectItem v-for="y in ['2026','2027','2028','2029','2030']" :key="y" :value="y">{{ y }}</UiSelectItem>
|
|
1442
1579
|
</UiSelectContent>
|
|
1443
1580
|
</UiSelect>
|
|
1444
1581
|
</UiField>
|
|
1445
|
-
|
|
1446
1582
|
<UiField>
|
|
1447
|
-
<UiFieldLabel for="cvv">CVV</UiFieldLabel>
|
|
1583
|
+
<UiFieldLabel for="cvv" tooltip="3-digit security code on the back.">CVV</UiFieldLabel>
|
|
1448
1584
|
<UiInput id="cvv" v-model="cvv" name="cvv" placeholder="123" required />
|
|
1449
1585
|
</UiField>
|
|
1450
1586
|
</div>
|
|
@@ -1455,31 +1591,238 @@ export const CheckoutPaymentForm: Story = {
|
|
|
1455
1591
|
|
|
1456
1592
|
<UiFieldSet>
|
|
1457
1593
|
<UiFieldLegend>Billing Address</UiFieldLegend>
|
|
1458
|
-
<UiFieldDescription>The billing address associated with your payment method
|
|
1594
|
+
<UiFieldDescription>The billing address associated with your payment method.</UiFieldDescription>
|
|
1459
1595
|
<UiFieldGroup>
|
|
1460
|
-
<UiField orientation="
|
|
1596
|
+
<UiField orientation="responsive">
|
|
1461
1597
|
<UiCheckbox id="same-as-shipping" v-model="sameAsShipping" name="same-as-shipping" />
|
|
1462
1598
|
<UiFieldLabel for="same-as-shipping" class="font-normal">Same as shipping address</UiFieldLabel>
|
|
1463
1599
|
</UiField>
|
|
1464
1600
|
</UiFieldGroup>
|
|
1465
1601
|
</UiFieldSet>
|
|
1466
1602
|
|
|
1603
|
+
<UiField>
|
|
1604
|
+
<UiFieldLabel for="comments" tooltip="Any special delivery instructions.">Comments</UiFieldLabel>
|
|
1605
|
+
<UiTextarea id="comments" v-model="comments" name="comments" placeholder="Add any additional comments" class="resize-none" />
|
|
1606
|
+
</UiField>
|
|
1607
|
+
|
|
1608
|
+
<UiField orientation="responsive">
|
|
1609
|
+
<UiButton type="submit">Submit</UiButton>
|
|
1610
|
+
<UiButton variant="outline" type="button">Cancel</UiButton>
|
|
1611
|
+
</UiField>
|
|
1612
|
+
</UiFieldGroup>
|
|
1613
|
+
</form>
|
|
1614
|
+
</div>
|
|
1615
|
+
`,
|
|
1616
|
+
}),
|
|
1617
|
+
parameters: { controls: { disable: true } },
|
|
1618
|
+
};
|
|
1619
|
+
|
|
1620
|
+
/**
|
|
1621
|
+
* Profile settings form with notification switches, privacy radio group,
|
|
1622
|
+
* and a labeled separator. Demonstrates `descriptionPlacement`, `UiSwitch`,
|
|
1623
|
+
* and `UiRadioGroup` inside fields.
|
|
1624
|
+
*/
|
|
1625
|
+
export const ProfileSettingsForm: Story = {
|
|
1626
|
+
render: () => ({
|
|
1627
|
+
components: {
|
|
1628
|
+
UiButton,
|
|
1629
|
+
UiField,
|
|
1630
|
+
UiFieldContent,
|
|
1631
|
+
UiFieldDescription,
|
|
1632
|
+
UiFieldGroup,
|
|
1633
|
+
UiFieldLabel,
|
|
1634
|
+
UiFieldLegend,
|
|
1635
|
+
UiFieldSeparator,
|
|
1636
|
+
UiFieldSet,
|
|
1637
|
+
UiInput,
|
|
1638
|
+
UiRadioGroup,
|
|
1639
|
+
UiRadioGroupItem,
|
|
1640
|
+
UiSwitch,
|
|
1641
|
+
UiTextarea,
|
|
1642
|
+
},
|
|
1643
|
+
setup() {
|
|
1644
|
+
const firstName = ref('John');
|
|
1645
|
+
const lastName = ref('Doe');
|
|
1646
|
+
const email = ref('john@example.com');
|
|
1647
|
+
const phone = ref('(555) 123-4567');
|
|
1648
|
+
const bio = ref('');
|
|
1649
|
+
const emailNotifications = ref(true);
|
|
1650
|
+
const pushNotifications = ref(false);
|
|
1651
|
+
const marketingEmails = ref(true);
|
|
1652
|
+
const privacy = ref('everyone');
|
|
1653
|
+
return {
|
|
1654
|
+
firstName,
|
|
1655
|
+
lastName,
|
|
1656
|
+
email,
|
|
1657
|
+
phone,
|
|
1658
|
+
bio,
|
|
1659
|
+
emailNotifications,
|
|
1660
|
+
pushNotifications,
|
|
1661
|
+
marketingEmails,
|
|
1662
|
+
privacy,
|
|
1663
|
+
};
|
|
1664
|
+
},
|
|
1665
|
+
template: `
|
|
1666
|
+
<div class="w-full max-w-md">
|
|
1667
|
+
<form>
|
|
1668
|
+
<UiFieldGroup>
|
|
1669
|
+
<UiFieldSet>
|
|
1670
|
+
<UiFieldLegend>Profile Settings</UiFieldLegend>
|
|
1671
|
+
<UiFieldDescription>Update your profile information and preferences.</UiFieldDescription>
|
|
1672
|
+
|
|
1673
|
+
<UiFieldGroup>
|
|
1674
|
+
<div class="grid grid-cols-2 gap-4">
|
|
1675
|
+
<UiField>
|
|
1676
|
+
<UiFieldLabel for="profile-first" tooltip="Your given name.">First Name</UiFieldLabel>
|
|
1677
|
+
<UiInput id="profile-first" v-model="firstName" name="firstName" placeholder="John" />
|
|
1678
|
+
</UiField>
|
|
1679
|
+
<UiField>
|
|
1680
|
+
<UiFieldLabel for="profile-last" tooltip="Your family name.">Last Name</UiFieldLabel>
|
|
1681
|
+
<UiInput id="profile-last" v-model="lastName" name="lastName" placeholder="Doe" />
|
|
1682
|
+
</UiField>
|
|
1683
|
+
</div>
|
|
1684
|
+
|
|
1685
|
+
<UiField>
|
|
1686
|
+
<UiFieldLabel for="profile-email" tooltip="Your primary contact email.">Email</UiFieldLabel>
|
|
1687
|
+
<UiInput id="profile-email" v-model="email" name="email" type="email" placeholder="john@example.com" />
|
|
1688
|
+
</UiField>
|
|
1689
|
+
|
|
1690
|
+
<UiField>
|
|
1691
|
+
<UiFieldLabel for="profile-phone" tooltip="Include country code.">Phone Number</UiFieldLabel>
|
|
1692
|
+
<UiInput id="profile-phone" v-model="phone" name="phone" type="tel" placeholder="(555) 123-4567" />
|
|
1693
|
+
</UiField>
|
|
1694
|
+
|
|
1695
|
+
<UiField>
|
|
1696
|
+
<UiFieldLabel for="profile-bio" tooltip="Keep it short and professional.">Bio</UiFieldLabel>
|
|
1697
|
+
<UiTextarea id="profile-bio" v-model="bio" name="bio" placeholder="Tell us a little about yourself" class="resize-none" />
|
|
1698
|
+
</UiField>
|
|
1699
|
+
</UiFieldGroup>
|
|
1700
|
+
</UiFieldSet>
|
|
1701
|
+
|
|
1702
|
+
<UiFieldSet>
|
|
1703
|
+
<UiFieldLegend>Notification Preferences</UiFieldLegend>
|
|
1704
|
+
<UiFieldDescription>Manage your notification preferences.</UiFieldDescription>
|
|
1705
|
+
|
|
1706
|
+
<UiFieldGroup>
|
|
1707
|
+
<UiField orientation="responsive" description-placement="under-label">
|
|
1708
|
+
<UiFieldLabel for="email-notif">Email notifications</UiFieldLabel>
|
|
1709
|
+
<UiFieldDescription>Receive emails about new products, features, and more. If you don't want to receive these emails, you can turn them off.</UiFieldDescription>
|
|
1710
|
+
<UiSwitch id="email-notif" v-model="emailNotifications" name="emailNotifications" />
|
|
1711
|
+
</UiField>
|
|
1712
|
+
|
|
1713
|
+
<UiField orientation="responsive">
|
|
1714
|
+
<UiFieldLabel for="push-notif">Push notifications</UiFieldLabel>
|
|
1715
|
+
<UiSwitch id="push-notif" v-model="pushNotifications" name="pushNotifications" />
|
|
1716
|
+
</UiField>
|
|
1717
|
+
|
|
1718
|
+
<UiField orientation="responsive">
|
|
1719
|
+
<UiFieldLabel for="marketing">Marketing emails</UiFieldLabel>
|
|
1720
|
+
<UiSwitch id="marketing" v-model="marketingEmails" name="marketingEmails" />
|
|
1721
|
+
</UiField>
|
|
1722
|
+
</UiFieldGroup>
|
|
1723
|
+
</UiFieldSet>
|
|
1724
|
+
|
|
1725
|
+
<UiFieldSeparator>Privacy</UiFieldSeparator>
|
|
1726
|
+
|
|
1727
|
+
<UiFieldSet>
|
|
1728
|
+
<UiFieldLegend>Privacy Settings</UiFieldLegend>
|
|
1729
|
+
<UiFieldDescription>Choose who can see your profile and what they can see.</UiFieldDescription>
|
|
1730
|
+
|
|
1731
|
+
<UiRadioGroup v-model="privacy" name="privacy">
|
|
1732
|
+
<UiField orientation="responsive">
|
|
1733
|
+
<UiRadioGroupItem id="privacy-everyone" value="everyone" />
|
|
1734
|
+
<UiFieldContent>
|
|
1735
|
+
<UiFieldLabel for="privacy-everyone" class="font-normal">Everyone</UiFieldLabel>
|
|
1736
|
+
<UiFieldDescription>Anyone can see your profile</UiFieldDescription>
|
|
1737
|
+
</UiFieldContent>
|
|
1738
|
+
</UiField>
|
|
1739
|
+
<UiField orientation="responsive">
|
|
1740
|
+
<UiRadioGroupItem id="privacy-followers" value="followers" />
|
|
1741
|
+
<UiFieldContent>
|
|
1742
|
+
<UiFieldLabel for="privacy-followers" class="font-normal">Followers</UiFieldLabel>
|
|
1743
|
+
<UiFieldDescription>Visible to your followers and connections</UiFieldDescription>
|
|
1744
|
+
</UiFieldContent>
|
|
1745
|
+
</UiField>
|
|
1746
|
+
<UiField orientation="responsive">
|
|
1747
|
+
<UiRadioGroupItem id="privacy-custom" value="custom" />
|
|
1748
|
+
<UiFieldContent>
|
|
1749
|
+
<UiFieldLabel for="privacy-custom" class="font-normal">Custom</UiFieldLabel>
|
|
1750
|
+
<UiFieldDescription>Choose who can see your profile</UiFieldDescription>
|
|
1751
|
+
</UiFieldContent>
|
|
1752
|
+
</UiField>
|
|
1753
|
+
</UiRadioGroup>
|
|
1754
|
+
</UiFieldSet>
|
|
1755
|
+
|
|
1756
|
+
<UiField orientation="responsive">
|
|
1757
|
+
<UiButton variant="outline" type="button">Cancel</UiButton>
|
|
1758
|
+
<UiButton type="submit">Save Changes</UiButton>
|
|
1759
|
+
</UiField>
|
|
1760
|
+
</UiFieldGroup>
|
|
1761
|
+
</form>
|
|
1762
|
+
</div>
|
|
1763
|
+
`,
|
|
1764
|
+
}),
|
|
1765
|
+
parameters: { controls: { disable: true } },
|
|
1766
|
+
};
|
|
1767
|
+
|
|
1768
|
+
/**
|
|
1769
|
+
* Personal information form with file upload and terms checkbox.
|
|
1770
|
+
* Demonstrates `tooltip` labels, file input, and validation-style checkbox.
|
|
1771
|
+
*/
|
|
1772
|
+
export const PersonalInformationForm: Story = {
|
|
1773
|
+
render: () => ({
|
|
1774
|
+
components: {
|
|
1775
|
+
UiButton,
|
|
1776
|
+
UiCheckbox,
|
|
1777
|
+
UiField,
|
|
1778
|
+
UiFieldContent,
|
|
1779
|
+
UiFieldDescription,
|
|
1780
|
+
UiFieldGroup,
|
|
1781
|
+
UiFieldLabel,
|
|
1782
|
+
UiFieldLegend,
|
|
1783
|
+
UiFieldSet,
|
|
1784
|
+
UiInput,
|
|
1785
|
+
},
|
|
1786
|
+
setup() {
|
|
1787
|
+
const pFirstName = ref('John');
|
|
1788
|
+
const pLastName = ref('Doe');
|
|
1789
|
+
const agreeTerms = ref(false);
|
|
1790
|
+
return { pFirstName, pLastName, agreeTerms };
|
|
1791
|
+
},
|
|
1792
|
+
template: `
|
|
1793
|
+
<div class="w-full max-w-sm">
|
|
1794
|
+
<form>
|
|
1795
|
+
<UiFieldGroup>
|
|
1467
1796
|
<UiFieldSet>
|
|
1797
|
+
<UiFieldLegend>Personal Information</UiFieldLegend>
|
|
1798
|
+
<UiFieldDescription>Your basic contact information.</UiFieldDescription>
|
|
1799
|
+
|
|
1468
1800
|
<UiFieldGroup>
|
|
1469
1801
|
<UiField>
|
|
1470
|
-
<UiFieldLabel for="
|
|
1471
|
-
<
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1802
|
+
<UiFieldLabel for="p-first" tooltip="As it appears on official documents.">First Name</UiFieldLabel>
|
|
1803
|
+
<UiInput id="p-first" v-model="pFirstName" name="pFirstName" placeholder="John" />
|
|
1804
|
+
</UiField>
|
|
1805
|
+
|
|
1806
|
+
<UiField>
|
|
1807
|
+
<UiFieldLabel for="p-last" tooltip="As it appears on official documents.">Last Name</UiFieldLabel>
|
|
1808
|
+
<UiInput id="p-last" v-model="pLastName" name="pLastName" placeholder="Doe" />
|
|
1809
|
+
</UiField>
|
|
1810
|
+
|
|
1811
|
+
<UiField>
|
|
1812
|
+
<UiFieldLabel for="p-resume" tooltip="PDF or DOCX, max 5 MB.">Upload Resume</UiFieldLabel>
|
|
1813
|
+
<UiInput id="p-resume" name="resume" type="file" />
|
|
1478
1814
|
</UiField>
|
|
1479
1815
|
</UiFieldGroup>
|
|
1480
1816
|
</UiFieldSet>
|
|
1481
1817
|
|
|
1482
|
-
<UiField orientation="
|
|
1818
|
+
<UiField orientation="responsive" data-invalid="true">
|
|
1819
|
+
<UiCheckbox id="agree-terms" v-model="agreeTerms" name="agreeTerms" />
|
|
1820
|
+
<UiFieldContent>
|
|
1821
|
+
<UiFieldLabel for="agree-terms" class="font-normal">I agree to the terms and conditions</UiFieldLabel>
|
|
1822
|
+
</UiFieldContent>
|
|
1823
|
+
</UiField>
|
|
1824
|
+
|
|
1825
|
+
<UiField orientation="responsive">
|
|
1483
1826
|
<UiButton type="submit">Submit</UiButton>
|
|
1484
1827
|
<UiButton variant="outline" type="button">Cancel</UiButton>
|
|
1485
1828
|
</UiField>
|
|
@@ -1488,8 +1831,5 @@ export const CheckoutPaymentForm: Story = {
|
|
|
1488
1831
|
</div>
|
|
1489
1832
|
`,
|
|
1490
1833
|
}),
|
|
1491
|
-
parameters: {
|
|
1492
|
-
controls: { disable: true },
|
|
1493
|
-
docs: { source: { code: checkoutPaymentFormTemplateSource } },
|
|
1494
|
-
},
|
|
1834
|
+
parameters: { controls: { disable: true } },
|
|
1495
1835
|
};
|