@aleph-alpha/ui-library 1.16.0 → 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.
Files changed (31) hide show
  1. package/dist/system/index.d.ts +585 -402
  2. package/dist/system/lib.js +13063 -12825
  3. package/package.json +3 -4
  4. package/src/components/UiChip/UiChip.stories.ts +239 -0
  5. package/src/components/UiChip/UiChip.vue +128 -0
  6. package/src/components/UiChip/__tests__/UiChip.test.ts +102 -0
  7. package/src/components/UiChip/index.ts +2 -0
  8. package/src/components/UiChip/types.ts +50 -0
  9. package/src/components/UiDropdownMenu/UiDropdownMenu.stories.ts +259 -1
  10. package/src/components/UiField/UiField.stories.ts +589 -249
  11. package/src/components/UiField/UiField.vue +87 -2
  12. package/src/components/UiField/UiFieldDescription.vue +22 -1
  13. package/src/components/UiField/UiFieldLabel.vue +2 -0
  14. package/src/components/UiField/UiFieldLabelInfo.vue +22 -0
  15. package/src/components/UiField/index.ts +1 -0
  16. package/src/components/UiField/keys.ts +5 -0
  17. package/src/components/UiField/types.ts +86 -1
  18. package/src/components/UiSelect/__tests__/UiSelectTrigger.test.ts +47 -2
  19. package/src/components/UiToggle/UiToggle.stories.ts +54 -1
  20. package/src/components/UiToggle/__tests__/UiToggle.test.ts +15 -0
  21. package/src/components/UiToggle/types.ts +1 -1
  22. package/src/components/UiToggleGroup/__tests__/UiToggleGroup.test.ts +21 -0
  23. package/src/components/UiToggleGroup/types.ts +2 -2
  24. package/src/components/core/button/index.ts +8 -3
  25. package/src/components/core/field/FieldLabel.vue +1 -1
  26. package/src/components/core/field/index.ts +5 -5
  27. package/src/components/core/select/SelectTrigger.vue +1 -1
  28. package/src/components/core/toggle/Toggle.vue +3 -3
  29. package/src/components/core/toggle/index.ts +6 -3
  30. package/src/components/core/toggle-group/index.ts +6 -3
  31. 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', 'horizontal', 'responsive'],
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 :orientation="args.orientation">
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 horizontalOrientationTemplateSource = `<script setup lang="ts">
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="horizontal">
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
- * Field with horizontal layout.
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 HorizontalOrientation: Story = {
291
- args: { orientation: 'horizontal' },
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: horizontalOrientationTemplateSource } },
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="horizontal">
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 horizontal styles can align it nicely.
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="horizontal">
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="horizontal">
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="horizontal">
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="horizontal">
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="horizontal">
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="horizontal" data-disabled="true">
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="horizontal">
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="horizontal">
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="horizontal" data-disabled="true">
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="horizontal">
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="horizontal">
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="horizontal">
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="horizontal">
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
- <UiFieldLabel for="profile-name">Name</UiFieldLabel>
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
- <UiFieldLabel for="profile-message">Message</UiFieldLabel>
1120
- <UiFieldDescription>
1121
- You can write your message here. Keep it short, preferably under 100 characters.
1122
- </UiFieldDescription>
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 `UiFieldContent` as the label/description column and keeps controls aligned responsively.
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
- <UiFieldLabel for="profile-name">Name</UiFieldLabel>
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
- <UiFieldLabel for="profile-message">Message</UiFieldLabel>
1187
- <UiFieldDescription>
1188
- You can write your message here. Keep it short, preferably under 100 characters.
1189
- </UiFieldDescription>
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
- * Full “checkout” composition (payment method + billing address + actions).
1354
- * Based on the main example in shadcn-vue field docs.
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 CheckoutPaymentForm: Story = {
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-md">
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</UiFieldDescription>
1550
+ <UiFieldDescription>All transactions are secure and encrypted.</UiFieldDescription>
1393
1551
 
1394
1552
  <UiFieldGroup>
1395
1553
  <UiField>
1396
- <UiFieldLabel for="card-name">Name on Card</UiFieldLabel>
1397
- <UiInput id="card-name" v-model="cardName" name="cardName" placeholder="Evil Rabbit" required />
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 Number</UiFieldLabel>
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 value="01">01</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 value="2026">2026</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</UiFieldDescription>
1594
+ <UiFieldDescription>The billing address associated with your payment method.</UiFieldDescription>
1459
1595
  <UiFieldGroup>
1460
- <UiField orientation="horizontal">
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="comments">Comments</UiFieldLabel>
1471
- <UiTextarea
1472
- id="comments"
1473
- v-model="comments"
1474
- name="comments"
1475
- placeholder="Add any additional comments"
1476
- class="resize-none"
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="horizontal">
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
  };