vueless 0.0.808 → 0.0.809

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "0.0.808",
3
+ "version": "0.0.809",
4
4
  "license": "MIT",
5
5
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
6
6
  "keywords": [
@@ -29,20 +29,6 @@ const emit = defineEmits([
29
29
  * @property {array} sortData
30
30
  */
31
31
  "dragSort",
32
-
33
- /**
34
- * Triggers when edit button is clicked.
35
- * @property {number} value
36
- * @property {string} label
37
- */
38
- "clickEdit",
39
-
40
- /**
41
- * Triggers when delete button is clicked.
42
- * @property {number} value
43
- * @property {string} label
44
- */
45
- "clickDelete",
46
32
  ]);
47
33
 
48
34
  const { tm } = useLocale();
@@ -50,13 +36,13 @@ const { tm } = useLocale();
50
36
  const i18nGlobal = tm(COMPONENT_NAME);
51
37
  const currentLocale = computed(() => merge({}, defaultConfig.i18n, i18nGlobal, props.config.i18n));
52
38
 
53
- function isActive(element: DataListItem) {
54
- return element.isActive === undefined || element.isActive;
39
+ function isCrossed(element: DataListItem) {
40
+ return Boolean(element.crossed);
55
41
  }
56
42
 
57
43
  function onDragMove(event: DragMoveEvent): boolean | void {
58
- const isDisabledNestingItem = event.draggedContext.element.isDisabledNesting;
59
- const isNestingAction = !event.relatedContext?.element?.isDisabledNesting;
44
+ const isDisabledNestingItem = !Boolean(event.draggedContext.element.nesting);
45
+ const isNestingAction = Boolean(event.relatedContext?.element?.nesting);
60
46
 
61
47
  if (isDisabledNestingItem && isNestingAction) {
62
48
  return false;
@@ -69,14 +55,6 @@ function onDragEnd() {
69
55
  emit("dragSort", sortData);
70
56
  }
71
57
 
72
- function onClickEdit(value: number, label: string) {
73
- emit("clickEdit", value, label);
74
- }
75
-
76
- function onClickDelete(value: number, label: string) {
77
- emit("clickDelete", value, label);
78
- }
79
-
80
58
  function prepareSortData(list: DataListItem[] = [], parentValue: string | number | null = null) {
81
59
  const sortData: DataListItem[] = [];
82
60
 
@@ -116,28 +94,27 @@ const {
116
94
  labelAttrs,
117
95
  labelCrossedAttrs,
118
96
  customActionsAttrs,
119
- deleteIconAttrs,
120
- editIconAttrs,
121
97
  dragIconAttrs,
98
+ dragAttrs,
122
99
  } = useUI<Config>(defaultConfig);
123
100
  </script>
124
101
 
125
102
  <template>
126
103
  <div v-bind="wrapperAttrs">
127
104
  <!--
128
- @slot Use it to add something instead of the drag icon.
105
+ @slot Use it to add custom empty state.
129
106
  @binding {string} empty-title
130
107
  @binding {string} empty-description
131
108
  -->
132
109
  <slot
133
110
  v-if="!hideEmptyStateForNesting && !list?.length"
134
111
  name="empty"
135
- :empty-title="emptyTitle"
136
- :empty-description="emptyDescription"
112
+ :empty-title="currentLocale.emptyTitle"
113
+ :empty-description="currentLocale.emptyDescription"
137
114
  >
138
115
  <UEmpty
139
- :title="emptyTitle || currentLocale.emptyTitle"
140
- :description="emptyDescription || currentLocale.emptyDescription"
116
+ :title="currentLocale.emptyTitle"
117
+ :description="currentLocale.emptyDescription"
141
118
  v-bind="emptyAttrs"
142
119
  />
143
120
  </slot>
@@ -159,105 +136,64 @@ const {
159
136
  <template #item="{ element }">
160
137
  <div :id="element[valueKey]" v-bind="itemWrapperAttrs" :data-test="getDataTest('item')">
161
138
  <div v-bind="itemAttrs" :data-test="getDataTest(`item-${element[valueKey]}`)">
162
- <!--
163
- @slot Use it to add something instead of the drag icon.
164
- @binding {object} item
165
- @binding {string} icon-name
166
- -->
167
- <slot name="drag" :item="element" :icon-name="config.defaults.dragIcon">
168
- <UIcon
169
- internal
170
- color="gray"
171
- variant="light"
172
- :name="config.defaults.dragIcon"
173
- v-bind="dragIconAttrs"
174
- />
175
- </slot>
139
+ <div v-bind="dragAttrs">
140
+ <!--
141
+ @slot Use it to add something instead of the drag icon.
142
+ @binding {object} item
143
+ @binding {string} icon-name
144
+ -->
145
+ <slot name="drag" :item="element" :icon-name="config.defaults.dragIcon">
146
+ <UIcon
147
+ internal
148
+ color="gray"
149
+ variant="light"
150
+ :name="config.defaults.dragIcon"
151
+ v-bind="dragIconAttrs"
152
+ />
153
+ </slot>
154
+ </div>
176
155
 
177
- <div v-bind="isActive(element) ? labelAttrs : labelCrossedAttrs">
156
+ <div v-bind="isCrossed(element) ? labelCrossedAttrs : labelAttrs">
178
157
  <!--
179
158
  @slot Use it to modify label.
180
159
  @binding {object} item
181
- @binding {boolean} active
160
+ @binding {boolean} crossed
182
161
  -->
183
- <slot name="label" :item="element" :active="isActive(element)">
162
+ <slot name="label" :item="element" :crossed="isCrossed(element)">
184
163
  {{ element[labelKey] }}
185
164
  </slot>
186
165
  </div>
187
166
 
188
- <template v-if="!element.isHiddenActions">
189
- <div
190
- v-if="hasSlotContent($slots['actions']) && !element.isHiddenCustomActions"
191
- v-bind="customActionsAttrs"
192
- >
167
+ <template v-if="element.actions !== false">
168
+ <div v-if="hasSlotContent($slots['actions'])" v-bind="customActionsAttrs">
193
169
  <!--
194
170
  @slot Use it to add custom actions.
195
171
  @binding {object} item
196
172
  -->
197
173
  <slot name="actions" :item="element" />
198
174
  </div>
199
-
200
- <!--
201
- @slot Use it to add something instead of the delete icon.
202
- @binding {object} item
203
- @binding {string} icon-name
204
- -->
205
- <slot name="delete" :item="element" :icon-name="config.defaults.deleteIcon">
206
- <UIcon
207
- v-if="!element.isHiddenDelete"
208
- internal
209
- interactive
210
- color="red"
211
- :name="config.defaults.deleteIcon"
212
- :tooltip="currentLocale.delete"
213
- v-bind="deleteIconAttrs"
214
- :data-test="getDataTest('delete')"
215
- @click="onClickDelete(element[valueKey], element[labelKey])"
216
- />
217
- </slot>
218
-
219
- <!--
220
- @slot Use it to add something instead of the edit icon.
221
- @binding {object} item
222
- @binding {string} icon-name
223
- -->
224
- <slot name="edit" :item="element" :icon-name="config.defaults.editIcon">
225
- <UIcon
226
- v-if="!element.isHiddenEdit"
227
- internal
228
- interactive
229
- color="gray"
230
- :name="config.defaults.editIcon"
231
- :tooltip="currentLocale.edit"
232
- v-bind="editIconAttrs"
233
- :data-test="getDataTest('edit')"
234
- @click="onClickEdit(element[valueKey], element[labelKey])"
235
- />
236
- </slot>
237
175
  </template>
238
176
  </div>
239
177
 
240
178
  <UDataList
241
- v-if="nesting && !element.isDisabledNesting"
179
+ v-if="nesting && element.nesting"
242
180
  :nesting="nesting"
243
181
  hide-empty-state-for-nesting
244
182
  :list="element.children"
245
183
  :group="group"
246
184
  v-bind="nestedAttrs"
247
185
  :data-test="getDataTest('table')"
248
- @click-delete="onClickDelete"
249
- @click-edit="onClickEdit"
250
186
  @drag-sort="onDragEnd"
251
187
  >
252
- <template #label="slotProps: { item: DataListItem; active: boolean }">
188
+ <template #label="slotProps: { item: DataListItem; crossed: boolean }">
253
189
  <!--
254
190
  @slot Use it to modify label.
255
191
  @binding {object} item
256
- @binding {boolean} active
192
+ @binding {boolean} crossed
257
193
  -->
258
- <slot name="label" :item="slotProps.item" :active="slotProps.active">
194
+ <slot name="label" :item="slotProps.item" :crossed="slotProps.crossed">
259
195
  <div
260
- v-bind="slotProps.active ? labelAttrs : labelCrossedAttrs"
196
+ v-bind="slotProps.crossed ? labelCrossedAttrs : labelAttrs"
261
197
  v-text="slotProps.item[labelKey]"
262
198
  />
263
199
  </slot>
@@ -29,6 +29,7 @@ export default /*tw*/ {
29
29
  },
30
30
  },
31
31
  },
32
+ drag: "icon-drag cursor-move",
32
33
  dragIcon: "{UIcon} {>dataListIcon} icon-drag cursor-move opacity-100",
33
34
  label: {
34
35
  base: "font-normal flex-auto pt-px",
@@ -41,18 +42,11 @@ export default /*tw*/ {
41
42
  },
42
43
  },
43
44
  labelCrossed: "{>label} line-through",
44
- customActions: `
45
- space-x-5 opacity-50 md:flex md:items-center md:opacity-0
46
- group-hover/item:md:block group-hover/item:opacity-100
47
- `,
48
- deleteIcon: "{UIcon} {>dataListIcon} hidden md:block md:opacity-0 group-hover/item:md:opacity-100",
49
- editIcon: "{UIcon} {>dataListIcon} fill-gray-500 opacity-50",
45
+ customActions: "space-x-5 opacity-50 flex items-center md:opacity-0 group-hover/item:opacity-100",
50
46
  divider: "{UDivider}",
51
47
  empty: "{UEmpty}",
52
48
  nested: "{UDataList} group/nested ml-6",
53
49
  i18n: {
54
- edit: "Edit",
55
- delete: "Delete",
56
50
  emptyTitle: "",
57
51
  emptyDescription: "There is no data in the list.",
58
52
  },
@@ -64,7 +58,5 @@ export default /*tw*/ {
64
58
  nesting: false,
65
59
  /* icons */
66
60
  dragIcon: "drag_indicator",
67
- deleteIcon: "delete",
68
- editIcon: "edit_note",
69
61
  },
70
62
  };
@@ -1,4 +1,4 @@
1
- import { Meta, Title, Subtitle, Description, Primary, Controls, Stories, Source } from "@storybook/blocks";
1
+ import { Markdown, Meta, Title, Subtitle, Description, Primary, Controls, Stories, Source } from "@storybook/blocks";
2
2
  import { getSource } from "../../utils/storybook.ts";
3
3
 
4
4
  import * as stories from "./stories.ts";
@@ -13,28 +13,20 @@ import defaultConfig from "../config.ts?raw"
13
13
  <Stories of={stories} />
14
14
 
15
15
  ## Configuring items in a list
16
- You can configure any item in a list by passing the following params.
16
+ You can configure any item in a `list` array by passing the following params:
17
17
 
18
- <Source code={`
19
- <UDataList :list="list" />
20
-
21
- const list = [
22
- {
23
- id: 1, // unique item identifier
24
- label: "Rent", // item label
25
- children: [ // nested items
26
- { label: "Office", id: 11 },
27
- { label: "Shops", id: 12, children: [...] }, // children of subitems
28
- ],
29
- isHiddenEdit: true, // hide edit button
30
- isHiddenDelete: true, // hide delete button
31
- isHiddenActions: true, // hide default and custom action buttons
32
- isHiddenCustomActions: true, // hide only custom action buttons
33
- isDisabledNesting: true, // disable nesting for the item
34
- }
35
- {...}
36
- ];
37
- `} language="jsx" dark />
18
+ <Markdown>
19
+ {`
20
+ | Key name | Description | Type | Default |
21
+ | ----------------------| ------------------------------------------------------ | ---------------| --------|
22
+ | id | Unique item identifier | String, Number | |
23
+ | label | Item label | String | |
24
+ | children | Nested items | Array | |
25
+ | crossed | Controls item style (line-through decoration) | Boolean | false |
26
+ | actions | Show custom actions buttons | Boolean | true |
27
+ | nesting | Enable nesting for the item | Boolean | false |
28
+ `}
29
+ </Markdown>
38
30
 
39
31
  ## Default config
40
32
  <Source code={getSource(defaultConfig)} language="jsx" dark />
@@ -1,3 +1,4 @@
1
+ import { ref } from "vue";
1
2
  import {
2
3
  getArgTypes,
3
4
  getSlotNames,
@@ -9,12 +10,18 @@ import UDataList from "../../ui.data-list/UDataList.vue";
9
10
  import UIcon from "../../ui.image-icon/UIcon.vue";
10
11
  import UButton from "../../ui.button/UButton.vue";
11
12
  import URow from "../../ui.container-row/URow.vue";
13
+ import UBadge from "../../ui.text-badge/UBadge.vue";
14
+ import UAvatar from "../../ui.image-avatar/UAvatar.vue";
15
+ import UHeader from "../../ui.text-header/UHeader.vue";
16
+ import ULoader from "../../ui.loader/ULoader.vue";
17
+ import tooltip from "../../directives/tooltip/vTooltip.ts";
12
18
 
13
19
  import type { Meta, StoryFn } from "@storybook/vue3";
14
- import type { Props } from "../types.ts";
20
+ import type { Props, DataListItem } from "../types.ts";
15
21
 
16
22
  interface UDataListArgs extends Props {
17
23
  slotTemplate?: string;
24
+ enum: "size";
18
25
  }
19
26
 
20
27
  export default {
@@ -24,25 +31,34 @@ export default {
24
31
  args: {
25
32
  list: [
26
33
  {
27
- label: "Salary",
34
+ label: "Expenses",
28
35
  id: 1,
36
+ nesting: true,
29
37
  children: [
30
- { label: "IT", id: 1.1 },
31
- { label: "HR", id: 1.2 },
32
- { label: "C Level", id: 1.3 },
38
+ { label: "Office Supplies", id: 1.1 },
39
+ { label: "Travel & Lodging", id: 1.2 },
40
+ { label: "Utilities", id: 1.3 },
33
41
  ],
34
42
  },
35
43
  {
36
- label: "Rent",
44
+ label: "Revenue Streams",
37
45
  id: 2,
46
+ nesting: true,
38
47
  children: [
39
- { label: "Office", id: 2.1 },
40
- { label: "Shops", id: 2.2 },
48
+ { label: "Product Sales", id: 2.1 },
49
+ { label: "Subscription Services", id: 2.2 },
50
+ { label: "Consulting", id: 2.3 },
41
51
  ],
42
52
  },
43
53
  {
44
- label: "Marketing",
54
+ label: "Departments",
45
55
  id: 3,
56
+ nesting: true,
57
+ children: [
58
+ { label: "Engineering", id: 3.1 },
59
+ { label: "Marketing", id: 3.2 },
60
+ { label: "Finance", id: 3.3 },
61
+ ],
46
62
  },
47
63
  ],
48
64
  },
@@ -57,76 +73,143 @@ export default {
57
73
  } as Meta;
58
74
 
59
75
  const DefaultTemplate: StoryFn<UDataListArgs> = (args: UDataListArgs) => ({
60
- components: { UDataList, UIcon, URow, UButton },
76
+ components: { UDataList, UIcon, URow, UButton, UBadge, UAvatar, ULoader, UHeader },
77
+ directives: { tooltip },
61
78
  setup() {
62
79
  const slots = getSlotNames(UDataList.__name);
63
80
 
64
- return { args, slots };
81
+ const avatars = [
82
+ "https://cdn-icons-png.flaticon.com/128/1999/1999625.png",
83
+ "https://cdn-icons-png.flaticon.com/128/4140/4140057.png",
84
+ "https://cdn-icons-png.flaticon.com/128/4140/4140047.png",
85
+ ];
86
+
87
+ const list = ref(
88
+ args.list?.map((item, index) => ({
89
+ ...item,
90
+ id: item.id,
91
+ avatar: avatars[index % avatars.length],
92
+ })),
93
+ );
94
+
95
+ function removeItem(targetItem: DataListItem) {
96
+ list.value = list.value?.filter((listItem) => listItem.id !== targetItem.id);
97
+
98
+ return alert(`Removed item: ${JSON.stringify(targetItem, null, 2)}`);
99
+ }
100
+
101
+ function editItem(targetItem: DataListItem) {
102
+ alert(`Edit item: ${JSON.stringify(targetItem, null, 2)}`);
103
+ }
104
+
105
+ return { args, slots, removeItem, editItem, list };
65
106
  },
66
107
  template: `
67
- <UDataList v-bind="args">
108
+ <UDataList v-bind="args" :list="args.slotTemplate ? list : args.list">
68
109
  ${args.slotTemplate || getSlotsFragment("")}
69
110
  </UDataList>
70
111
  `,
71
112
  });
72
113
 
114
+ const EnumVariantTemplate: StoryFn<UDataListArgs> = (args: UDataListArgs, { argTypes }) => ({
115
+ components: { URow, UDataList, UHeader },
116
+ setup() {
117
+ return {
118
+ args,
119
+ options: argTypes?.[args.enum]?.options,
120
+ };
121
+ },
122
+ template: `
123
+ <div v-for="(option, index) in options" :key="index">
124
+ <UHeader :label="option" size="xs" />
125
+ <UDataList v-bind="args" :[args.enum]="option" class="mb-4" />
126
+ </div>
127
+ `,
128
+ });
129
+
73
130
  export const Default = DefaultTemplate.bind({});
74
131
  Default.args = {};
75
132
 
76
133
  export const EmptyState = DefaultTemplate.bind({});
77
- EmptyState.args = {
78
- list: [],
79
- emptyTitle: "The list is empty.",
80
- emptyDescription: "There is no data in the list.",
81
- };
134
+ EmptyState.args = { list: [] };
82
135
 
83
136
  export const Nesting = DefaultTemplate.bind({});
84
137
  Nesting.args = { nesting: true };
85
138
 
139
+ export const Size = EnumVariantTemplate.bind({});
140
+ Size.args = { enum: "size" };
141
+
86
142
  export const SlotLabel = DefaultTemplate.bind({});
87
143
  SlotLabel.args = {
88
144
  slotTemplate: `
89
145
  <template #label="{ item }">
90
- <URow gap="xs" align="center">
91
- {{ item.label }}
92
- <UIcon name="check" color="green" size="sm" />
93
- </URow>
146
+ <UBadge :label="item.label" />
94
147
  </template>
95
148
  `,
96
149
  };
97
150
 
98
- export const SlotActions = DefaultTemplate.bind({});
99
- SlotActions.args = {
151
+ export const SlotEmpty = DefaultTemplate.bind({});
152
+ SlotEmpty.args = {
153
+ list: [],
154
+ config: {
155
+ wrapper: "flex flex-col items-center justify-center py-10 gap-4",
156
+ i18n: {
157
+ emptyTitle: "Fetching data...",
158
+ emptyDescription: "Please wait until data is received.",
159
+ },
160
+ },
100
161
  slotTemplate: `
101
- <template #actions>
102
- <UIcon interactive name="star" color="red" />
162
+ <template #empty="{ emptyTitle, emptyDescription }">
163
+ <ULoader loading size="lg" />
164
+ <UHeader :label="emptyTitle" size="xs" />
165
+ <p>{{ emptyDescription }}</p>
103
166
  </template>
104
167
  `,
105
168
  };
169
+ SlotEmpty.parameters = {
170
+ docs: {
171
+ description: {
172
+ story:
173
+ "You can customize the `empty` slot's props (`emptyTitle` and `emptyDescription`) using the `i18n` config key.",
174
+ },
175
+ },
176
+ };
106
177
 
107
178
  export const SlotDrag = DefaultTemplate.bind({});
108
179
  SlotDrag.args = {
180
+ list: [
181
+ { label: "John Doe (Engineering)", id: 1 },
182
+ { label: "Michael Johnson (Finance)", id: 2 },
183
+ { label: "Emma Smith (Marketing)", id: 3 },
184
+ ],
109
185
  slotTemplate: `
110
- <template #drag>
111
- <UIcon interactive name="swap_vert" size="sm" />
186
+ <template #drag="{ item }">
187
+ <UAvatar :src="item.avatar" rounded="full" />
112
188
  </template>
113
189
  `,
114
190
  };
115
191
 
116
- export const SlotDelete = DefaultTemplate.bind({});
117
- SlotDelete.args = {
118
- slotTemplate: `
119
- <template #delete>
120
- <UButton label="Delete" size="xs" variant="secondary" color="red" />
121
- </template>
122
- `,
123
- };
124
-
125
- export const SlotEdit = DefaultTemplate.bind({});
126
- SlotEdit.args = {
192
+ export const SlotActions = DefaultTemplate.bind({});
193
+ SlotActions.args = {
127
194
  slotTemplate: `
128
- <template #edit>
129
- <UButton label="Edit" size="xs" variant="secondary" color="grayscale" />
195
+ <template #actions="{ item }">
196
+ <UButton label="Export" size="xs" />
197
+ <UIcon
198
+ name="delete"
199
+ size="sm"
200
+ color="red"
201
+ interactive
202
+ v-tooltip="'Delete'"
203
+ @click="removeItem(item)"
204
+ />
205
+ <UIcon
206
+ name="edit_note"
207
+ size="sm"
208
+ color="grayscale"
209
+ interactive
210
+ v-tooltip="'Edit'"
211
+ @click="editItem(item)"
212
+ />
130
213
  </template>
131
214
  `,
132
215
  };
@@ -12,12 +12,9 @@ export interface DragMoveEvent extends DragEvent {
12
12
  }
13
13
 
14
14
  export interface DataListItem {
15
- isActive?: boolean;
16
- isHiddenActions?: boolean;
17
- isHiddenCustomActions?: boolean;
18
- isHiddenDelete?: boolean;
19
- isHiddenEdit?: boolean;
20
- isDisabledNesting?: boolean;
15
+ crossed?: boolean;
16
+ actions?: boolean;
17
+ nesting?: boolean;
21
18
  children?: DataListItem[];
22
19
  [key: string]: UnknownType | DataListItem[];
23
20
  }
@@ -48,16 +45,6 @@ export interface Props {
48
45
  */
49
46
  valueKey?: string;
50
47
 
51
- /**
52
- * Empty state title.
53
- */
54
- emptyTitle?: string;
55
-
56
- /**
57
- * Empty state description.
58
- */
59
- emptyDescription?: string;
60
-
61
48
  /**
62
49
  * Drag animation duration.
63
50
  */
@@ -23,7 +23,6 @@ export default {
23
23
  component: UInputRating,
24
24
  args: {
25
25
  modelValue: 2,
26
- label: "Rate your experience: ",
27
26
  },
28
27
  argTypes: {
29
28
  ...getArgTypes(UInputRating.__name),
@@ -7,8 +7,8 @@ import {
7
7
 
8
8
  import UAvatar from "../../ui.image-avatar/UAvatar.vue";
9
9
  import URow from "../../ui.container-row/URow.vue";
10
- import UCol from "../../ui.container-col/UCol.vue";
11
10
  import ULoader from "../../ui.loader/ULoader.vue";
11
+ import tooltip from "../../directives/tooltip/vTooltip.ts";
12
12
 
13
13
  import type { Meta, StoryFn } from "@storybook/vue3";
14
14
  import type { UAvatarProps } from "../types.ts";
@@ -47,7 +47,8 @@ const DefaultTemplate: StoryFn<UAvatarArgs> = (args: UAvatarArgs) => ({
47
47
  });
48
48
 
49
49
  const EnumVariantTemplate: StoryFn<UAvatarArgs> = (args: UAvatarArgs, { argTypes }) => ({
50
- components: { UCol, URow, UAvatar },
50
+ components: { URow, UAvatar },
51
+ directives: { tooltip },
51
52
  setup() {
52
53
  return {
53
54
  args,
@@ -55,26 +56,16 @@ const EnumVariantTemplate: StoryFn<UAvatarArgs> = (args: UAvatarArgs, { argTypes
55
56
  };
56
57
  },
57
58
  template: `
58
- <UCol gap="xl">
59
- <URow>
60
- <UAvatar
61
- v-for="(option, index) in options"
62
- :key="index"
63
- v-bind="args"
64
- :[args.enum]="option"
65
- :label="option"
66
- />
67
- </URow>
68
- <URow>
69
- <UAvatar
70
- v-for="(option, index) in options"
71
- :key="index"
72
- v-bind="args"
73
- :[args.enum]="option"
74
- :label="''"
75
- />
76
- </URow>
77
- </UCol>
59
+ <URow>
60
+ <UAvatar
61
+ v-for="(option, index) in options"
62
+ :key="index"
63
+ v-bind="args"
64
+ :[args.enum]="option"
65
+ :label="option"
66
+ v-tooltip="option"
67
+ />
68
+ </URow>
78
69
  `,
79
70
  });
80
71
 
@@ -83,43 +74,66 @@ Default.args = { size: "3xl" };
83
74
 
84
75
  export const Src = DefaultTemplate.bind({});
85
76
  Src.args = {
86
- src: "https://avatars.githubusercontent.com/u/16276298?v=4",
77
+ src: "https://i.pravatar.cc/300?img=67",
78
+ size: "3xl",
79
+ };
80
+
81
+ export const PlaceholderIcon = DefaultTemplate.bind({});
82
+ PlaceholderIcon.args = {
83
+ placeholderIcon: "account_circle",
87
84
  size: "3xl",
88
85
  };
89
86
 
90
87
  export const Label = DefaultTemplate.bind({});
91
88
  Label.args = { label: "Name Surname", size: "3xl" };
92
89
 
93
- /**
94
- * Hold cursor above an avatar to see value.
95
- */
96
- export const Sizes = EnumVariantTemplate.bind({});
97
- Sizes.args = { enum: "size" };
90
+ export const Size = EnumVariantTemplate.bind({});
91
+ Size.args = { enum: "size" };
92
+ Size.parameters = {
93
+ docs: {
94
+ description: {
95
+ story: "Hold cursor above an avatar to see the value.",
96
+ },
97
+ },
98
+ };
98
99
 
99
- /**
100
- * Hold cursor above an avatar to see value.
101
- */
102
100
  export const Rounded = EnumVariantTemplate.bind({});
103
101
  Rounded.args = { enum: "rounded", label: "John Doe", color: "orange" };
102
+ Rounded.parameters = {
103
+ docs: {
104
+ description: {
105
+ story: "Hold cursor above an avatar to see the value.",
106
+ },
107
+ },
108
+ };
104
109
 
105
- /**
106
- * Hold cursor above an avatar to see value.
107
- */
108
- export const Colors = EnumVariantTemplate.bind({});
109
- Colors.args = { enum: "color" };
110
+ export const Color = EnumVariantTemplate.bind({});
111
+ Color.args = { enum: "color" };
112
+ Color.parameters = {
113
+ docs: {
114
+ description: {
115
+ story: "Hold cursor above an avatar to see the value.",
116
+ },
117
+ },
118
+ };
110
119
 
111
- /**
112
- * Hold cursor above an avatar to see value.
113
- */
114
120
  export const Bordered = EnumVariantTemplate.bind({});
115
121
  Bordered.args = { enum: "color", bordered: true };
122
+ Bordered.parameters = {
123
+ docs: {
124
+ description: {
125
+ story: "Hold cursor above an avatar to see the value.",
126
+ },
127
+ },
128
+ };
116
129
 
117
130
  export const SlotPlaceholder = DefaultTemplate.bind({});
118
131
  SlotPlaceholder.args = {
132
+ color: "green",
119
133
  size: "3xl",
120
134
  slotTemplate: `
121
- <template #placeholder>
122
- <ULoader loading />
135
+ <template #placeholder="{ iconColor }">
136
+ <ULoader loading :color="iconColor" />
123
137
  </template>
124
138
  `,
125
139
  };
@@ -7,6 +7,9 @@ import {
7
7
 
8
8
  import UIcon from "../../ui.image-icon/UIcon.vue";
9
9
  import URow from "../../ui.container-row/URow.vue";
10
+ import tooltip from "../../directives/tooltip/vTooltip.ts";
11
+
12
+ import Beverage from "../../assets/icons/vueless/emoji_food_beverage.svg?component";
10
13
 
11
14
  import type { Meta, StoryFn } from "@storybook/vue3";
12
15
  import type { Props } from "../types.ts";
@@ -35,6 +38,7 @@ export default {
35
38
 
36
39
  const DefaultTemplate: StoryFn<UIconArgs> = (args: UIconArgs) => ({
37
40
  components: { UIcon },
41
+ directives: { tooltip },
38
42
  setup() {
39
43
  const slots = getSlotNames(UIcon.__name);
40
44
 
@@ -49,6 +53,7 @@ const DefaultTemplate: StoryFn<UIconArgs> = (args: UIconArgs) => ({
49
53
 
50
54
  const EnumVariantTemplate: StoryFn<UIconArgs> = (args: UIconArgs, { argTypes }) => ({
51
55
  components: { UIcon, URow },
56
+ directives: { tooltip },
52
57
  setup() {
53
58
  return {
54
59
  args,
@@ -62,6 +67,7 @@ const EnumVariantTemplate: StoryFn<UIconArgs> = (args: UIconArgs, { argTypes })
62
67
  :key="index"
63
68
  v-bind="args"
64
69
  :[args.enum]="option"
70
+ v-tooltip="option"
65
71
  />
66
72
  </URow>
67
73
  `,
@@ -70,6 +76,18 @@ const EnumVariantTemplate: StoryFn<UIconArgs> = (args: UIconArgs, { argTypes })
70
76
  export const Default = DefaultTemplate.bind({});
71
77
  Default.args = {};
72
78
 
79
+ export const Src = DefaultTemplate.bind({});
80
+ Src.args = { src: Beverage };
81
+ Src.parameters = {
82
+ docs: {
83
+ description: {
84
+ story:
85
+ // eslint-disable-next-line vue/max-len
86
+ "To use a custom icon, import it with the suffix `?component` and pass the imported component in the `src` prop, like this: <br/> `import Beverage from '../../assets/icons/vueless/emoji_food_beverage.svg?component'`",
87
+ },
88
+ },
89
+ };
90
+
73
91
  export const Colors = EnumVariantTemplate.bind({});
74
92
  Colors.args = { enum: "color" };
75
93
 
@@ -77,7 +95,7 @@ export const Sizes = EnumVariantTemplate.bind({});
77
95
  Sizes.args = { enum: "size" };
78
96
 
79
97
  export const Variants = EnumVariantTemplate.bind({});
80
- Variants.args = { enum: "variant", color: "red" };
98
+ Variants.args = { enum: "variant", color: "green" };
81
99
 
82
100
  export const Interactive = DefaultTemplate.bind({});
83
101
  Interactive.args = { interactive: true };