vueless 1.4.7-beta.4 → 1.4.7-beta.6

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 (35) hide show
  1. package/package.json +2 -2
  2. package/ui.container-accordion/storybook/stories.ts +1 -1
  3. package/ui.container-accordion-item/storybook/stories.ts +1 -1
  4. package/ui.container-card/storybook/stories.ts +40 -39
  5. package/ui.container-modal/storybook/stories.ts +2 -2
  6. package/ui.container-modal-confirm/storybook/stories.ts +17 -2
  7. package/ui.container-page/storybook/stories.ts +6 -1
  8. package/ui.data-table/storybook/stories.ts +1 -1
  9. package/ui.form-checkbox/storybook/stories.ts +11 -17
  10. package/ui.form-checkbox-group/storybook/stories.ts +3 -3
  11. package/ui.form-date-picker/storybook/stories.ts +19 -17
  12. package/ui.form-date-picker-range/storybook/stories.ts +11 -17
  13. package/ui.form-input/storybook/stories.ts +4 -8
  14. package/ui.form-input-file/storybook/stories.ts +11 -17
  15. package/ui.form-input-number/storybook/stories.ts +11 -17
  16. package/ui.form-input-password/storybook/stories.ts +11 -17
  17. package/ui.form-input-rating/UInputRating.vue +8 -3
  18. package/ui.form-input-search/storybook/stories.ts +12 -18
  19. package/ui.form-label/storybook/stories.ts +12 -18
  20. package/ui.form-listbox/UListbox.vue +72 -71
  21. package/ui.form-listbox/tests/UListbox.test.ts +37 -3
  22. package/ui.form-radio/storybook/stories.ts +12 -17
  23. package/ui.form-radio-group/storybook/stories.ts +11 -17
  24. package/ui.form-select/config.ts +4 -1
  25. package/ui.form-select/storybook/stories.ts +27 -19
  26. package/ui.form-switch/storybook/stories.ts +3 -3
  27. package/ui.form-textarea/storybook/stories.ts +11 -17
  28. package/ui.text-files/storybook/stories.ts +3 -3
  29. package/icons/storybook/date_range.svg +0 -1
  30. package/icons/storybook/event.svg +0 -1
  31. package/icons/storybook/format_quote.svg +0 -1
  32. package/icons/storybook/location_city.svg +0 -1
  33. package/icons/storybook/mark_email_unread.svg +0 -1
  34. package/icons/storybook/shield.svg +0 -1
  35. package/icons/storybook/workspace_premium.svg +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "1.4.7-beta.4",
3
+ "version": "1.4.7-beta.6",
4
4
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
5
5
  "author": "Johnny Grid <hello@vueless.com> (https://vueless.com)",
6
6
  "homepage": "https://vueless.com",
@@ -58,7 +58,7 @@
58
58
  "@vue/eslint-config-typescript": "^14.7.0",
59
59
  "@vue/test-utils": "^2.4.8",
60
60
  "@vue/tsconfig": "^0.9.1",
61
- "@vueless/storybook": "^1.5.2",
61
+ "@vueless/storybook": "^1.5.4",
62
62
  "eslint": "^10.2.1",
63
63
  "eslint-plugin-storybook": "^10.3.5",
64
64
  "eslint-plugin-vue": "^10.9.0",
@@ -25,7 +25,7 @@ interface UAccordionArgs extends Props {
25
25
  }
26
26
 
