vueless 1.3.1-beta.1 → 1.3.2-beta.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 (78) hide show
  1. package/icons/internal/progress_activity.svg +1 -0
  2. package/package.json +1 -1
  3. package/ui.container-accordion/tests/UAccordion.test.ts +6 -9
  4. package/ui.container-accordion-item/tests/UAccordionItem.test.ts +18 -41
  5. package/ui.container-card/config.ts +2 -0
  6. package/ui.container-card/tests/UCard.test.ts +14 -31
  7. package/ui.container-card/types.ts +1 -1
  8. package/ui.container-col/tests/UCol.test.ts +11 -25
  9. package/ui.container-drawer/config.ts +1 -0
  10. package/ui.container-drawer/types.ts +1 -1
  11. package/ui.container-group/tests/UGroup.test.ts +12 -26
  12. package/ui.container-groups/tests/UGroups.test.ts +4 -11
  13. package/ui.container-modal/UModal.vue +1 -1
  14. package/ui.container-modal/config.ts +2 -1
  15. package/ui.container-modal/types.ts +1 -1
  16. package/ui.container-modal-confirm/UModalConfirm.vue +2 -2
  17. package/ui.container-modal-confirm/tests/UModalConfirm.test.ts +28 -57
  18. package/ui.container-modal-confirm/types.ts +1 -1
  19. package/ui.container-page/config.ts +2 -0
  20. package/ui.container-page/tests/UPage.test.ts +18 -38
  21. package/ui.container-page/types.ts +1 -1
  22. package/ui.container-row/tests/URow.test.ts +11 -25
  23. package/ui.form-calendar/config.ts +0 -1
  24. package/ui.form-checkbox/config.ts +14 -15
  25. package/ui.form-checkbox/storybook/docs.mdx +0 -16
  26. package/ui.form-checkbox/storybook/optionKeys.mdx +17 -0
  27. package/ui.form-checkbox/storybook/stories.ts +1 -3
  28. package/ui.form-checkbox-group/storybook/docs.mdx +2 -2
  29. package/ui.form-checkbox-multi-state/storybook/docs.mdx +3 -0
  30. package/ui.loader/ULoader.vue +10 -2
  31. package/ui.loader/config.ts +14 -1
  32. package/ui.loader/storybook/stories.ts +4 -1
  33. package/ui.loader/tests/ULoader.test.ts +74 -17
  34. package/ui.loader/types.ts +5 -0
  35. package/ui.loader-overlay/tests/ULoaderOverlay.test.ts +6 -15
  36. package/ui.loader-progress/tests/ULoaderProgress.test.ts +8 -18
  37. package/ui.navigation-breadcrumbs/tests/UBreadcrumbs.test.ts +18 -40
  38. package/ui.navigation-pagination/tests/UPagination.test.ts +18 -40
  39. package/ui.navigation-progress/tests/UProgress.test.ts +11 -25
  40. package/ui.navigation-tab/tests/UTab.test.ts +21 -46
  41. package/ui.navigation-tabs/tests/UTabs.test.ts +13 -30
  42. package/ui.other-chip/tests/UChip.test.ts +13 -29
  43. package/ui.other-dot/tests/UDot.test.ts +4 -10
  44. package/ui.other-theme-color-toggle/tests/UThemeColorToggle.test.ts +13 -29
  45. package/ui.skeleton/USkeleton.vue +6 -6
  46. package/ui.skeleton/config.ts +1 -13
  47. package/ui.skeleton/storybook/stories.ts +3 -20
  48. package/ui.skeleton/tests/USkeleton.test.ts +2 -27
  49. package/ui.skeleton/types.ts +0 -5
  50. package/ui.skeleton-choice/USkeletonChoice.vue +8 -8
  51. package/ui.skeleton-choice/config.ts +0 -1
  52. package/ui.skeleton-choice/storybook/stories.ts +3 -6
  53. package/ui.skeleton-choice/tests/USkeletonChoice.test.ts +7 -35
  54. package/ui.skeleton-choice/types.ts +0 -5
  55. package/ui.skeleton-input/USkeletonInput.vue +11 -10
  56. package/ui.skeleton-input/config.ts +0 -1
  57. package/ui.skeleton-input/storybook/stories.ts +4 -7
  58. package/ui.skeleton-input/tests/USkeletonInput.test.ts +11 -48
  59. package/ui.skeleton-input/types.ts +0 -5
  60. package/ui.skeleton-text/USkeletonText.vue +8 -8
  61. package/ui.skeleton-text/config.ts +2 -2
  62. package/ui.skeleton-text/storybook/stories.ts +1 -4
  63. package/ui.skeleton-text/tests/USkeletonText.test.ts +5 -32
  64. package/ui.skeleton-text/types.ts +0 -5
  65. package/ui.text-alert/tests/UAlert.test.ts +17 -38
  66. package/ui.text-badge/tests/UBadge.test.ts +19 -42
  67. package/ui.text-block/UText.vue +7 -7
  68. package/ui.text-block/config.ts +8 -7
  69. package/ui.text-block/storybook/stories.ts +13 -25
  70. package/ui.text-block/tests/UText.test.ts +27 -28
  71. package/ui.text-block/types.ts +6 -1
  72. package/ui.text-empty/tests/UEmpty.test.ts +14 -31
  73. package/ui.text-file/tests/UFile.test.ts +13 -30
  74. package/ui.text-files/tests/UFiles.test.ts +14 -32
  75. package/ui.text-header/config.ts +2 -0
  76. package/ui.text-header/tests/UHeader.test.ts +10 -23
  77. package/ui.text-notify/tests/UNotify.test.ts +12 -26
  78. package/ui.text-number/tests/UNumber.test.ts +16 -35
