vueless 1.0.2-beta.27 → 1.0.2-beta.29

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/icons/storybook/celebration.svg +1 -0
  2. package/icons/storybook/mark_email_unread.svg +1 -0
  3. package/package.json +1 -1
  4. package/ui.button-toggle/storybook/stories.ts +3 -2
  5. package/ui.container-card/UCard.vue +5 -2
  6. package/ui.container-card/storybook/stories.ts +7 -7
  7. package/ui.container-group/storybook/stories.ts +48 -32
  8. package/ui.container-modal/storybook/stories.ts +9 -6
  9. package/ui.container-modal-confirm/storybook/stories.ts +10 -6
  10. package/ui.container-page/storybook/stories.ts +1 -1
  11. package/ui.dropdown-badge/storybook/stories.ts +3 -2
  12. package/ui.form-select/USelect.vue +2 -2
  13. package/ui.image-avatar/config.ts +1 -1
  14. package/ui.image-icon/storybook/stories.ts +0 -4
  15. package/ui.text-alert/config.ts +1 -1
  16. package/ui.text-alert/storybook/stories.ts +23 -36
  17. package/ui.text-badge/storybook/stories.ts +1 -0
  18. package/ui.text-block/config.ts +8 -0
  19. package/ui.text-block/storybook/stories.ts +17 -3
  20. package/ui.text-block/types.ts +5 -0
  21. package/ui.text-empty/config.ts +1 -1
  22. package/ui.text-empty/storybook/assets/empty-inbox.png +0 -0
  23. package/ui.text-empty/storybook/stories.ts +18 -10
  24. package/ui.text-file/UFile.vue +23 -21
  25. package/ui.text-file/config.ts +2 -2
  26. package/ui.text-file/storybook/assets/imageURL.png +0 -0
  27. package/ui.text-file/storybook/stories.ts +18 -10
  28. package/ui.text-file/tests/UFile.test.ts +3 -3
  29. package/ui.text-files/UFiles.vue +1 -1
  30. package/ui.text-files/config.ts +0 -1
  31. package/ui.text-files/storybook/stories.ts +15 -14
  32. package/ui.text-files/tests/UFiles.test.ts +0 -18
  33. package/ui.text-files/types.ts +0 -5
  34. package/ui.text-header/storybook/stories.ts +21 -0
  35. package/ui.text-number/storybook/stories.ts +12 -7
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 -960 960 960"><path d="m73.3-69 193.42-540.8 350.39 346.39L73.3-69Zm114.63-114.63L494.04-293 296.3-491.74 187.93-183.63Zm376-258.74L527.3-479l236.9-236.89q32.95-32.96 83.75-33.46 50.79-.5 83.98 32.46l17 17-36.86 36.63-19-19q-19-19-44.12-19.5-25.12-.5-44.88 19.5L563.93-442.37Zm-164.5-160.26L362.8-639.5l28.81-29.04q23.24-23 21.74-52.38-1.5-29.38-21.74-49.62l-28-28 36.87-36.63 26 26q35.95 36.19 35.45 90.25-.5 54.05-36.45 90.25l-26.05 26.04ZM483.3-523l-36.87-36.63 149.85-149.85q19-19 18.5-48.5t-19.5-48.5l-61-61 36.87-36.87 63 63q31.96 33.2 32.96 83.37 1 50.18-31.96 83.13L483.3-523Zm163.5 164.5-36.87-36.87 46.05-45.8q36.19-36.2 86.75-37.2 50.55-1 86.75 35.2l51 51-36.87 36.87-52-52q-23-23-48-23t-48 23l-48.81 48.8ZM187.93-183.63Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 -960 960 960"><path d="M142.15-154.02q-27.6 0-47.86-20.27-20.27-20.26-20.27-47.86v-515.7q0-27.7 20.27-48.03 20.26-20.34 47.86-20.34h429.46q-4.44 17.15-5.68 34.19-1.23 17.03 1.24 34.18H147.15l332.85 218 148.37-97.04q10.96 9.96 23.39 18.11 12.44 8.15 25.87 13.8L480-454.35l-337.85-223v455.2h675.7v-353.31q19.18-5.02 36.07-14.7 16.88-9.67 32.3-22.6v390.61q0 27.6-20.34 47.86-20.33 20.27-48.03 20.27h-675.7Zm0-583.83v515.7-515.7Zm617.73 91.92q-47.57 0-80.76-33.31-33.19-33.3-33.19-80.88 0-47.57 33.31-80.76 33.3-33.19 80.88-33.19 47.57 0 80.76 33.31 33.19 33.3 33.19 80.88 0 47.57-33.31 80.76-33.3 33.19-80.88 33.19Z"/></svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "1.0.2-beta.27",
3
+ "version": "1.0.2-beta.29",
4
4
  "license": "MIT",