27
27
  export default {
28
- id: "5040",
28
+ id: "5050",
29
29
  title: "Containers / Accordion",
30
30
  component: UAccordion,
31
31
  args: {
@@ -23,7 +23,7 @@ interface UAccordionItemArgs extends Props {
23
23
  }
24
24
 
25
25
  export default {
26
- id: "5050",
26
+ id: "5040",
27
27
  title: "Containers / Accordion Item",
28
28
  component: UAccordionItem,
29
29
  args: {
@@ -44,34 +44,34 @@ export default {
44
44
  },
45
45
  } as Meta;
46
46
 
47
- const defaultTemplate = `
48
- <UCol
49
- justify="between"
50
- class="h-full"
51
- >
52
- <URow
53
- v-for="(cookie, index) in cookieSettings"
54
- :key="cookie.label"
55
- justify="between"
56
- align="center"
57
- block
58
- >
59
- <UCol gap="2xs">
60
- <UHeader
61
- :label="cookie.label"
62
- class="text-sm"
63
- />
64
- <UText
65
- :label="cookie.description"
66
- size="sm"
67
- variant="lifted"
68
- />
69
- </UCol>
70
-
71
- <USwitch v-model="cookieValues[index]" />
72
- </URow>
73
- </UCol>
74
- `;
47
+ const defaultTemplate = (isInvertedExpr: string = "false") => {
48
+ return `
49
+ <UCol justify="between" block class="h-full">
50
+ <URow
51
+ v-for="(cookie, index) in cookieSettings"
52
+ :key="cookie.label"
53
+ align="center"
54
+ block
55
+ gap="sm"
56
+ >
57
+ <UCol gap="2xs" class="min-w-0 flex-1">
58
+ <UHeader
59
+ :label="cookie.label"
60
+ class="text-sm"
61
+ :class="{ 'text-inverted': ${isInvertedExpr} }"
62
+ />
63
+ <UText
64
+ :label="cookie.description"
65
+ size="sm"
66
+ variant="lifted"
67
+ />
68
+ </UCol>
69
+
70
+ <USwitch v-model="cookieValues[index]" class="shrink-0" />
71
+ </URow>
72
+ </UCol>
73
+ `;
74
+ };
75
75
 
76
76
  const cookieSettings = ref([
77
77
  {
@@ -95,7 +95,7 @@ const DefaultTemplate: StoryFn<UCardArgs> = (args: UCardArgs) => ({
95
95
  setup: () => ({ args, slots: getSlotNames(UCard.__name), cookieSettings, cookieValues }),
96
96
  template: `
97
97
  <UCard v-bind="args" class="max-w-96">
98
- ${args.slotTemplate || getSlotsFragment(defaultTemplate)}
98
+ ${args.slotTemplate || getSlotsFragment(defaultTemplate())}
99
99
  </UCard>
100
100
  `,
101
101
  });
@@ -109,9 +109,10 @@ const EnumTemplate: StoryFn<UCardArgs> = (args: UCardArgs, { argTypes }) => ({
109
109
  v-for="option in argTypes?.[args.enum]?.options"
110
110
  v-bind="getArgs(args, option)"
111
111
  :key="option"
112
+ :config="{ title: option === 'inverted' ? 'text-inverted' : 'text-default' }"
112
113
  class="max-w-96"
113
114
  >
114
- ${defaultTemplate}
115
+ ${defaultTemplate("option === 'inverted'")}
115
116
  </UCard>
116
117
  </URow>
117
118
  `,
@@ -135,7 +136,7 @@ NoDivided.args = {
135
136
  <template #footer-left>
136
137
  <UButton size="sm" label="Save" variant="subtle" />
137
138
  </template>
138
- ${defaultTemplate}
139
+ ${defaultTemplate()}
139
140
  `,
140
141
  };
141
142
 
@@ -145,7 +146,7 @@ BeforeTitleSlot.args = {
145
146
  <template #before-title>
146
147
  <UIcon name="cookie" color="success" size="sm" />
147
148
  </template>
148
- ${defaultTemplate}
149
+ ${defaultTemplate()}
149
150
  `,
150
151
  };
151
152
 
@@ -155,7 +156,7 @@ TitleSlot.args = {
155
156
  <template #title="{ title }">
156
157
  <UHeader :label="title" color="primary" />
157
158
  </template>
158
- ${defaultTemplate}
159
+ ${defaultTemplate()}
159
160
  `,
160
161
  };
161
162
 
@@ -165,7 +166,7 @@ AfterTitleSlot.args = {
165
166
  <template #after-title>
166
167
  <UIcon name="cookie" color="success" size="sm" />
167
168
  </template>
168
- ${defaultTemplate}
169
+ ${defaultTemplate()}
169
170
  `,
170
171
  };
171
172
 
@@ -175,18 +176,18 @@ ActionsSlot.args = {
175
176
  slotTemplate: `
176
177
  <template #actions>
177
178
  <URow align="center" class="max-w-fit">
178
- <ULink label="Learn more" />
179
- <UButton size="sm" label="Manage" variant="subtle" />
179
+ <ULink label="Learn more" size="sm" />
180
+ <UButton label="Manage" variant="subtle" size="xs" />
180
181
  </URow>
181
182
  </template>
182
- ${defaultTemplate}
183
+ ${defaultTemplate()}
183
184
  `,
184
185
  };
185
186
 
186
187
  export const FooterLeftSlot = DefaultTemplate.bind({});
187
188
  FooterLeftSlot.args = {
188
189
  slotTemplate: `
189
- ${defaultTemplate}
190
+ ${defaultTemplate()}
190
191
  <template #footer-left>
191
192
  <UButton size="sm" label="Cancel" variant="outlined" />
192
193
  </template>
@@ -196,7 +197,7 @@ FooterLeftSlot.args = {
196
197
  export const FooterRightSlot = DefaultTemplate.bind({});
197
198
  FooterRightSlot.args = {
198
199
  slotTemplate: `
199
- ${defaultTemplate}
200
+ ${defaultTemplate()}
200
201
  <template #footer-right>
201
202
  <UButton size="sm" label="Save" />
202
203
  </template>
@@ -264,7 +264,7 @@ WithoutDivider.args = {
264
264
  slotTemplate: `
265
265
  ${defaultTemplate}
266
266
  <template #footer-left>
267
- <UButton label="Back" color="neutral" variant="subtle" />
267
+ <UButton label="Back" color="neutral" variant="subtle" block />
268
268
  </template>`,
269
269
  };
270
270
  WithoutDivider.parameters = {
@@ -404,7 +404,7 @@ FooterRightSlot.args = {
404
404
  </template>
405
405
 
406
406
  <template #footer-right>
407
- <UButton label="Submit" variant="subtle" />
407
+ <UButton label="Not now" variant="subtle" color="neutral" />
408
408
  </template>
409
409
  `,
410
410
  };
@@ -27,6 +27,10 @@ interface UModalConfirmArgs extends Props {
27
27
  modelValues?: UnknownObject;
28
28
  }
29
29
 
30
+ const confirmModalDocsLayout = {
31
+ innerWrapper: "w-full max-h-full",
32
+ };
33
+
30
34
  export default {
31
35
  id: "5080",
32
36
  title: "Containers / Modal Confirm",
@@ -35,6 +39,9 @@ export default {
35
39
  title: "Confirm Subscription Upgrade",
36
40
  confirmLabel: "Confirm",
37
41
  modelValue: true,
42
+ config: {
43
+ confirmModal: confirmModalDocsLayout,
44
+ },
38
45
  },
39
46
  argTypes: {
40
47
  ...getArgTypes(UModalConfirm.__name),
@@ -152,7 +159,14 @@ export const Inner: StoryFn<UModalConfirmArgs> = (args: UModalConfirmArgs) => ({
152
159
  resetBodyOverflow();
153
160
  }
154
161
 
155
- return { args, showMainModal, showInnerModal, openMainModal, openInnerModal };
162
+ return {
163
+ args,
164
+ showMainModal,
165
+ showInnerModal,
166
+ openMainModal,
167
+ openInnerModal,
168
+ confirmModalDocsLayout,
169
+ };
156
170
  },
157
171
  template: `
158
172
  <div>
@@ -181,6 +195,7 @@ export const Inner: StoryFn<UModalConfirmArgs> = (args: UModalConfirmArgs) => ({
181
195
  "
182
196
  confirm-label="Agree"
183
197
  inner
198
+ :config="{ confirmModal: confirmModalDocsLayout }"
184
199
  >
185
200
  <UText label="Click Agree to proceed with subscription upgrade." />
186
201
  </UModalConfirm>
@@ -291,7 +306,7 @@ AfterTitleSlot.args = {
291
306
 
292
307
  export const ActionsSlot = DefaultTemplate.bind({});
293
308
  ActionsSlot.args = {
294
- config: { confirmModal: { closeButton: "p-0" } },
309
+ config: { confirmModal: { closeButton: "p-0", innerWrapper: "w-full max-h-full" } },
295
310
  slotTemplate: `
296
311
  <template #actions="{ close }">
297
312
  <UButton
@@ -35,6 +35,7 @@ export default {
35
35
  component: UPage,
36
36
  args: {
37
37
  title: "Join Our Community",
38
+ config: { wrapper: "min-h-max", page: "min-h-max" },
38
39
  },
39
40
  argTypes: {
40
41
  ...getArgTypes(UPage.__name),
@@ -142,7 +143,11 @@ const EnumTemplate: StoryFn<UPageArgs> = (args: UPageArgs, { argTypes }) => ({
142
143
  v-for="option in argTypes?.[args.enum]?.options"
143
144
  v-bind="getArgs(args, option)"
144
145
  :key="option"
145
- :config="{ wrapper: 'min-h-max', page: 'min-h-max mb-4' }"
146
+ :config="{
147
+ wrapper: 'min-h-max',
148
+ page: 'min-h-max mb-4',
149
+ title: option === 'inverted' ? 'text-inverted' : 'text-default'
150
+ }"
146
151
  >
147
152
  ${defaultTemplate}
148
153
  </UPage>
@@ -184,7 +184,7 @@ Loading.parameters = {
184
184
 
185
185
  export const EmptyCellLabel = DefaultTemplate.bind({});
186
186
  EmptyCellLabel.args = {
187
- emptyCellLabel: "---",
187
+ emptyCellLabel: "NO DATA",
188
188
  rows: [
189
189
  {
190
190
  id: getRandomId(),
@@ -168,13 +168,10 @@ export const Slots: StoryFn<UCheckboxArgs> = (args) => ({
168
168
  label="Email me product updates"
169
169
  >
170
170
  <template #description>
171
- <URow align="center" gap="2xs" class="text-neutral">
172
- <UIcon name="mail" size="xs" class="mt-0.5" color="primary" />
173
- <UText size="sm">
174
- Unsubscribe anytime.
175
- <ULink label="Privacy policy" underlined size="sm" />.
176
- </UText>
177
- </URow>
171
+ <UText size="sm" variant="lifted">
172
+ Unsubscribe anytime, see our
173
+ <ULink label="privacy policy" underlined size="sm" />.
174
+ </UText>
178
175
  </template>
179
176
  </UCheckbox>
180
177
 
@@ -185,16 +182,13 @@ export const Slots: StoryFn<UCheckboxArgs> = (args) => ({
185
182
  :error="true"
186
183
  >
187
184
  <template #error>
188
- <URow align="center" gap="2xs">
189
- <UIcon name="error" size="xs" color="error" />
190
- <UText size="sm" color="error">
191
- <ul>
192
- <li>You must accept the terms to continue</li>
193
- <li>This checkbox is required for registration</li>
194
- <li>Clear the error by checking the box above</li>
195
- </ul>
196
- </UText>
197
- </URow>
185
+ <UText size="sm" color="error">
186
+ <ul>
187
+ <li>You must accept the terms to continue</li>
188
+ <li>This checkbox is required for registration</li>
189
+ <li>Clear the error by checking the box above</li>
190
+ </ul>
191
+ </UText>
198
192
  </template>
199
193
  </UCheckbox>
200
194
  </UCol>
@@ -222,9 +222,9 @@ export const Slots: StoryFn<UCheckboxGroupArgs> = (args) => ({
222
222
  <template #description>
223
223
  <URow align="center" gap="2xs" class="text-neutral">
224
224
  <UIcon name="notifications" size="xs" color="primary" />
225
- <UText size="sm">
226
- You can change this later.
227
- <ULink label="Notification settings" underlined size="sm" />.
225
+ <UText size="sm" variant="lifted">
226
+ You can change this later in
227
+ <ULink label="notification settings" underlined size="sm" />.
228
228
  </UText>
229
229
  </URow>
230
230
  </template>
@@ -418,13 +418,10 @@ export const Slots: StoryFn<DefaultUDatePickerArgs> = (args) => ({
418
418
  class="w-full"
419
419
  >
420
420
  <template #description>
421
- <URow align="center" gap="2xs" class="text-neutral">
422
- <UIcon name="event" size="xs" color="primary" />
423
- <UText size="sm">
424
- Uses your local timezone.
425
- <ULink label="Date policy" underlined size="sm" />.
426
- </UText>
427
- </URow>
421
+ <UText size="sm" variant="lifted">
422
+ Uses your local timezone, see our
423
+ <ULink label="date policy" underlined size="sm" />.
424
+ </UText>
428
425
  </template>
429
426
  </UDatePicker>
430
427
 
@@ -436,19 +433,24 @@ export const Slots: StoryFn<DefaultUDatePickerArgs> = (args) => ({
436
433
  class="w-full"
437
434
  >
438
435
  <template #error>
439
- <URow align="center" gap="2xs">
440
- <UIcon name="error" size="xs" color="error" />
441
- <UText size="sm" color="error">
442
- <ul>
443
- <li>The selected date is not available</li>
444
- <li>Pick a day within the allowed range</li>
445
- <li>Weekends and holidays are excluded</li>
446
- </ul>
447
- </UText>
448
- </URow>
436
+ <UText size="sm" color="error">
437
+ <ul>
438
+ <li>The selected date is not available</li>
439
+ <li>Pick a day within the allowed range</li>
440
+ <li>Weekends and holidays are excluded</li>
441
+ </ul>
442
+ </UText>
449
443
  </template>
450
444
  </UDatePicker>
451
445
  </URow>
452
446
  </UCol>
453
447
  `,
454
448
  });
449
+
450
+ Slots.parameters = {
451
+ docs: {
452
+ story: {
453
+ height: "550px",
454
+ },
455
+ },
456
+ };
@@ -354,13 +354,10 @@ export const Slots: StoryFn<DefaultUDatePickerRangeArgs> = (args) => ({
354
354
  class="w-full"
355
355
  >
356
356
  <template #description>
357
- <URow align="center" gap="2xs" class="text-neutral">
358
- <UIcon name="date_range" size="xs" color="primary" />
359
- <UText size="sm">
360
- Inclusive of start and end.
361
- <ULink label="Fiscal calendar" underlined size="sm" />.
362
- </UText>
363
- </URow>
357
+ <UText size="sm" variant="lifted">
358
+ Inclusive of start and end, see the
359
+ <ULink label="fiscal calendar" underlined size="sm" />.
360
+ </UText>
364
361
  </template>
365
362
  </UDatePickerRange>
366
363
 
@@ -373,16 +370,13 @@ export const Slots: StoryFn<DefaultUDatePickerRangeArgs> = (args) => ({
373
370
  class="w-full"
374
371
  >
375
372
  <template #error>
376
- <URow align="center" gap="2xs">
377
- <UIcon name="error" size="xs" color="error" />
378
- <UText size="sm" color="error">
379
- <ul>
380
- <li>End date must be after the start date</li>
381
- <li>Range cannot span more than 30 days</li>
382
- <li>Select both dates from the calendar</li>
383
- </ul>
384
- </UText>
385
- </URow>
373
+ <UText size="sm" color="error">
374
+ <ul>
375
+ <li>End date must be after the start date</li>
376
+ <li>Range cannot span more than 30 days</li>
377
+ <li>Select both dates from the calendar</li>
378
+ </ul>
379
+ </UText>
386
380
  </template>
387
381
  </UDatePickerRange>
388
382
  </URow>
@@ -245,13 +245,10 @@ export const Slots: StoryFn<UInputArgs> = (args) => ({
245
245
  <URow block>
246
246
  <UInput v-model="descriptionSlotValue" label="Display name">
247
247
  <template #description>
248
- <URow align="center" gap="2xs" class="text-neutral">
249
- <UIcon name="info" size="xs" color="primary" />
250
- <UText size="sm">
251
- Shown on your public profile. Read the
252
- <ULink label="naming policy" underlined size="sm" />.
253
- </UText>
254
- </URow>
248
+ <UText size="sm" variant="lifted">
249
+ Shown on your public profile, read the
250
+ <ULink label="naming policy" underlined size="sm" />.
251
+ </UText>
255
252
  </template>
256
253
  </UInput>
257
254
 
@@ -262,7 +259,6 @@ export const Slots: StoryFn<UInputArgs> = (args) => ({
262
259
  >
263
260
  <template #error>
264
261
  <URow align="center" gap="2xs">
265
- <UIcon name="error" size="xs" color="error" />
266
262
  <UText size="sm" color="error">
267
263
  <ul>
268
264
  <li>This field failed validation</li>
@@ -168,13 +168,10 @@ export const Slots: StoryFn<UInputFileArgs> = (args) => ({
168
168
  label="Upload document"
169
169
  >
170
170
  <template #description>
171
- <URow align="center" gap="2xs">
172
- <UIcon name="description" size="xs" color="primary" />
173
- <UText size="sm">
174
- PDF or image, max 5MB.
175
- <ULink label="See requirements" underlined size="sm" />.
176
- </UText>
177
- </URow>
171
+ <UText size="sm" variant="lifted">
172
+ PDF or image, max 5MB, see
173
+ <ULink label="requirements" underlined size="sm" />.
174
+ </UText>
178
175
  </template>
179
176
  </UInputFile>
180
177
 
@@ -185,16 +182,13 @@ export const Slots: StoryFn<UInputFileArgs> = (args) => ({
185
182
  :error="true"
186
183
  >
187
184
  <template #error>
188
- <URow align="center" gap="2xs">
189
- <UIcon name="error" size="xs" color="error" />
190
- <UText size="sm" color="error">
191
- <ul>
192
- <li>File type is not accepted for this field</li>
193
- <li>Maximum file size has been exceeded</li>
194
- <li>Choose another file and upload again</li>
195
- </ul>
196
- </UText>
197
- </URow>
185
+ <UText size="sm" color="error">
186
+ <ul>
187
+ <li>File type is not accepted for this field</li>
188
+ <li>Maximum file size has been exceeded</li>
189
+ <li>Choose another file and upload again</li>
190
+ </ul>
191
+ </UText>
198
192
  </template>
199
193
  </UInputFile>
200
194
  </UCol>
@@ -247,13 +247,10 @@ export const Slots: StoryFn<UInputNumberArgs> = (args) => ({
247
247
  <URow block>
248
248
  <UInputNumber v-model="descriptionSlotValue" label="Amount">
249
249
  <template #description>
250
- <URow align="center" gap="2xs" class="text-neutral">
251
- <UIcon name="payments" size="xs" color="primary" />
252
- <UText size="sm">
253
- Net amount in
254
- <ULink label="account currency" underlined size="sm" />.
255
- </UText>
256
- </URow>
250
+ <UText size="sm" variant="lifted">
251
+ Net amount in
252
+ <ULink label="account currency" underlined size="sm" />.
253
+ </UText>
257
254
  </template>
258
255
  </UInputNumber>
259
256
 
@@ -263,16 +260,13 @@ export const Slots: StoryFn<UInputNumberArgs> = (args) => ({
263
260
  :error="true"
264
261
  >
265
262
  <template #error>
266
- <URow align="center" gap="2xs">
267
- <UIcon name="error" size="xs" color="error" />
268
- <UText size="sm" color="error">
269
- <ul>
270
- <li>Value is outside the allowed range</li>
271
- <li>Use up to two decimal places for this currency</li>
272
- <li>Enter a number greater than zero</li>
273
- </ul>
274
- </UText>
275
- </URow>
263
+ <UText size="sm" color="error">
264
+ <ul>
265
+ <li>Value is outside the allowed range</li>
266
+ <li>Use up to two decimal places for this currency</li>
267
+ <li>Enter a number greater than zero</li>
268
+ </ul>
269
+ </UText>
276
270
  </template>
277
271
  </UInputNumber>
278
272
  </URow>
@@ -210,13 +210,10 @@ export const Slots: StoryFn<UInputPasswordArgs> = (args) => ({
210
210
  label="Password"
211
211
  >
212
212
  <template #description>
213
- <URow align="center" gap="2xs" class="text-neutral">
214
- <UIcon name="shield" size="xs" color="primary" />
215
- <UText size="sm">
216
- Minimum 8 characters.
217
- <ULink label="Password rules" underlined size="sm" />.
218
- </UText>
219
- </URow>
213
+ <UText size="sm" variant="lifted">
214
+ Minimum 8 characters, see
215
+ <ULink label="password rules" underlined size="sm" />.
216
+ </UText>
220
217
  </template>
221
218
  </UInputPassword>
222
219
 
@@ -226,16 +223,13 @@ export const Slots: StoryFn<UInputPasswordArgs> = (args) => ({
226
223
  :error="true"
227
224
  >
228
225
  <template #error>
229
- <URow align="center" gap="2xs">
230
- <UIcon name="error" size="xs" color="error" />
231
- <UText size="sm" color="error">
232
- <ul>
233
- <li>Password does not meet strength requirements</li>
234
- <li>Use at least 8 characters with mixed case and numbers</li>
235
- <li>Avoid common words and repeated characters</li>
236
- </ul>
237
- </UText>
238
- </URow>
226
+ <UText size="sm" color="error">
227
+ <ul>
228
+ <li>Password does not meet strength requirements</li>
229
+ <li>Use at least 8 characters with mixed case and numbers</li>
230
+ <li>Avoid common words and repeated characters</li>
231
+ </ul>
232
+ </UText>
239
233
  </template>
240
234
  </UInputPassword>
241
235
  </URow>
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { computed, ref, useTemplateRef } from "vue";
2
+ import { computed, ref, useId, useTemplateRef } from "vue";
3
3
 
4
4
  import { useUI } from "../composables/useUI";
5
5
  import { hasSlotContent } from "../utils/helper";
@@ -27,6 +27,7 @@ const emit = defineEmits([
27
27
  ]);
28
28
 
29
29
  const wrapperRef = useTemplateRef<HTMLDivElement>("wrapper");
30
+ const instanceId = useId();
30
31
 
31
32
  const hovered = ref<number | null>(null);
32
33
  const preventHover = ref(false);
@@ -66,6 +67,10 @@ function onMouseHover(overStar: number | null = null) {
66
67
  }
67
68
  }
68
69
 
70
+ function getStarInputId(index: number) {
71
+ return `${props.id ?? instanceId}-${index}`;
72
+ }
73
+
69
74
  defineExpose({
70
75
  /**
71
76
  * A reference to the component's wrapper element for direct DOM manipulation.
@@ -112,13 +117,13 @@ const {
112
117
  v-for="(star, index) in stars"
113
118
  :key="star"
114
119
  tabindex="0"
115
- :for="String(index)"
120
+ :for="getStarInputId(index)"
116
121
  v-bind="starLabelAttrs"
117
122
  @keydown.enter="onClickStar(star)"
118
123
  @keydown.space.prevent="onClickStar(star)"
119
124
  >
120
125
  <input
121
- :id="String(index)"
126
+ :id="getStarInputId(index)"
122
127
  tabindex="-1"
123
128
  type="radio"
124
129
  :disabled="disabled"