@@ -28,15 +28,14 @@ const mountWithRouter = (component: unknown, options: UnknownObject) => {
28
28
  };
29
29
 
30
30
  describe("UPage.vue", () => {
31
- // Props tests
32
31
  describe("Props", () => {
33
- // Variant prop
34
- it("applies correct variant classes", () => {
32
+ it("Variant – applies correct variant classes", () => {
35
33
  const variants = {
36
34
  solid: "bg-default border-transparent",
37
35
  outlined: "bg-default border-muted",
38
36
  subtle: "bg-muted border-default/50",
39
37
  soft: "bg-muted border-transparent",
38
+ inverted: "bg-inverted border-transparent",
40
39
  };
41
40
 
42
41
  Object.entries(variants).forEach(([variant, classes]) => {
@@ -51,8 +50,7 @@ describe("UPage.vue", () => {
51
50
  });
52
51
  });
53
52
 
54
- // Size prop
55
- it("applies correct size classes", () => {
53
+ it("Size – applies correct size classes", () => {
56
54
  const sizeClasses = {
57
55
  xs: "md:w-[25rem]",
58
56
  sm: "md:w-[31.25rem]",
@@ -77,8 +75,7 @@ describe("UPage.vue", () => {
77
75
  });
78
76
  });
79
77
 
80
- // TitleSize prop
81
- it("applies correct titleSize to the header", () => {
78
+ it("Title Size – applies correct titleSize to the header", () => {
82
79
  const titleSizes = ["xs", "sm", "md", "lg", "xl", "2xl"];
83
80
  const title = "Test Title";
84
81
 
@@ -97,8 +94,7 @@ describe("UPage.vue", () => {
97
94
  });
98
95
  });
99
96
 
100
- // Rounding prop
101
- it("applies correct rounding classes", () => {
97
+ it("Rounding – applies correct rounding classes", () => {
102
98
  const variants = {
103
99
  true: "border-r-0",
104
100
  false: "rounded-large",
@@ -119,8 +115,7 @@ describe("UPage.vue", () => {
119
115
  });
120
116
  });
121
117
 
122
- // Title prop
123
- it("renders the title correctly", () => {
118
+ it("Title – renders the title correctly", () => {
124
119
  const title = "Test Title";
125
120
 
126
121
  const component = mount(UPage, {
@@ -136,8 +131,7 @@ describe("UPage.vue", () => {
136
131
  expect(header.props("label")).toBe(title);
137
132
  });
138
133
 
139
- // Description prop
140
- it("renders the description correctly", () => {
134
+ it("Description – renders the description correctly", () => {
141
135
  const description = "Test Description";
142
136
 
143
137
  const component = mount(UPage, {
@@ -153,8 +147,7 @@ describe("UPage.vue", () => {
153
147
  expect(descriptionElement.text()).toBe(description);
154
148
  });
155
149
 
156
- // BackTo and BackLabel props
157
- it("renders back link correctly", () => {
150
+ it("Back To renders back link correctly", () => {
158
151
  // Need to provide a valid RouteLocationRaw object
159
152
  const backTo = { path: "/back" };
160
153
  const backLabel = "Back";
@@ -174,8 +167,7 @@ describe("UPage.vue", () => {
174
167
  expect(backLink.props("label")).toBe(backLabel);
175
168
  });
176
169
 
177
- // DataTest prop
178
- it("applies the correct data-test attribute", () => {
170
+ it("Data Test – applies the correct data-test attribute", () => {
179
171
  const dataTest = "page-test";
180
172
 
181
173
  const component = mount(UPage, {
@@ -188,10 +180,8 @@ describe("UPage.vue", () => {
188
180
  });
189
181
  });
190
182
 
191
- // Slots tests
192
183
  describe("Slots", () => {
193
- // Default slot
194
- it("renders content in default slot", () => {
184
+ it("Default – renders content in default slot", () => {
195
185
  const slotContent = "Default Content";
196
186
  const slotClass = "default-content";
197
187
 
@@ -205,8 +195,7 @@ describe("UPage.vue", () => {
205
195
  expect(component.text()).toContain(slotContent);
206
196
  });
207
197
 
208
- // Before-title slot
209
- it("renders content in before-title slot", () => {
198
+ it("Before-title – renders content in before-title slot", () => {
210
199
  const slotContent = "Before Title Content";
211
200
  const slotClass = "before-title-content";
212
201
 
@@ -220,8 +209,7 @@ describe("UPage.vue", () => {
220
209
  expect(component.text()).toContain(slotContent);
221
210
  });
222
211
 
223
- // Title slot
224
- it("renders content in title slot", () => {
212
+ it("Title – renders content in title slot", () => {
225
213
  const slotContent = "Title Content";
226
214
  const slotClass = "title-content";
227
215
 
@@ -235,8 +223,7 @@ describe("UPage.vue", () => {
235
223
  expect(component.text()).toContain(slotContent);
236
224
  });
237
225
 
238
- // After-title slot
239
- it("renders content in after-title slot", () => {
226
+ it("After-title – renders content in after-title slot", () => {
240
227
  const slotContent = "After Title Content";
241
228
  const slotClass = "after-title-content";
242
229
 
@@ -250,8 +237,7 @@ describe("UPage.vue", () => {
250
237
  expect(component.text()).toContain(slotContent);
251
238
  });
252
239
 
253
- // Actions slot
254
- it("renders content in actions slot", () => {
240
+ it("Actions – renders content in actions slot", () => {
255
241
  const slotContent = "Actions Content";
256
242
  const slotClass = "actions-content";
257
243
 
@@ -265,8 +251,7 @@ describe("UPage.vue", () => {
265
251
  expect(component.text()).toContain(slotContent);
266
252
  });
267
253
 
268
- // Footer-left slot
269
- it("renders content in footer-left slot", () => {
254
+ it("Footer-left – renders content in footer-left slot", () => {
270
255
  const slotContent = "Footer Left Content";
271
256
  const slotClass = "footer-left-content";
272
257
 
@@ -280,8 +265,7 @@ describe("UPage.vue", () => {
280
265
  expect(component.text()).toContain(slotContent);
281
266
  });
282
267
 
283
- // Footer-right slot
284
- it("renders content in footer-right slot", () => {
268
+ it("Footer-right – renders content in footer-right slot", () => {
285
269
  const slotContent = "Footer Right Content";
286
270
  const slotClass = "footer-right-content";
287
271
 
@@ -296,10 +280,8 @@ describe("UPage.vue", () => {
296
280
  });
297
281
  });
298
282
 
299
- // Events tests
300
283
  describe("Events", () => {
301
- // Back event
302
- it("emits back event when back link is clicked", async () => {
284
+ it("Back – emits back event when back link is clicked", async () => {
303
285
  const component = mountWithRouter(UPage, {
304
286
  props: {
305
287
  title: "Test Title", // Need a title to make isExistHeader true
@@ -318,10 +300,8 @@ describe("UPage.vue", () => {
318
300
  });
319
301
  });
320
302
 
321
- // Exposed refs tests
322
303
  describe("Exposed refs", () => {
323
- // wrapperRef
324
- it("exposes wrapperRef", () => {
304
+ it("wrapperRef – exposes wrapperRef", () => {
325
305
  const component = mount(UPage);
326
306
 
327
307
  expect(component.vm.wrapperRef).toBeDefined();
@@ -34,7 +34,7 @@ export interface Props {
34
34
  /**
35
35
  * Page variant.
36
36
  */
37
- variant?: "solid" | "outlined" | "subtle" | "soft";
37
+ variant?: "solid" | "outlined" | "subtle" | "soft" | "inverted";
38
38
 
39
39
  /**
40
40
  * Page size (width).
@@ -6,10 +6,8 @@ import URow from "../URow.vue";
6
6
  import type { Props } from "../types";
7
7
 
8
8
  describe("URow.vue", () => {
9
- // Props tests
10
9
  describe("Props", () => {
11
- // Gap prop
12
- it("applies the correct gap class", () => {
10
+ it("Gap – applies the correct gap class", () => {
13
11
  const gapClasses = {
14
12
  none: "gap-0",
15
13
  "2xs": "gap-1",
@@ -32,8 +30,7 @@ describe("URow.vue", () => {
32
30
  });
33
31
  });
34
32
 
35
- // Align prop
36
- it("applies the correct align class", () => {
33
+ it("Align – applies the correct align class", () => {
37
34
  const alignClasses = {
38
35
  end: "items-end",
39
36
  start: "items-start",
@@ -53,8 +50,7 @@ describe("URow.vue", () => {
53
50
  });
54
51
  });
55
52
 
56
- // Content prop
57
- it("applies the correct content class", () => {
53
+ it("Content – applies the correct content class", () => {
58
54
  const contentClasses = {
59
55
  end: "content-end",
60
56
  start: "content-start",
@@ -78,8 +74,7 @@ describe("URow.vue", () => {
78
74
  });
79
75
  });
80
76
 
81
- // Justify prop
82
- it("applies the correct justify class", () => {
77
+ it("Justify – applies the correct justify class", () => {
83
78
  const justifyClasses = {
84
79
  end: "justify-end",
85
80
  start: "justify-start",
@@ -100,8 +95,7 @@ describe("URow.vue", () => {
100
95
  });
101
96
  });
102
97
 
103
- // Reverse prop
104
- it("applies the correct reverse class", () => {
98
+ it("Reverse – applies the correct reverse class", () => {
105
99
  const reverseClasses = {
106
100
  false: "flex-row",
107
101
  true: "flex-row-reverse",
@@ -118,8 +112,7 @@ describe("URow.vue", () => {
118
112
  });
119
113
  });
120
114
 
121
- // Wrap prop
122
- it("applies the correct wrap class", () => {
115
+ it("Wrap – applies the correct wrap class", () => {
123
116
  const wrap = true;
124
117
  const expectedClasses = "flex-wrap";
125
118
 
@@ -132,8 +125,7 @@ describe("URow.vue", () => {
132
125
  expect(component.attributes("class")).toContain(expectedClasses);
133
126
  });
134
127
 
135
- // Block prop
136
- it("applies the correct block class", () => {
128
+ it("Block – applies the correct block class", () => {
137
129
  const block = true;
138
130
  const expectedClasses = "w-full";
139
131
 
@@ -146,8 +138,7 @@ describe("URow.vue", () => {
146
138
  expect(component.attributes("class")).toContain(expectedClasses);
147
139
  });
148
140
 
149
- // Tag prop
150
- it("renders the correct HTML tag", () => {
141
+ it("Tag – renders the correct HTML tag", () => {
151
142
  const tags = ["div", "section", "article", "main", "aside", "nav", "span"];
152
143
 
153
144
  tags.forEach((tag) => {
@@ -161,8 +152,7 @@ describe("URow.vue", () => {
161
152
  });
162
153
  });
163
154
 
164
- // DataTest prop
165
- it("applies the correct data-test attribute", () => {
155
+ it("Data Test – applies the correct data-test attribute", () => {
166
156
  const dataTest = "test-row";
167
157
 
168
158
  const component = mount(URow, {
@@ -175,10 +165,8 @@ describe("URow.vue", () => {
175
165
  });
176
166
  });
177
167
 
178
- // Slots tests
179
168
  describe("Slots", () => {
180
- // Default slot
181
- it("renders content from default slot", () => {
169
+ it("Default – renders content from default slot", () => {
182
170
  const slotContent = "Custom Content";
183
171
 
184
172
  const component = mount(URow, {
@@ -191,10 +179,8 @@ describe("URow.vue", () => {
191
179
  });
192
180
  });
193
181
 
194
- // Exposed refs tests
195
182
  describe("Exposed refs", () => {
196
- // wrapperRef
197
- it("exposes wrapperRef", () => {
183
+ it("wrapperRef – exposes wrapperRef", () => {
198
184
  const component = mount(URow);
199
185
 
200
186
  expect(component.vm.wrapperRef).toBeDefined();
@@ -159,7 +159,6 @@ export default /*tw*/ {
159
159
  range: false,
160
160
  timepicker: false,
161
161
  /* icons */
162
- viewSwitchIcon: "keyboard_arrow_down",
163
162
  nextYearIcon: "keyboard_double_arrow_right",
164
163
  prevYearIcon: "keyboard_double_arrow_left",
165
164
  nextIcon: "keyboard_arrow_right",
@@ -1,9 +1,18 @@
1
1
  export default /*tw*/ {
2
2
  checkboxLabel: "{ULabel}",
3
+ checkboxBase: {
4
+ base: "rounded-small cursor-pointer transition",
5
+ variants: {
6
+ size: {
7
+ sm: "size-4 -ml-4",
8
+ md: "size-5 -ml-5",
9
+ lg: "size-6 -ml-6",
10
+ },
11
+ },
12
+ },
3
13
  checkbox: {
4
14
  base: `
5
- bg-default cursor-pointer transition
6
- border border-solid border-default rounded-small outline-transparent
15
+ {>checkboxBase} ml-0 bg-default border border-solid border-default outline-transparent
7
16
  appearance-none p-0 print:color-adjust-exact inline-block align-middle bg-origin-border select-none shrink-0
8
17
  hover:border-lifted
9
18
  active:border-{color} active:bg-{color}/15
@@ -13,11 +22,6 @@ export default /*tw*/ {
13
22
  disabled:checked:bg-{color}/(--vl-disabled-opacity) disabled:checked:border-transparent
14
23
  `,
15
24
  variants: {
16
- size: {
17
- sm: "size-4",
18
- md: "size-5",
19
- lg: "size-6",
20
- },
21
25
  error: {
22
26
  true: "!border-error focus-visible:outline-error",
23
27
  },
@@ -25,21 +29,15 @@ export default /*tw*/ {
25
29
  },
26
30
  checked: {
27
31
  base: `
28
- flex items-center justify-center absolute rounded-small cursor-pointer transition
32
+ {>checkboxBase} flex items-center justify-center relative
29
33
  bg-{color} hover:bg-{color}-lifted active:bg-{color}-accented
30
34
  `,
31
35
  variants: {
32
- size: {
33
- sm: "size-4",
34
- md: "size-5",
35
- lg: "size-6",
36
- },
37
36
  disabled: {
38
37
  true: "!bg-{color}/(--vl-disabled-opacity) cursor-not-allowed",
39
38
  },
40
39
  },
41
40
  },
42
- partiallyChecked: "{>checked}",
43
41
  checkedIcon: {
44
42
  base: "{UIcon} text-inverted",
45
43
  defaults: {
@@ -50,9 +48,10 @@ export default /*tw*/ {
50
48
  },
51
49
  },
52
50
  },
51
+ partiallyChecked: "{>checked}",
53
52
  partiallyCheckedIcon: "{>checkedIcon}",
54
- /* These are used for a11y. */
55
53
  i18n: {
54
+ /* These are used for a11y. */
56
55
  checkbox: "Checkbox",
57
56
  },
58
57
  defaults: {
@@ -12,21 +12,5 @@ import defaultConfig from "../config?raw"
12
12
  <Controls of={stories.Default} />
13
13
  <Stories of={stories} />
14
14
 
15
- ## Option meta keys
16
- Keys you may/have to provide to the component in an option object.
17
-
18
- <Markdown>
19
- {`
20
- | Key name | Description | Type |
21
- | ------------------| ---------------------------------------| ---------------------------------------|
22
- | value | Native value attribute | Boolean, String, Number, Array, Object |
23
- | trueValue | Own value for checkbox checked state | Boolean, String, Number, Array, Object |
24
- | falseValue | Own value for checkbox unchecked state | Boolean, String, Number, Array, Object |
25
- | label | Option label | String |
26
- | icon | Option icon | String |
27
- | description | Option description | Number |
28
- `}
29
- </Markdown>
30
-
31
15
  ## Default config
32
16
  <Source code={getSource(defaultConfig)} language="jsx" dark />
@@ -0,0 +1,17 @@
1
+ import { Markdown } from "@storybook/addon-docs/blocks";
2
+
3
+ ## Option meta keys
4
+ Keys you may/have to provide to the component in an option object.
5
+
6
+ <Markdown>
7
+ {`
8
+ | Key name | Description | Type |
9
+ | ------------------| ---------------------------------------| ---------------------------------------|
10
+ | value | Native value attribute | Boolean, String, Number, Array, Object |
11
+ | trueValue | Own value for checkbox checked state | Boolean, String, Number, Array, Object |
12
+ | falseValue | Own value for checkbox unchecked state | Boolean, String, Number, Array, Object |
13
+ | label | Option label | String |
14
+ | icon | Option icon | String |
15
+ | description | Option description | Number |
16
+ `}
17
+ </Markdown>
@@ -158,9 +158,7 @@ export const BottomSlot = DefaultTemplate.bind({});
158
158
  BottomSlot.args = {
159
159
  slotTemplate: `
160
160
  <template #bottom>
161
- <UChip icon="arrow_outward" size="sm" class="mt-2">
162
- <ULink label="Learn more" size="sm" class="mr-1.5" />
163
- </UChip>
161
+ <ULink label="Learn more" size="sm" class="mr-1.5" />
164
162
  </template>
165
163
  `,
166
164
  };
@@ -3,6 +3,7 @@ import { getSource } from "../../utils/storybook";
3
3
 
4
4
  import * as stories from "./stories";
5
5
  import defaultConfig from "../config?raw"
6
+ import CheckboxOptionKeys from "../../ui.form-checkbox/storybook/optionKeys.mdx"
6
7
 
7
8
  <Meta of={stories} />
8
9
  <Title of={stories} />
@@ -12,8 +13,7 @@ import defaultConfig from "../config?raw"
12
13
  <Controls of={stories.Default} />
13
14
  <Stories of={stories} />
14
15
 
15
- ## Option meta keys
16
- Full list of keys you may/have to provide to the component in an option object can be found here: <a href="https://ui.vueless.com/?path=/docs/3100--docs" target="_blank">UCheckbox docs</a>.
16
+ <CheckboxOptionKeys />
17
17
 
18
18
  ## Default config
19
19
  <Source code={getSource(defaultConfig)} language="jsx" dark />
@@ -3,6 +3,7 @@ import { getSource } from "../../utils/storybook";
3
3
 
4
4
  import * as stories from "./stories";
5
5
  import defaultConfig from "../config?raw"
6
+ import CheckboxOptionKeys from "../../ui.form-checkbox/storybook/optionKeys.mdx"
6
7
 
7
8
  <Meta of={stories} />
8
9
  <Title of={stories} />
@@ -12,5 +13,7 @@ import defaultConfig from "../config?raw"
12
13
  <Controls of={stories.Default} />
13
14
  <Stories of={stories} />
14
15
 
16
+ <CheckboxOptionKeys />
17
+
15
18
  ## Default config
16
19
  <Source code={getSource(defaultConfig)} language="jsx" dark />
@@ -4,6 +4,8 @@ import { useTemplateRef } from "vue";
4
4
  import { useUI } from "../composables/useUI";
5
5
  import { getDefaults } from "../utils/ui";
6
6
 
7
+ import UIcon from "../ui.image-icon/UIcon.vue";
8
+
7
9
  import { COMPONENT_NAME, ELLIPSES_AMOUNT } from "./constants";
8
10
  import defaultConfig from "./config";
9
11
 
@@ -29,7 +31,8 @@ defineExpose({
29
31
  * Get element / nested component attributes for each config token ✨
30
32
  * Applies: `class`, `config`, redefined default `props` and dev `vl-...` attributes.
31
33
  */
32
- const { getDataTest, config, loaderAttrs, ellipseAttrs } = useUI<Config>(defaultConfig);
34
+ const { getDataTest, config, loaderAttrs, ellipseAttrs, spinnerIconAttrs } =
35
+ useUI<Config>(defaultConfig);
33
36
  </script>
34
37
 
35
38
  <template>
@@ -37,7 +40,12 @@ const { getDataTest, config, loaderAttrs, ellipseAttrs } = useUI<Config>(default
37
40
  <div v-if="loading" ref="loader" v-bind="loaderAttrs" :data-test="getDataTest()">
38
41
  <!-- @slot Use it to add something instead of the default loader. -->
39
42
  <slot>
40
- <div v-for="ellipse in ELLIPSES_AMOUNT" :key="ellipse" v-bind="ellipseAttrs" />
43
+ <template v-if="variant === 'spinner'">
44
+ <UIcon :name="config.defaults.spinnerIcon" :color="color" v-bind="spinnerIconAttrs" />
45
+ </template>
46
+ <template v-else>
47
+ <div v-for="ellipse in ELLIPSES_AMOUNT" :key="ellipse" v-bind="ellipseAttrs" />
48
+ </template>
41
49
  </slot>
42
50
  </div>
43
51
  </Transition>
@@ -1,6 +1,6 @@
1
1
  export default /*tw*/ {
2
2
  loader: {
3
- base: "relative flex items-center",
3
+ base: "relative flex items-center justify-center",
4
4
  variants: {
5
5
  size: {
6
6
  sm: "h-1.5 w-9",
@@ -49,9 +49,22 @@ export default /*tw*/ {
49
49
  },
50
50
  },
51
51
  },
52
+ spinnerIcon: {
53
+ base: "{UIcon} animate-spin",
54
+ defaults: {
55
+ size: {
56
+ sm: "sm",
57
+ md: "md",
58
+ lg: "lg",
59
+ },
60
+ },
61
+ },
52
62
  defaults: {
53
63
  color: "primary",
64
+ variant: "dots",
54
65
  size: "md",
55
66
  loading: false,
67
+ /* icons */
68
+ spinnerIcon: "progress_activity",
56
69
  },
57
70
  };
@@ -16,7 +16,7 @@ import type { Props } from "../types";
16
16
 
17
17
  interface ULoaderArgs extends Props {
18
18
  slotTemplate?: string;
19
- enum: "size" | "color";
19
+ enum: "size" | "color" | "variant";
20
20
  }
21
21
 
22
22
  export default {
@@ -82,6 +82,9 @@ const LoadingTemplate: StoryFn<ULoaderArgs> = (args: ULoaderArgs) => ({
82
82
  export const Default = DefaultTemplate.bind({});
83
83
  Default.args = {};
84
84
 
85
+ export const Variants = EnumTemplate.bind({});
86
+ Variants.args = { enum: "variant" };
87
+
85
88
  export const Sizes = EnumTemplate.bind({});
86
89
  Sizes.args = { enum: "size" };
87
90