5
5
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
6
6
  "keywords": [
@@ -57,14 +57,14 @@ const DefaultTemplate: StoryFn<UToggleArgs> = (args: UToggleArgs) => ({
57
57
 
58
58
  const EnumTemplate: StoryFn<UToggleArgs> = (args: UToggleArgs, { argTypes }) => ({
59
59
  components: { UToggle, URow },
60
- setup: () => ({ args, argTypes, getArgs, values: ref(argTypes.size?.options) }),
60
+ setup: () => ({ args, argTypes, getArgs }),
61
61
  template: `
62
62
  <URow>
63
63
  <UToggle
64
64
  v-for="option in argTypes?.[args.enum]?.options"
65
65
  v-bind="getArgs(args, option)"
66
66
  :key="option"
67
- v-model="values[option]"
67
+ v-model="args.modelValue"
68
68
  class="w-auto"
69
69
  />
70
70
  </URow>
@@ -78,6 +78,7 @@ export const Sizes = EnumTemplate.bind({});
78
78
  Sizes.args = {
79
79
  name: "sizeTemplate",
80
80
  enum: "size",
81
+ modelValue: 1,
81
82
  options: [
82
83
  { value: 1, label: "{enumValue}" },
83
84
  { value: 2, label: "{enumValue}" },
@@ -66,8 +66,11 @@ const {
66
66
  <!-- @slot Use it to add something before left side of the header. -->
67
67
  <slot name="before-title" />
68
68
 
69
- <!-- @slot Use it to customize left side of the header. -->
70
- <slot name="title">
69
+ <!--
70
+ @slot Use it to customize left side of the header.
71
+ @binding {string} title
72
+ -->
73
+ <slot name="title" :title="title">
71
74
  <div v-bind="titleFallbackAttrs">
72
75
  <UHeader :label="title" size="xs" v-bind="titleAttrs" />
73
76
  <div v-if="description" v-bind="descriptionAttrs" v-text="description" />
@@ -104,21 +104,21 @@ export const Slots: StoryFn<UCardArgs> = (args) => ({
104
104
  <UCol gap="lg">
105
105
  <UCard v-bind="args" description="Before Title Slot">
106
106
  <template #before-title>
107
- <UIcon name="account_circle" size="sm" />
107
+ <UIcon name="account_circle" color="success" />
108
108
  </template>
109
109
  ${defaultTemplate}
110
110
  </UCard>
111
111
 
112
- <UCard v-bind="args">
113
- <template #title>
114
- <UBadge label="Title Slot" size="lg" />
112
+ <UCard title="Title Slot">
113
+ <template #title="{ title }">
114
+ <UBadge :label="title" size="lg" color="primary" variant="outlined" />
115
115
  </template>
116
116
  ${defaultTemplate}
117
117
  </UCard>
118
118
 
119
119
  <UCard v-bind="args" description="After Title Slot">
120
120
  <template #after-title>
121
- <UIcon name="verified" size="sm" />
121
+ <UIcon name="verified" color="success" />
122
122
  </template>
123
123
  ${defaultTemplate}
124
124
  </UCard>
@@ -126,7 +126,7 @@ export const Slots: StoryFn<UCardArgs> = (args) => ({
126
126
  <UCard v-bind="args" description="Actions Slot">
127
127
  <template #actions>
128
128
  <URow class="max-w-fit">
129
- <UButton size="sm" label="Follow" />
129
+ <UButton size="sm" label="Follow" variant="subtle" />
130
130
  <UButton size="sm" label="Message" />
131
131
  </URow>
132
132
  </template>
@@ -136,7 +136,7 @@ export const Slots: StoryFn<UCardArgs> = (args) => ({
136
136
  <UCard v-bind="args" description="Footer Left Slot">
137
137
  ${defaultTemplate}
138
138
  <template #footer-left>
139
- <UButton size="sm" label="Cancel" />
139
+ <UButton size="sm" label="Cancel" variant="outlined" />
140
140
  </template>
141
141
  </UCard>
142
142
 
@@ -12,6 +12,7 @@ import UButton from "../../ui.button/UButton.vue";
12
12
  import UIcon from "../../ui.image-icon/UIcon.vue";
13
13
  import UBadge from "../../ui.text-badge/UBadge.vue";
14
14
  import URow from "../../ui.container-row/URow.vue";
15
+ import UAlert from "../../ui.text-alert/UAlert.vue";
15
16
 
16
17
  import type { Meta, StoryFn } from "@storybook/vue3";
17
18
  import type { Props } from "../types.ts";
@@ -39,14 +40,20 @@ export default {
39
40
 
40
41
  const defaultTemplate = `
41
42
  <UCol>
42
- <UInput placeholder="Vasyl" label="First Name" />
43
- <UInput placeholder="Vasylenko" label="Last Name" />
44
- <UInput placeholder="Kyiv" label="City" />
43
+ <UInput label="First Name" placeholder="John" />
44
+ <UInput label="Last Name" placeholder="Doe" />
45
+ <UAlert
46
+ title="Attention!"
47
+ description="Please check your email for verification."
48
+ color="warning"
49
+ icon="mark_email_unread"
50
+ class="w-full"
51
+ />
45
52
  </UCol>
46
53
  `;
47
54
 
48
55
  const DefaultTemplate: StoryFn<UGroupArgs> = (args: UGroupArgs) => ({
49
- components: { UGroup, UCol, UInput, UButton },
56
+ components: { UGroup, UCol, UInput, UAlert },
50
57
  setup: () => ({ args, slots: getSlotNames(UGroup.__name) }),
51
58
  template: `
52
59
  <UGroup v-bind="args">
@@ -79,42 +86,51 @@ Underlined.parameters = {
79
86
  };
80
87
 
81
88
  export const Slots: StoryFn<UGroupArgs> = (args) => ({
82
- components: { UGroup, UIcon, UBadge, UButton, URow, UInput, UCol },
89
+ components: { UGroup, UIcon, UBadge, UButton, URow, UInput, UCol, UAlert },
83
90
  setup() {
84
91
  args.config = { wrapper: "mb-8" };
85
92
 
86
93
  return { args };
87
94
  },
88
95
  template: `
89
- <UGroup v-bind="args" title="Before Title Slot">
90
- <template #before-title>
91
- <UIcon name="account_circle" />
92
- </template>
93
- ${defaultTemplate}
94
- </UGroup>
96
+ <UGroup v-bind="args" title="Before Title Slot">
97
+ <template #before-title>
98
+ <UIcon name="account_circle" color="primary" class="mr-1" />
99
+ </template>
100
+ <UCol>
101
+ <UInput label="Username" placeholder="johndoe" />
102
+ </UCol>
103
+ </UGroup>
95
104
 
96
- <UGroup v-bind="args">
97
- <template #title>
98
- <UBadge label="Title Slot" size="lg" />
99
- </template>
100
- ${defaultTemplate}
101
- </UGroup>
105
+ <UGroup v-bind="args" title="Title Slot" upperlined>
106
+ <template #title="{ title }">
107
+ <UBadge :label="title" size="lg" color="primary" variant="outlined" />
108
+ </template>
109
+ <UCol>
110
+ <UInput label="Access Level" placeholder="Superuser" />
111
+ </UCol>
112
+ </UGroup>
102
113
 
103
- <UGroup v-bind="args" title="After Title Slot">
104
- <template #after-title>
105
- <UIcon name="verified" />
106
- </template>
107
- ${defaultTemplate}
108
- </UGroup>
114
+ <UGroup v-bind="args" title="After Title Slot" upperlined>
115
+ <template #after-title>
116
+ <UIcon name="verified" color="success" />
117
+ </template>
118
+ <UCol>
119
+ <UInput label="Email" placeholder="john@email.com" />
120
+ </UCol>
121
+ </UGroup>
109
122
 
110
- <UGroup v-bind="args" title="Actions Slot">
111
- <template #actions>
112
- <URow class="max-w-fit">
113
- <UButton size="sm" variant="outlined" label="Clear" />
114
- <UButton size="sm" label="Submit" />
115
- </URow>
116
- </template>
117
- ${defaultTemplate}
118
- </UGroup>
123
+ <UGroup v-bind="args" title="Actions Slot" upperlined>
124
+ <template #actions>
125
+ <URow class="max-w-fit">
126
+ <UButton size="sm" variant="outlined" label="Cancel" />
127
+ <UButton size="sm" label="Save Changes" />
128
+ </URow>
129
+ </template>
130
+ <UCol>
131
+ <UInput label="First Name" placeholder="John" />
132
+ <UInput label="Last Name" placeholder="Doe" />
133
+ </UCol>
134
+ </UGroup>
119
135
  `,
120
136
  });
@@ -16,6 +16,7 @@ import UTextarea from "../../ui.form-textarea/UTextarea.vue";
16
16
  import URow from "../../ui.container-row/URow.vue";
17
17
  import UBadge from "../../ui.text-badge/UBadge.vue";
18
18
  import UCol from "../../ui.container-col/UCol.vue";
19
+ import UText from "../../ui.text-block/UText.vue";
19
20
 
20
21
  import type { Meta, StoryFn } from "@storybook/vue3";
21
22
  import type { Props } from "../types.ts";
@@ -115,7 +116,7 @@ Description.args = {
115
116
  };
116
117
 
117
118
  export const Inner: StoryFn<UModalArgs> = (args: UModalArgs) => ({
118
- components: { UModal, UButton },
119
+ components: { UModal, UButton, UCol, UText },
119
120
  setup() {
120
121
  const showMainModal = ref(false);
121
122
  const showInnerModal = ref(false);
@@ -133,11 +134,13 @@ export const Inner: StoryFn<UModalArgs> = (args: UModalArgs) => ({
133
134
  template: `
134
135
  <div>
135
136
  <UModal v-bind="args" v-model="showMainModal">
136
- <p>
137
- Are you sure you want to cancel your subscription?
138
- This action will remove access to premium features and cannot be undone.
139
- </p>
140
- <UButton label="View Plan Details" @click="openInnerModal"/>
137
+ <UCol gap="sm">
138
+ <UText>
139
+ Are you sure you want to cancel your subscription?
140
+ This action will remove access to premium features and cannot be undone.
141
+ </UText>
142
+ <UButton label="View Plan Details" @click="openInnerModal"/>
143
+ </UCol>
141
144
 
142
145
  <UModal
143
146
  v-model="showInnerModal"
@@ -14,6 +14,8 @@ import UHeader from "../../ui.text-header/UHeader.vue";
14
14
  import UIcon from "../../ui.image-icon/UIcon.vue";
15
15
  import URow from "../../ui.container-row/URow.vue";
16
16
  import UBadge from "../../ui.text-badge/UBadge.vue";
17
+ import UCol from "../../ui.container-col/UCol.vue";
18
+ import UText from "../../ui.text-block/UText.vue";
17
19
 
18
20
  import type { Meta, StoryFn } from "@storybook/vue3";
19
21
  import type { Props } from "../types.ts";
@@ -93,7 +95,7 @@ ConfirmLabel.parameters = {
93
95
  };
94
96
 
95
97
  export const Inner: StoryFn<UModalConfirmArgs> = (args: UModalConfirmArgs) => ({
96
- components: { UModalConfirm, UButton, UModal },
98
+ components: { UModalConfirm, UButton, UModal, UCol, UText },
97
99
  setup() {
98
100
  const showMainModal = ref(false);
99
101
  const showInnerModal = ref(false);
@@ -111,11 +113,13 @@ export const Inner: StoryFn<UModalConfirmArgs> = (args: UModalConfirmArgs) => ({
111
113
  template: `
112
114
  <div>
113
115
  <UModalConfirm v-bind="args" v-model="showMainModal">
114
- <p>
115
- Are you sure you want to cancel your subscription?
116
- This action will remove access to premium features and cannot be undone.
117
- </p>
118
- <UButton label="View Plan Details" @click="openInnerModal"/>
116
+ <UCol gap="sm">
117
+ <UText>
118
+ Are you sure you want to cancel your subscription?
119
+ This action will remove access to premium features and cannot be undone.
120
+ </UText>
121
+ <UButton label="View Plan Details" @click="openInnerModal"/>
122
+ </UCol>
119
123
 
120
124
  <UModal
121
125
  v-model="showInnerModal"
@@ -84,7 +84,7 @@ const EnumTemplate: StoryFn<UPageArgs> = (args: UPageArgs, { argTypes }) => ({
84
84
  v-for="option in argTypes?.[args.enum]?.options"
85
85
  v-bind="getArgs(args, option)"
86
86
  :key="option"
87
- :config="{ wrapper: 'min-h-max', page: 'min-h-max' }"
87
+ :config="{ wrapper: 'min-h-max', page: 'min-h-max mb-4' }"
88
88
  >
89
89
  ${defaultTemplate}
90
90
  </UPage>
@@ -12,6 +12,7 @@ import UCol from "../../ui.container-col/UCol.vue";
12
12
  import UIcon from "../../ui.image-icon/UIcon.vue";
13
13
  import ULink from "../../ui.button-link/ULink.vue";
14
14
  import UAvatar from "../../ui.image-avatar/UAvatar.vue";
15
+ import UText from "../../ui.text-block/UText.vue";
15
16
 
16
17
  import type { Meta, StoryFn } from "@storybook/vue3";
17
18
  import type { Props } from "../types.ts";
@@ -52,7 +53,7 @@ export default {
52
53
  } as Meta;
53
54
 
54
55
  const DefaultTemplate: StoryFn<DefaultUDropdownBadgeArgs> = (args: DefaultUDropdownBadgeArgs) => ({
55
- components: { UDropdownBadge, UIcon, ULink, UAvatar, URow, UCol },
56
+ components: { UDropdownBadge, UIcon, ULink, UAvatar, URow, UCol, UText },
56
57
  setup: () => ({ args, slots: getSlotNames(UDropdownBadge.__name) }),
57
58
  template: `
58
59
  <UDropdownBadge v-bind="args">
@@ -187,7 +188,7 @@ DefaultSlot.args = {
187
188
  <template #default>
188
189
  <URow align="center" gap="xs">
189
190
  <UAvatar size="3xs" src="https://i.pravatar.cc/300" />
190
- <span class="text-small font-semibold">John Doe</span>
191
+ <UText weight="semibold" size="sm" class="text-inverted">John Doe</UText>
191
192
  </URow>
192
193
  </template>
193
194
  `,
@@ -578,7 +578,7 @@ const {
578
578
  :name="config.defaults.clearIcon"
579
579
  v-bind="clearIconAttrs"
580
580
  :data-test="getDataTest('clear')"
581
- @click="onClickClear"
581
+ @click.stop="onClickClear"
582
582
  />
583
583
  </slot>
584
584
  </div>
@@ -795,7 +795,7 @@ const {
795
795
  :underlined="false"
796
796
  v-bind="listClearAllAttrs"
797
797
  :data-test="getDataTest('clear-all')"
798
- @click="onClickClear"
798
+ @click.stop="onClickClear"
799
799
  />
800
800
  </div>
801
801
  </template>
@@ -30,7 +30,7 @@ export default /*tw*/ {
30
30
  full: "rounded-full",
31
31
  },
32
32
  src: {
33
- true: "bg-transparent",
33
+ true: "border-none bg-transparent",
34
34
  },
35
35
  },
36
36
  },
@@ -4,7 +4,6 @@ import {
4
4
  getSlotNames,
5
5
  getSlotsFragment,
6
6
  getDocsDescription,
7
- getEnumVariantDescription,
8
7
  } from "../../utils/storybook.ts";
9
8
 
10
9
  import UIcon from "../../ui.image-icon/UIcon.vue";
@@ -99,15 +98,12 @@ import Beverage from "./src/assets/icons/beverage.svg?component";
99
98
 
100
99
  export const Colors = EnumTemplate.bind({});
101
100
  Colors.args = { enum: "color" };
102
- Colors.parameters = getEnumVariantDescription();
103
101
 
104
102
  export const Sizes = EnumTemplate.bind({});
105
103
  Sizes.args = { enum: "size" };
106
- Sizes.parameters = getEnumVariantDescription();
107
104
 
108
105
  export const Variants = EnumTemplate.bind({});
109
106
  Variants.args = { enum: "variant", color: "success" };
110
- Variants.parameters = getEnumVariantDescription();
111
107
 
112
108
  export const Interactive = DefaultTemplate.bind({});
113
109
  Interactive.args = { interactive: true };
@@ -1,6 +1,6 @@
1
1
  export default /*tw*/ {
2
2
  wrapper: {
3
- base: "p-4 border-box flex flex-col border rounded-medium",
3
+ base: "p-4 border-box flex flex-col border rounded-medium w-full",
4
4
  variants: {
5
5
  variant: {
6
6
  solid: "text-inverted bg-{color} border-transparent",
@@ -12,7 +12,6 @@ import UCol from "../../ui.container-col/UCol.vue";
12
12
  import UIcon from "../../ui.image-icon/UIcon.vue";
13
13
  import UButton from "../../ui.button/UButton.vue";
14
14
  import UBadge from "../../ui.text-badge/UBadge.vue";
15
- import ULink from "../../ui.button-link/ULink.vue";
16
15
  import UText from "../../ui.text-block/UText.vue";
17
16
 
18
17
  import type { Meta, StoryFn } from "@storybook/vue3";
@@ -29,6 +28,10 @@ export default {
29
28
  component: UAlert,
30
29
  args: {
31
30
  title: "Scheduled Maintenance Notice",
31
+ description: `
32
+ Our website will be undergoing scheduled maintenance on March 15th from 2:00 AM to 4:00 AM UTC.
33
+ Some features may be temporarily unavailable during this time. We appreciate your patience!
34
+ `,
32
35
  },
33
36
  argTypes: {
34
37
  ...getArgTypes(UAlert.__name),
@@ -67,14 +70,6 @@ const EnumTemplate: StoryFn<UAlertArgs> = (args: UAlertArgs, { argTypes }) => ({
67
70
  export const Default = DefaultTemplate.bind({});
68
71
  Default.args = {};
69
72
 
70
- export const Description = DefaultTemplate.bind({});
71
- Description.args = {
72
- description: `
73
- Our website will be undergoing scheduled maintenance on March 15th from 2:00 AM to 4:00 AM UTC.
74
- Some features may be temporarily unavailable during this time. We appreciate your patience!
75
- `,
76
- };
77
-
78
73
  export const Variants = EnumTemplate.bind({});
79
74
  Variants.args = { enum: "variant" };
80
75
 
@@ -99,6 +94,7 @@ CloseSlot.args = {
99
94
  label="Close"
100
95
  variant="ghost"
101
96
  size="sm"
97
+ class="ml-2"
102
98
  @click="close"
103
99
  />
104
100
  </template>
@@ -106,7 +102,7 @@ CloseSlot.args = {
106
102
  };
107
103
 
108
104
  export const Slots: StoryFn<UAlertArgs> = (args) => ({
109
- components: { UAlert, UIcon, URow, UCol, UButton, UBadge, ULink, UText },
105
+ components: { UAlert, URow, UCol, UButton, UBadge, UText, UIcon },
110
106
  setup() {
111
107
  return { args };
112
108
  },
@@ -118,30 +114,24 @@ export const Slots: StoryFn<UAlertArgs> = (args) => ({
118
114
  Try it out and let us know what you think!"
119
115
  color="success"
120
116
  icon="question_mark"
117
+ :config="{ contentWrapper: 'items-center' }"
121
118
  >
122
- <template #left="{ iconName }">
123
- <URow align="center" gap="none">
124
- <ULink label="What's New" color="success" />
125
- <UIcon :name="iconName" color="success" size="2xs" class="mb-1" />
126
- </URow>
119
+ <template #left>
120
+ <UIcon name="celebration" color="success" size="lg" />
127
121
  </template>
128
122
  </UAlert>
129
123
 
130
124
  <UAlert
131
- title="System Maintenance"
125
+ title="MAINTENANCE"
132
126
  description="Scheduled maintenance will begin in 30 minutes. Estimated downtime: 2 hours."
133
127
  color="warning"
134
128
  >
135
- <template #title>
136
- <URow align="center" gap="sm">
137
- <UBadge
138
- label="MAINTENANCE"
139
- size="sm"
140
- color="warning"
141
- variant="outlined"
142
- />
143
- <UText label="System Maintenance" size="sm" />
144
- </URow>
129
+ <template #title="{ title }">
130
+ <UBadge
131
+ :label="title"
132
+ color="warning"
133
+ variant="subtle"
134
+ />
145
135
  </template>
146
136
  </UAlert>
147
137
 
@@ -151,23 +141,20 @@ export const Slots: StoryFn<UAlertArgs> = (args) => ({
151
141
  Check out our documentation to get started with building beautiful interfaces."
152
142
  color="info"
153
143
  >
154
- <template #description>
155
- <UCol>
156
- <p>
157
- You've successfully joined our community. Check out our documentation
158
- to get started with building beautiful interfaces.
159
- </p>
144
+ <template #description="{ description }">
145
+ <UCol gap="xs">
146
+ <UText :label="description" color="inherit" />
160
147
  <URow gap="sm">
161
148
  <UButton
162
149
  label="View Docs"
163
- variant="ghost"
164
- size="sm"
150
+ variant="subtle"
151
+ size="xs"
165
152
  color="info"
166
153
  />
167
154
  <UButton
168
155
  label="Join Discord"
169
- variant="ghost"
170
- size="sm"
156
+ variant="subtle"
157
+ size="xs"
171
158
  color="info"
172
159
  />
173
160
  </URow>
@@ -141,6 +141,7 @@ export const Slots: StoryFn<UBadgeArgs> = (args) => ({
141
141
  size="sm"
142
142
  currency="$"
143
143
  currency-space
144
+ color="inherit"
144
145
  />
145
146
  </template>
146
147
  </UBadge>
@@ -32,6 +32,13 @@ export default /*tw*/ {
32
32
  center: "text-center",
33
33
  right: "text-right",
34
34
  },
35
+ weight: {
36
+ light: "font-light",
37
+ normal: "font-normal",
38
+ medium: "font-medium",
39
+ semibold: "font-semibold",
40
+ bold: "font-bold",
41
+ },
35
42
  line: {
36
43
  true: "leading-none",
37
44
  },
@@ -52,6 +59,7 @@ export default /*tw*/ {
52
59
  variant: "default",
53
60
  size: "md",
54
61
  align: "left",
62
+ weight: "normal",
55
63
  line: false,
56
64
  wrap: true,
57
65
  },
@@ -17,7 +17,8 @@ import type { Props } from "../types.ts";
17
17
 
18
18
  interface UTextArgs extends Props {
19
19
  slotTemplate?: string;
20
- enum: "size" | "align" | "variant" | "color";
20
+ enum: "size" | "align" | "variant" | "color" | "weight";
21
+ class?: string;
21
22
  }
22
23
 
23
24
  export default {
@@ -58,7 +59,6 @@ const EnumTemplate: StoryFn<UTextArgs> = (args: UTextArgs, { argTypes }) => ({
58
59
  v-for="option in argTypes?.[args.enum]?.options"
59
60
  v-bind="getArgs(args, option)"
60
61
  :key="option"
61
- class="w-full"
62
62
  />
63
63
  </UCol>
64
64
  `,
@@ -68,7 +68,21 @@ export const Default = DefaultTemplate.bind({});
68
68
  Default.args = {};
69
69
 
70
70
  export const Align = EnumTemplate.bind({});
71
- Align.args = { enum: "align" };
71
+ Align.args = { enum: "align", class: "w-full" };
72
+
73
+ export const Weight: StoryFn<UTextArgs> = (args: UTextArgs, { argTypes }) => ({
74
+ components: { UText, UCol },
75
+ setup: () => ({ args, argTypes, getArgs }),
76
+ template: `
77
+ <UCol>
78
+ <UText v-bind="args" weight="normal" />
79
+
80
+ <UText v-bind="args" weight="medium" />
81
+
82
+ <UText v-bind="args" weight="bold" />
83
+ </UCol>
84
+ `,
85
+ });
72
86
 
73
87
  export const Sizes = EnumTemplate.bind({});
74
88
  Sizes.args = { enum: "size" };
@@ -24,6 +24,11 @@ export interface Props {
24
24
  */
25
25
  variant?: "default" | "accented" | "lifted" | "muted";
26
26
 
27
+ /**
28
+ * Font weight.
29
+ */
30
+ weight?: "light" | "normal" | "medium" | "semibold" | "bold";
31
+
27
32
  /**
28
33
  * Text color.
29
34
  */
@@ -41,7 +41,7 @@ export default /*tw*/ {
41
41
  },
42
42
  },
43
43
  description: {
44
- base: "text-center",
44
+ base: "text-center mt-2",
45
45
  variants: {
46
46
  size: {
47
47
  sm: "text-small",
@@ -11,6 +11,10 @@ import UButton from "../../ui.button/UButton.vue";
11
11
  import UIcon from "../../ui.image-icon/UIcon.vue";
12
12
  import URow from "../../ui.container-row/URow.vue";
13
13
  import UBadge from "../../ui.text-badge/UBadge.vue";
14
+ import ULink from "../../ui.button-link/ULink.vue";
15
+ import UText from "../../ui.text-block/UText.vue";
16
+
17
+ import emptyInbox from "./assets/empty-inbox.png";
14
18
 
15
19
  import type { Meta, StoryFn } from "@storybook/vue3";
16
20
  import type { Props } from "../types.ts";
@@ -38,8 +42,8 @@ export default {
38
42
  } as Meta;
39
43
 
40
44
  const DefaultTemplate: StoryFn<UEmptyArgs> = (args: UEmptyArgs) => ({
41
- components: { UEmpty, UIcon, UButton, UBadge },
42
- setup: () => ({ args, slots: getSlotNames(UEmpty.__name) }),
45
+ components: { UEmpty, UIcon, UButton, UBadge, ULink, UText },
46
+ setup: () => ({ args, slots: getSlotNames(UEmpty.__name), emptyInbox }),
43
47
  template: `
44
48
  <UEmpty v-bind="args">
45
49
  ${args.slotTemplate || getSlotsFragment("")}
@@ -68,17 +72,13 @@ export const Description = DefaultTemplate.bind({});
68
72
  Description.args = { description: "There are no contacts in the list." };
69
73
 
70
74
  export const Sizes = EnumTemplate.bind({});
71
- Sizes.args = { enum: "size", title: "{enumValue}" };
75
+ Sizes.args = { enum: "size" };
72
76
 
73
77
  export const HeaderSlot = DefaultTemplate.bind({});
74
78
  HeaderSlot.args = {
75
79
  slotTemplate: `
76
80
  <template #header>
77
- <UIcon
78
- name="person"
79
- color="info"
80
- size="2xl"
81
- />
81
+ <img :src="emptyInbox" alt="empty" width="300" />
82
82
  </template>
83
83
  `,
84
84
  };
@@ -87,7 +87,10 @@ export const DefaultSlot = DefaultTemplate.bind({});
87
87
  DefaultSlot.args = {
88
88
  slotTemplate: `
89
89
  <template #default>
90
- <UBadge label="There are no contacts in the list." />
90
+ <UText>
91
+ <i>Nothing to display here yet</i>. You can <ULink class="inline">add your own</ULink> <b>content</b>
92
+ or include custom <b>components</b> to enhance the view.
93
+ </UText>
91
94
  </template>
92
95
  `,
93
96
  };
@@ -96,7 +99,12 @@ export const FooterSlot = DefaultTemplate.bind({});
96
99
  FooterSlot.args = {
97
100
  slotTemplate: `
98
101
  <template #footer>
99
- <UButton label="Add new one" size="sm" variant="soft" />
102
+ <UButton
103
+ label="Add new one"
104
+ size="sm"
105
+ color="grayscale"
106
+ variant="soft"
107
+ />
100
108
  </template>
101
109
  `,
102
110
  };
@@ -27,16 +27,12 @@ const emit = defineEmits([
27
27
  "remove",
28
28
  ]);
29
29
 
30
- const fileRef = useTemplateRef<InstanceType<typeof ULink>>("file");
30
+ const fileRef = useTemplateRef<HTMLDivElement>("file");
31
31
 
32
32
  const focus = ref(false);
33
33
 
34
34
  const fileId = props.id || useId();
35
35
 
36
- const link = computed(() => {
37
- return fileRef.value?.linkRef || null;
38
- });
39
-
40
36
  function onRemove() {
41
37
  emit("remove", fileId);
42
38
  }
@@ -51,10 +47,10 @@ function onBlur() {
51
47
 
52
48
  defineExpose({
53
49
  /**
54
- * A reference to the ULink instance for direct DOM manipulation.
55
- * @property {InstanceType<typeof ULink>}
50
+ * A reference to the file wrapper for direct DOM manipulation.
51
+ * @property {HTMLDivElement}
56
52
  */
57
- link,
53
+ fileRef,
58
54
  });
59
55
 
60
56
  /**
@@ -78,9 +74,18 @@ const {
78
74
  </script>
79
75
 
80
76
  <template>
81
- <ULink ref="file" :href="url" v-bind="fileAttrs" :data-test="getDataTest()">
77
+ <div ref="file" v-bind="fileAttrs" :data-test="getDataTest()">
82
78
  <!-- @slot Use it to add something before the file. -->
83
- <slot name="left" />
79
+ <slot name="left">
80
+ <UIcon
81
+ v-if="!imageUrl"
82
+ color="neutral"
83
+ :name="config.defaults.fileIcon"
84
+ v-bind="fileIconAttrs"
85
+ @focus="onFocus"
86
+ @blur="onBlur"
87
+ />
88
+ </slot>
84
89
 
85
90
  <!--
86
91
  @slot Use it to add a file directly.
@@ -93,17 +98,14 @@ const {
93
98
  <div v-bind="bodyAttrs">
94
99
  <img v-if="imageUrl" :alt="label" :src="imageUrl" v-bind="fileImageAttrs" />
95
100
 
96
- <UIcon
97
- v-else
98
- interactive
99
- color="neutral"
100
- :name="config.defaults.fileIcon"
101
- v-bind="fileIconAttrs"
102
- @focus="onFocus"
103
- @blur="onBlur"
101
+ <ULink
102
+ :href="url"
103
+ :label="label"
104
+ :size="size"
105
+ color="grayscale"
106
+ dashed
107
+ v-bind="fileLabelAttrs"
104
108
  />
105
-
106
- <ULink :label="label" :size="size" color="grayscale" dashed v-bind="fileLabelAttrs" />
107
109
  </div>
108
110
  </slot>
109
111
 
@@ -119,5 +121,5 @@ const {
119
121
  @click.stop.prevent="onRemove"
120
122
  />
121
123
  </slot>
122
- </ULink>
124
+ </div>
123
125
  </template>
@@ -1,6 +1,6 @@
1
1
  export default /*tw*/ {
2
2
  file: {
3
- base: "{ULink} flex items-center",
3
+ base: "flex items-center",
4
4
  variants: {
5
5
  size: {
6
6
  sm: "gap-0.5",
@@ -12,7 +12,7 @@ export default /*tw*/ {
12
12
  body: "flex items-center gap-2",
13
13
  fileImage: "rounded-sm max-w-7",
14
14
  fileIcon: {
15
- base: "{UIcon} -mr-1",
15
+ base: "{UIcon}",
16
16
  defaults: {
17
17
  size: {
18
18
  sm: "xs",
@@ -11,7 +11,7 @@ import URow from "../../ui.container-row/URow.vue";
11
11
  import UIcon from "../../ui.image-icon/UIcon.vue";
12
12
  import UBadge from "../../ui.text-badge/UBadge.vue";
13
13
 
14
- import tooltip from "../../directives/tooltip/vTooltip.ts";
14
+ import imageURL from "./assets/imageURL.png";
15
15
 
16
16
  import type { Meta, StoryFn } from "@storybook/vue3";
17
17
  import type { Props } from "../types.ts";
@@ -27,7 +27,7 @@ export default {
27
27
  component: UFile,
28
28
  args: {
29
29
  label: "Invoice_123.pdf",
30
- url: "https://storybook.js.org/",
30
+ url: "",
31
31
  },
32
32
  argTypes: {
33
33
  ...getArgTypes(UFile.__name),
@@ -59,7 +59,6 @@ const DefaultTemplate: StoryFn<UFileArgs> = (args: UFileArgs) => ({
59
59
 
60
60
  const EnumTemplate: StoryFn<UFileArgs> = (args: UFileArgs, { argTypes }) => ({
61
61
  components: { UFile, URow },
62
- directives: { tooltip },
63
62
  setup: () => ({ args, argTypes, getArgs }),
64
63
  template: `
65
64
  <URow>
@@ -67,7 +66,6 @@ const EnumTemplate: StoryFn<UFileArgs> = (args: UFileArgs, { argTypes }) => ({
67
66
  v-for="option in argTypes?.[args.enum]?.options"
68
67
  v-bind="getArgs(args, option)"
69
68
  :key="option"
70
- v-tooltip="option"
71
69
  />
72
70
  </URow>
73
71
  `,
@@ -77,9 +75,7 @@ export const Default = DefaultTemplate.bind({});
77
75
  Default.args = {};
78
76
 
79
77
  export const ImageURL = DefaultTemplate.bind({});
80
- ImageURL.args = {
81
- imageUrl: "https://cdn-icons-png.flaticon.com/256/11039/11039912.png",
82
- };
78
+ ImageURL.args = { imageUrl: imageURL };
83
79
 
84
80
  export const Removable = DefaultTemplate.bind({});
85
81
  Removable.args = { removable: true };
@@ -93,16 +89,28 @@ export const Slots: StoryFn<UFileArgs> = (args) => ({
93
89
  return { args };
94
90
  },
95
91
  template: `
96
- <URow>
92
+ <URow gap="lg">
97
93
  <UFile v-bind="args">
98
94
  <template #left>
99
- <UIcon name="info" color="warning" size="xs" />
95
+ <UIcon
96
+ name="info"
97
+ color="warning"
98
+ size="xs"
99
+ class="hover:cursor-default"
100
+ />
100
101
  </template>
101
102
  </UFile>
102
103
 
103
104
  <UFile v-bind="args">
104
105
  <template #right>
105
- <UBadge label="File uploaded" color="success" size="sm" variant="subtle" right-icon="done_all" />
106
+ <UBadge
107
+ label="File uploaded"
108
+ color="success"
109
+ size="sm"
110
+ variant="soft"
111
+ right-icon="done_all"
112
+ class="hover:cursor-default"
113
+ />
106
114
  </template>
107
115
  </UFile>
108
116
  </URow>
@@ -247,11 +247,11 @@ describe("UFile.vue", () => {
247
247
 
248
248
  // Exposed refs tests
249
249
  describe("Exposed refs", () => {
250
- // link ref
251
- it("exposes link ref", () => {
250
+ // file ref
251
+ it("exposes file ref", () => {
252
252
  const component = mount(UFile, {});
253
253
 
254
- expect(component.vm.link).toBeDefined();
254
+ expect(component.vm.fileRef).toBeDefined();
255
255
  });
256
256
  });
257
257
  });
@@ -69,7 +69,7 @@ const { getDataTest, filesLabelAttrs, itemsAttrs, itemAttrs } = useUI<Config>(de
69
69
  :label="label"
70
70
  :description="description"
71
71
  :size="size"
72
- :align="labelAlign"
72
+ align="topWithDesc"
73
73
  v-bind="filesLabelAttrs"
74
74
  >
75
75
  <template #label>
@@ -4,6 +4,5 @@ export default /*tw*/ {
4
4
  item: "{UFile} flex",
5
5
  defaults: {
6
6
  size: "md",
7
- labelAlign: "top",
8
7
  },
9
8
  };
@@ -79,25 +79,26 @@ Removable.args = { removable: true };
79
79
  export const Sizes = EnumTemplate.bind({});
80
80
  Sizes.args = { enum: "size" };
81
81
 
82
- export const LabelAlign = EnumTemplate.bind({});
83
- LabelAlign.args = {
84
- enum: "labelAlign",
85
- description: "These files include important documents like reports and employee data.",
86
- };
87
-
88
82
  export const Slots: StoryFn<UFilesArgs> = (args) => ({
89
83
  components: { UFiles, URow, UIcon },
90
84
  setup() {
91
85
  return { args };
92
86
  },
93
87
  template: `
94
- <UFiles v-bind="args">
95
- <template #before-file="{ index }">
96
- <UIcon v-if="index === 0" name="info" color="warning" size="xs" />
97
- </template>
98
- <template #after-file="{ index }">
99
- <UIcon v-if="index === 1" name="check_circle" color="success" size="xs" />
100
- </template>
101
- </UFiles>
88
+ <URow>
89
+ <UFiles v-bind="args">
90
+ <template #before-file="{ index }">
91
+ <UIcon v-if="index === 0" name="info" color="warning" size="xs" />
92
+ <UIcon v-if="index === 1" name="check_circle" color="success" size="xs" />
93
+ </template>
94
+ </UFiles>
95
+
96
+ <UFiles v-bind="args">
97
+ <template #after-file="{ index }">
98
+ <UIcon v-if="index === 0" name="info" color="warning" size="xs" />
99
+ <UIcon v-if="index === 1" name="check_circle" color="success" size="xs" />
100
+ </template>
101
+ </UFiles>
102
+ </URow>
102
103
  `,
103
104
  });
@@ -61,24 +61,6 @@ describe("UFiles.vue", () => {
61
61
  expect(labelComponent.props("label")).toBe(label);
62
62
  });
63
63
 
64
- // LabelAlign prop
65
- it("passes the correct labelAlign to ULabel", () => {
66
- const labelAligns = ["top", "topWithDesc"];
67
-
68
- labelAligns.forEach((labelAlign) => {
69
- const component = mount(UFiles, {
70
- props: {
71
- fileList,
72
- labelAlign: labelAlign as Props["labelAlign"],
73
- },
74
- });
75
-
76
- const labelComponent = component.findComponent(ULabel);
77
-
78
- expect(labelComponent.props("align")).toBe(labelAlign);
79
- });
80
- });
81
-
82
64
  // Description prop
83
65
  it("passes the correct description to ULabel", () => {
84
66
  const description = "List of files";
@@ -14,11 +14,6 @@ export interface Props {
14
14
  */
15
15
  label?: string;
16
16
 
17
- /**
18
- * File list label placement.
19
- */
20
- labelAlign?: "top" | "topWithDesc";
21
-
22
17
  /**
23
18
  * File list description.
24
19
  */
@@ -62,6 +62,27 @@ const EnumTemplate: StoryFn<UHeaderArgs> = (args: UHeaderArgs, { argTypes }) =>
62
62
  export const Default = DefaultTemplate.bind({});
63
63
  Default.args = {};
64
64
 
65
+ export const Line: StoryFn<UHeaderArgs> = (args: UHeaderArgs) => ({
66
+ components: { UHeader, UCol },
67
+ setup: () => ({ args }),
68
+ template: `
69
+ <UCol>
70
+ <UHeader :line="false">
71
+ <div class="rounded-medium border border-primary border-dashed w-fit">
72
+ Text with default library line height.
73
+ </div>
74
+ </UHeader>
75
+
76
+ <UHeader line>
77
+ <div class="rounded-medium border border-primary border-dashed w-fit">
78
+ Text with line height equal to its font size.
79
+ </div>
80
+ </UHeader>
81
+ </UCol>
82
+ `,
83
+ });
84
+ Line.args = {};
85
+
65
86
  export const Sizes = EnumTemplate.bind({});
66
87
  Sizes.args = { enum: "size" };
67
88
 
@@ -65,7 +65,7 @@ export const Align: StoryFn<UNumberArgs> = (args: UNumberArgs) => ({
65
65
  components: { UNumber, URow, UCol },
66
66
  setup: () => ({ args }),
67
67
  template: `
68
- <UCol block align="stretch">
68
+ <UCol block align="stretch" class="p-2 rounded-medium border border-primary border-dashed">
69
69
  <UNumber v-bind="args" align="left" />
70
70
  <UNumber v-bind="args" align="right" />
71
71
  </UCol>
@@ -81,11 +81,16 @@ Sizes.args = { enum: "size" };
81
81
  export const CurrencyAlign = EnumTemplate.bind({});
82
82
  CurrencyAlign.args = { enum: "currencyAlign", currency: "USD", currencySpace: true };
83
83
 
84
- export const LimitFractionDigits = DefaultTemplate.bind({});
85
- LimitFractionDigits.args = {
86
- minFractionDigits: 4,
87
- maxFractionDigits: 6,
88
- };
84
+ export const LimitFractionDigits: StoryFn<UNumberArgs> = (args: UNumberArgs) => ({
85
+ components: { UNumber, UCol },
86
+ setup: () => ({ args }),
87
+ template: `
88
+ <UCol>
89
+ <UNumber :value="-14.24" :minFractionDigits="4" :maxFractionDigits="6" />
90
+ <UNumber :value="-14.123456789" :minFractionDigits="4" :maxFractionDigits="6" />
91
+ </UCol>
92
+ `,
93
+ });
89
94
  LimitFractionDigits.parameters = {
90
95
  docs: {
91
96
  description: {
@@ -107,7 +112,7 @@ DecimalSeparator.parameters = {
107
112
  };
108
113
 
109
114
  export const ThousandsSeparator = DefaultTemplate.bind({});
110
- ThousandsSeparator.args = { value: -1400000.24, thousandsSeparator: "-" };
115
+ ThousandsSeparator.args = { value: -1400000.24, thousandsSeparator: "." };
111
116
  ThousandsSeparator.parameters = {
112
117
  docs: {
113
118
  description: {