sprintify-ui 0.0.11 → 0.0.12

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 (67) hide show
  1. package/dist/sprintify-ui.es.js +4906 -3570
  2. package/dist/style.css +1 -1
  3. package/dist/types/src/components/BaseCharacterCounter.vue.d.ts +143 -0
  4. package/dist/types/src/components/BaseInput.vue.d.ts +39 -5
  5. package/dist/types/src/components/BaseLoadingCover.vue.d.ts +72 -0
  6. package/dist/types/src/components/BaseModalCenter.vue.d.ts +8 -8
  7. package/dist/types/src/components/BaseModalSide.vue.d.ts +8 -8
  8. package/dist/types/src/components/BasePagination.vue.d.ts +105 -13
  9. package/dist/types/src/components/BasePaginationSimple.vue.d.ts +2 -2
  10. package/dist/types/src/components/BaseSelect.vue.d.ts +130 -26
  11. package/dist/types/src/components/BaseSwitch.vue.d.ts +15 -8
  12. package/dist/types/src/components/BaseTabItem.vue.d.ts +26 -4
  13. package/dist/types/src/components/BaseTextareaAutoresize.vue.d.ts +175 -21
  14. package/dist/types/src/components/index.d.ts +24 -1
  15. package/dist/types/src/index.d.ts +4 -0
  16. package/package.json +1 -1
  17. package/src/components/BaseCharacterCounter.stories.js +30 -0
  18. package/src/components/BaseCharacterCounter.vue +60 -0
  19. package/src/components/BaseDataIterator.stories.js +2 -2
  20. package/src/components/BaseDataIterator.vue +32 -38
  21. package/src/components/BaseDataTable.stories.js +2 -2
  22. package/src/components/BaseFileUploader.vue +4 -0
  23. package/src/components/BaseInput.stories.js +46 -0
  24. package/src/components/BaseInput.vue +10 -2
  25. package/src/components/BaseInputLabel.stories.js +31 -0
  26. package/src/components/BaseInputLabel.vue +1 -1
  27. package/src/components/BaseLoadingCover.stories.js +55 -0
  28. package/src/components/BaseLoadingCover.vue +19 -1
  29. package/src/components/BaseMenu.stories.js +125 -0
  30. package/src/components/BaseModalCenter.stories.js +61 -0
  31. package/src/components/BaseModalCenter.vue +2 -2
  32. package/src/components/BaseModalSide.stories.js +55 -0
  33. package/src/components/BaseModalSide.vue +2 -2
  34. package/src/components/BaseNavbar.stories.js +150 -0
  35. package/src/components/BaseNavbar.vue +3 -0
  36. package/src/components/BaseNavbarItem.vue +1 -0
  37. package/src/components/BaseNavbarItemContent.vue +3 -0
  38. package/src/components/BasePagination.stories.js +32 -0
  39. package/src/components/BasePagination.vue +126 -40
  40. package/src/components/BasePaginationSimple.vue +3 -3
  41. package/src/components/BasePanel.stories.js +56 -0
  42. package/src/components/BasePassword.stories.js +36 -0
  43. package/src/components/BasePassword.vue +11 -5
  44. package/src/components/BaseProcessRing.stories.js +27 -0
  45. package/src/components/BaseReadMore.stories.js +30 -0
  46. package/src/components/BaseReadMore.vue +1 -1
  47. package/src/components/BaseSelect.stories.js +67 -0
  48. package/src/components/BaseSelect.vue +144 -44
  49. package/src/components/BaseSideNavigation.stories.js +55 -0
  50. package/src/components/BaseSideNavigation.vue +7 -2
  51. package/src/components/BaseSideNavigationItem.vue +11 -3
  52. package/src/components/BaseSkeleton.stories.js +36 -0
  53. package/src/components/BaseSwitch.stories.js +101 -0
  54. package/src/components/BaseSwitch.vue +90 -12
  55. package/src/components/BaseSystemAlert.stories.js +63 -0
  56. package/src/components/BaseTabItem.vue +19 -6
  57. package/src/components/BaseTabs.stories.js +54 -0
  58. package/src/components/BaseTabs.vue +3 -3
  59. package/src/components/BaseTextarea.stories.js +35 -0
  60. package/src/components/BaseTextarea.vue +1 -1
  61. package/src/components/BaseTextareaAutoresize.stories.js +49 -0
  62. package/src/components/BaseTextareaAutoresize.vue +83 -87
  63. package/src/components/index.ts +46 -0
  64. package/src/lang/en.json +1 -0
  65. package/src/lang/fr.json +1 -0
  66. package/dist/types/src/components/BaseWordCount.vue.d.ts +0 -31
  67. package/src/components/BaseWordCount.vue +0 -36
@@ -41,19 +41,19 @@ export default defineComponent({
41
41
  type: Number,
42
42
  },
43
43
  },
44
- emits: ['model-value:update'],
44
+ emits: ['update:model-value'],
45
45
  methods: {
46
46
  next() {
47
47
  if (this.modelValue >= this.lastPage) {
48
48
  return;
49
49
  }
50
- this.$emit('model-value:update', this.modelValue + 1);
50
+ this.$emit('update:model-value', this.modelValue + 1);
51
51
  },
52
52
  previous() {
53
53
  if (this.modelValue == 1) {
54
54
  return;
55
55
  }
56
- this.$emit('model-value:update', this.modelValue - 1);
56
+ this.$emit('update:model-value', this.modelValue - 1);
57
57
  },
58
58
  },
59
59
  });
@@ -0,0 +1,56 @@
1
+ import BaseContainer from './BaseContainer.vue';
2
+ import BasePanel from './BasePanel.vue';
3
+ import BaseCard from './BaseCard.vue';
4
+ import BaseCardRow from './BaseCardRow.vue';
5
+ import BaseInputLabel from './BaseInputLabel.vue';
6
+ import BaseInput from './BaseInput.vue';
7
+
8
+ export default {
9
+ title: 'Layout/BasePanel',
10
+ component: BasePanel,
11
+ args: {
12
+ title: 'General information',
13
+ description:
14
+ 'Enter general user information, name and age. User must be more than 10 years old to participate.',
15
+ },
16
+ };
17
+
18
+ const Template = (args) => ({
19
+ components: {
20
+ BaseContainer,
21
+ BasePanel,
22
+ BaseCard,
23
+ BaseCardRow,
24
+ BaseInputLabel,
25
+ BaseInput,
26
+ },
27
+ setup() {
28
+ return { args };
29
+ },
30
+ template: `
31
+ <div class="bg-slate-100 py-10">
32
+ <BaseContainer>
33
+ <BasePanel v-bind="args">
34
+ <BaseCard>
35
+ <BaseCardRow>
36
+ <div class="mb-4">
37
+ <BaseInputLabel label="Name" />
38
+ <BaseInput name="name" class="w-full" placeholder="Enter you name" />
39
+ </div>
40
+
41
+ <div class="mb-4">
42
+ <BaseInputLabel label="Age" />
43
+ <BaseInput name="age" class="w-full" placeholder="Enter you age" />
44
+ </div>
45
+
46
+ <button class="btn btn-primary mt-2">Submit</button>
47
+ </BaseCardRow>
48
+ </BaseCard>
49
+ </BasePanel>
50
+ </BaseContainer>
51
+ </div>
52
+ `,
53
+ });
54
+
55
+ export const Demo = Template.bind({});
56
+ Demo.args = {};
@@ -0,0 +1,36 @@
1
+ import BasePassword from './BasePassword.vue';
2
+
3
+ export default {
4
+ title: 'Form/BasePassword',
5
+ component: BasePassword,
6
+ args: {
7
+ required: true,
8
+ name: 'password',
9
+ },
10
+ };
11
+
12
+ const Template = (args) => ({
13
+ components: {
14
+ BasePassword,
15
+ },
16
+ setup() {
17
+ const value = ref('');
18
+ return { args, value };
19
+ },
20
+ template: `
21
+ <form @submit.prevent="">
22
+ <BasePassword class="border-slate-300" v-model="value" v-bind="args"></BasePassword>
23
+ </form>
24
+ `,
25
+ });
26
+
27
+ export const Demo = Template.bind({});
28
+ Demo.args = {
29
+ placeholder: 'Enter your password',
30
+ };
31
+
32
+ export const Disabled = Template.bind({});
33
+ Disabled.args = {
34
+ disabled: true,
35
+ placeholder: 'Enter your password',
36
+ };
@@ -1,5 +1,8 @@
1
1
  <template>
2
- <div class="flex border bg-white">
2
+ <div
3
+ class="flex rounded border border-slate-300 bg-white"
4
+ :class="[disabled ? 'cursor-not-allowed text-slate-300' : '']"
5
+ >
3
6
  <input
4
7
  ref="input"
5
8
  :value="modelValue"
@@ -8,7 +11,7 @@
8
11
  :disabled="disabled"
9
12
  :placeholder="placeholder"
10
13
  :required="required"
11
- class="grow rounded-l border-none focus:ring-2 focus:ring-primary-500"
14
+ class="grow rounded-l rounded-r-none border-none focus:ring-2 focus:ring-primary-500 disabled:cursor-not-allowed"
12
15
  :class="inputClass"
13
16
  @input="onInput"
14
17
  />
@@ -16,15 +19,16 @@
16
19
  <button
17
20
  tabindex="-1"
18
21
  type="button"
19
- class="pr-3 text-slate-500"
22
+ class="pr-3 text-slate-500 disabled:cursor-not-allowed disabled:text-slate-300"
23
+ :disabled="disabled"
20
24
  @click="showPassword = !showPassword"
21
25
  >
22
26
  <BaseIcon
23
27
  v-if="!showPassword"
24
- icon="heroicons:eye-off"
28
+ icon="heroicons:eye-slash-20-solid"
25
29
  class="h-5 w-5"
26
30
  />
27
- <BaseIcon v-else icon="heroicons:eye" class="h-5 w-5" />
31
+ <BaseIcon v-else icon="heroicons:eye-20-solid" class="h-5 w-5" />
28
32
  </button>
29
33
  </div>
30
34
  </div>
@@ -33,8 +37,10 @@
33
37
  <script lang="ts">
34
38
  import { trim } from 'lodash';
35
39
  import { defineComponent, PropType } from 'vue';
40
+ import { Icon as BaseIcon } from '@iconify/vue';
36
41
 
37
42
  export default defineComponent({
43
+ components: { BaseIcon },
38
44
  props: {
39
45
  modelValue: {
40
46
  default: '',
@@ -0,0 +1,27 @@
1
+ import BaseProcessRing from './BaseProcessRing.vue';
2
+
3
+ export default {
4
+ title: 'Components/BaseProcessRing',
5
+ component: BaseProcessRing,
6
+ args: {
7
+ class: 'text-primary-500',
8
+ radius: 100,
9
+ stroke: 5,
10
+ progress: 0.6,
11
+ },
12
+ };
13
+
14
+ const Template = (args) => ({
15
+ components: {
16
+ BaseProcessRing,
17
+ },
18
+ setup() {
19
+ return { args };
20
+ },
21
+ template: `
22
+ <BaseProcessRing v-bind="args"></BaseProcessRing>
23
+ `,
24
+ });
25
+
26
+ export const Demo = Template.bind({});
27
+ Demo.args = {};
@@ -0,0 +1,30 @@
1
+ import BaseReadMore from './BaseReadMore.vue';
2
+ import BaseContainer from './BaseContainer.vue';
3
+
4
+ export default {
5
+ title: 'Components/BaseReadMore',
6
+ component: BaseReadMore,
7
+ args: {},
8
+ };
9
+
10
+ const Template = (args) => ({
11
+ components: {
12
+ BaseReadMore,
13
+ BaseContainer,
14
+ },
15
+ setup() {
16
+ return { args };
17
+ },
18
+ template: `
19
+ <BaseContainer size="3xl">
20
+ <BaseReadMore v-bind="args">
21
+ <p class="text-slate-600">
22
+ Aute incididunt laborum in sint commodo reprehenderit et aliquip aliqua proident exercitation nostrud sunt. Consectetur laborum elit do non ullamco anim fugiat laboris non aliqua consequat culpa. Veniam aliquip irure et qui dolore eiusmod exercitation elit exercitation ad excepteur reprehenderit enim. Id laboris do eu amet qui Lorem excepteur. Eiusmod eiusmod est qui minim consectetur aliqua occaecat sit tempor nulla. Velit et eiusmod id ut adipisicing occaecat deserunt.Excepteur occaecat nulla deserunt Lorem eu mollit non esse. Velit do proident adipisicing labore ipsum nostrud ipsum pariatur magna. Consequat do reprehenderit eiusmod cupidatat cupidatat cupidatat reprehenderit. Aute fugiat ex fugiat in ut enim dolore est qui. Lorem irure eiusmod eiusmod cillum aute nostrud sint aute enim aute. Aliquip aliqua quis deserunt commodo fugiat incididunt sint qui proident.
23
+ </p>
24
+ </BaseReadMore>
25
+ </BaseContainer>
26
+ `,
27
+ });
28
+
29
+ export const Demo = Template.bind({});
30
+ Demo.args = {};
@@ -13,7 +13,7 @@
13
13
  class="mt-1 inline appearance-none border-b border-dashed border-slate-400 bg-transparent px-0.5 py-0 text-slate-900 hover:text-slate-600"
14
14
  @click="showMore = true"
15
15
  >
16
- <span class="text-base font-semibold">{{ $t('sui.read_more') }}</span>
16
+ <span class="text-base font-medium">{{ $t('sui.read_more') }}</span>
17
17
  </button>
18
18
  </div>
19
19
  </template>
@@ -0,0 +1,67 @@
1
+ import BaseSelect from './BaseSelect.vue';
2
+ import BaseInputLabel from './BaseInputLabel.vue';
3
+
4
+ export default {
5
+ title: 'Form/BaseSelect',
6
+ component: BaseSelect,
7
+ args: {
8
+ name: 'name',
9
+ class: 'w-full',
10
+ },
11
+ };
12
+
13
+ const Template = (args) => ({
14
+ components: {
15
+ BaseSelect,
16
+ BaseInputLabel,
17
+ },
18
+ setup() {
19
+ function onSubmit() {
20
+ alert('submit');
21
+ }
22
+ // To test, you should try the following scenarios
23
+ // - valid (ex: 'javascript')
24
+ // - invalid (ex: 'test')
25
+ // - empty string ''
26
+ // - null
27
+ // - undefined
28
+
29
+ // Test on Safari AND Chrome
30
+
31
+ // For optional, make sure the default option is selected
32
+ // For required, try to submit, it should be prevented
33
+ const value = ref('test');
34
+ return { args, value, onSubmit };
35
+ },
36
+ template: `
37
+ <form @submit.prevent="onSubmit" class="border-none">
38
+ <BaseInputLabel :required="args.required" label="Choose your favorite programing language" />
39
+ <BaseSelect v-model="value" v-bind="args">
40
+ <option value="javascript">JavaScript</option>
41
+ <option value="typescript">Typescript</option>
42
+ <option value="golang">Golang</option>
43
+ </BaseSelect>
44
+ <button type="submit" class="btn btn-primary mt-5">Submit</button>
45
+ </form>
46
+ <pre class="mt-4 bg-slate-800 font-light text-xs p-3 rounded text-white">{{ {value} }}</pre>
47
+ `,
48
+ });
49
+
50
+ export const Optional = Template.bind({});
51
+ Optional.args = {
52
+ required: false,
53
+ placeholder: 'I dont like programing languages',
54
+ };
55
+
56
+ export const Required = Template.bind({});
57
+ Required.args = {
58
+ required: true,
59
+ placeholder: 'Choose a language',
60
+ };
61
+
62
+ export const Disabled = Template.bind({});
63
+ Disabled.args = {
64
+ required: true,
65
+ placeholder: 'Choose a language',
66
+ disabled: true,
67
+ };
@@ -1,59 +1,159 @@
1
1
  <template>
2
2
  <select
3
- :value="modelValue"
3
+ ref="select"
4
+ :value="modelValueInternal"
4
5
  :name="name"
5
6
  :disabled="disabled"
6
7
  :required="required"
7
- class="rounded"
8
+ class="rounded border border-slate-300 disabled:cursor-not-allowed disabled:text-slate-300 disabled:opacity-100"
9
+ :class="[!modelValue && required ? 'text-slate-400' : '']"
8
10
  @change="onChange($event)"
9
11
  >
10
- <option v-if="required" selected disabled hidden value="">
11
- {{ placeholder ? placeholder : $t('sui.select_an_option') }}
12
- </option>
12
+ <template v-if="required">
13
+ <option disabled hidden :value="EMPTY_VALUE_INTERNAL">
14
+ {{ placeholder ? placeholder : $t('sui.select_an_option') }}
15
+ </option>
16
+ </template>
17
+ <template v-else>
18
+ <option :value="EMPTY_VALUE_INTERNAL">
19
+ {{ placeholder ? placeholder : $t('sui.select_an_option') }}
20
+ </option>
21
+ </template>
13
22
  <slot />
14
23
  </select>
15
24
  </template>
16
25
 
17
- <script lang="ts">
18
- import { defineComponent, PropType } from 'vue';
19
- import { get } from 'lodash';
20
-
21
- export default defineComponent({
22
- props: {
23
- modelValue: {
24
- default: null,
25
- type: [String, Number, null] as PropType<string | number | null>,
26
- },
27
- name: {
28
- default: undefined,
29
- type: String,
30
- },
31
- placeholder: {
32
- default: '',
33
- type: String,
34
- },
35
- disabled: {
36
- default: false,
37
- type: Boolean,
38
- },
39
- required: {
40
- default: false,
41
- type: Boolean,
42
- },
26
+ <script lang="ts" setup>
27
+ import { PropType, Ref } from 'vue';
28
+ import { get, isEqual } from 'lodash';
29
+ import { useMounted } from '@vueuse/core';
30
+
31
+ type Option = string | number | null;
32
+
33
+ const EMPTY_VALUE_INTERNAL = '';
34
+ const EMPTY_VALUE_EXTERNAL = null;
35
+
36
+ const props = defineProps({
37
+ modelValue: {
38
+ default: undefined,
39
+ type: [String, Number, null, undefined] as PropType<Option>,
40
+ },
41
+ name: {
42
+ default: undefined,
43
+ type: String,
43
44
  },
44
- emits: ['update:modelValue'],
45
- methods: {
46
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
47
- onChange(event: Event): any {
48
- if (event === null) {
49
- this.$emit('update:modelValue', null);
50
- }
51
- const value = get(event, 'target.value', null);
52
- if (value === null) {
53
- this.$emit('update:modelValue', null);
54
- }
55
- this.$emit('update:modelValue', value);
56
- },
45
+ placeholder: {
46
+ default: '',
47
+ type: String,
57
48
  },
49
+ disabled: {
50
+ default: false,
51
+ type: Boolean,
52
+ },
53
+ required: {
54
+ default: false,
55
+ type: Boolean,
56
+ },
57
+ });
58
+
59
+ const mounted = useMounted();
60
+ const select = ref(null) as Ref<HTMLSelectElement | null>;
61
+
62
+ const emit = defineEmits(['update:modelValue']);
63
+
64
+ function isEmptyExternal(value: string | number | null | undefined) {
65
+ if (value === undefined || value === EMPTY_VALUE_EXTERNAL) {
66
+ return true;
67
+ }
68
+
69
+ return false;
70
+ }
71
+
72
+ function isEmptyInternal(value: string | number | null | undefined) {
73
+ if (value === undefined || value === EMPTY_VALUE_INTERNAL) {
74
+ return true;
75
+ }
76
+
77
+ return false;
78
+ }
79
+
80
+ /**
81
+ * Transform to external empty NULL
82
+ * to internal empty ''.
83
+ */
84
+ const modelValueInternal = computed(() => {
85
+ if (isEmptyExternal(props.modelValue)) {
86
+ return EMPTY_VALUE_INTERNAL;
87
+ }
88
+
89
+ if (!validModelValue()) {
90
+ return EMPTY_VALUE_INTERNAL;
91
+ }
92
+
93
+ return props.modelValue;
58
94
  });
95
+
96
+ /**
97
+ * Checks if the current modelValue is valid
98
+ */
99
+ function validModelValue(): boolean {
100
+ if (props.modelValue === EMPTY_VALUE_EXTERNAL) {
101
+ return true;
102
+ }
103
+
104
+ const options = [...(select.value?.options ?? [])];
105
+ return options.findIndex((o) => isEqual(o.value, props.modelValue)) != -1;
106
+ }
107
+
108
+ /**
109
+ * This watcher is used to update the parent value
110
+ * if the given modelValue should be empty.
111
+ */
112
+ watch(
113
+ () => props.modelValue,
114
+ () => validateAndFixModelVale()
115
+ );
116
+
117
+ /**
118
+ * Re-trigger the same validation on mounted
119
+ */
120
+ onMounted(() => {
121
+ validateAndFixModelVale();
122
+ });
123
+
124
+ /**
125
+ * Validate the current Model Value. Transform to external empty if :
126
+ * 1. is internal empty
127
+ * 2. is in the current options
128
+ */
129
+ function validateAndFixModelVale() {
130
+ if (!mounted.value) {
131
+ return;
132
+ }
133
+ if (isEmptyInternal(props.modelValue)) {
134
+ emit('update:modelValue', EMPTY_VALUE_EXTERNAL);
135
+ } else if (!validModelValue()) {
136
+ emit('update:modelValue', EMPTY_VALUE_EXTERNAL);
137
+ }
138
+ }
139
+
140
+ /**
141
+ *
142
+ * Emit change while mutating internal empty value ''
143
+ * to external empty value NULL.
144
+ */
145
+ function onChange(event: Event) {
146
+ if (event === null) {
147
+ emit('update:modelValue', EMPTY_VALUE_EXTERNAL);
148
+ }
149
+
150
+ const value = get(event, 'target.value', null);
151
+
152
+ if (isEmptyExternal(value)) {
153
+ emit('update:modelValue', EMPTY_VALUE_EXTERNAL);
154
+ return;
155
+ }
156
+
157
+ emit('update:modelValue', value);
158
+ }
59
159
  </script>
@@ -0,0 +1,55 @@
1
+ import BaseSideNavigation from './BaseSideNavigation.vue';
2
+ import BaseSideNavigationItem from './BaseSideNavigationItem.vue';
3
+ import BaseContainer from './BaseContainer.vue';
4
+ import BaseCard from './BaseCard.vue';
5
+ import BaseCardRow from './BaseCardRow.vue';
6
+
7
+ export default {
8
+ title: 'Layout/BaseSideNavigation',
9
+ component: BaseSideNavigation,
10
+ args: {},
11
+ };
12
+
13
+ const Template = (args) => ({
14
+ components: {
15
+ BaseSideNavigation,
16
+ BaseSideNavigationItem,
17
+ BaseContainer,
18
+ BaseCard,
19
+ BaseCardRow,
20
+ },
21
+ setup() {
22
+ return { args };
23
+ },
24
+ template: `
25
+ <div class="bg-slate-100 py-10">
26
+ <BaseContainer>
27
+ <div class="md:flex">
28
+ <div class="shrink-0 mb-6 md:mb-0" style="margin-right: 2rem; width: 200px;">
29
+ <BaseSideNavigation v-bind="args">
30
+ <BaseSideNavigationItem to="/">
31
+ Home
32
+ </BaseSideNavigationItem>
33
+ <BaseSideNavigationItem to="/setup">
34
+ Setup
35
+ </BaseSideNavigationItem>
36
+ <BaseSideNavigationItem to="/settings">
37
+ Settings
38
+ </BaseSideNavigationItem>
39
+ </BaseSideNavigation>
40
+ </div>
41
+ <div class="grow">
42
+ <BaseCard>
43
+ <BaseCardRow>
44
+ {{ $route.path }}
45
+ </BaseCardRow>
46
+ </BaseCard>
47
+ </div>
48
+ </div>
49
+ </BaseContainer>
50
+ </div>
51
+ `,
52
+ });
53
+
54
+ export const Demo = Template.bind({});
55
+ Demo.args = {};
@@ -1,6 +1,11 @@
1
1
  <template>
2
- <nav class="space-y-1" aria-label="Sidebar">
3
- <slot />
2
+ <nav aria-label="Sidebar" class="relative">
3
+ <div class="absolute bottom-0 left-0 h-full w-px bg-slate-300" />
4
+ <div class="relative overflow-x-auto overflow-y-hidden">
5
+ <div class="space-y-2">
6
+ <slot />
7
+ </div>
8
+ </div>
4
9
  </nav>
5
10
  </template>
6
11
 
@@ -3,15 +3,23 @@
3
3
  <a
4
4
  :href="disabled ? undefined : href"
5
5
  :disabled="disabled"
6
- class="flex items-center rounded-md px-3 py-2 text-sm font-medium"
6
+ class="group relative flex items-center px-3 py-1"
7
7
  :class="[
8
8
  isActive
9
- ? 'bg-slate-300 bg-opacity-60 text-black'
10
- : 'text-slate-600 hover:bg-slate-200 hover:bg-opacity-70 hover:text-slate-900',
9
+ ? 'font-semibold text-blue-600'
10
+ : 'text-slate-600 hover:text-slate-900',
11
11
  disabled ? 'cursor-not-allowed opacity-60' : '',
12
12
  ]"
13
13
  @click.prevent="onClick(navigate)"
14
14
  >
15
+ <div
16
+ class="absolute left-0 top-0 h-full"
17
+ :class="[
18
+ isActive
19
+ ? 'w-[2px] bg-blue-600'
20
+ : 'group-hover:w-px group-hover:bg-slate-700',
21
+ ]"
22
+ ></div>
15
23
  <slot />
16
24
  </a>
17
25
  </router-link>
@@ -0,0 +1,36 @@
1
+ import BaseSkeleton from './BaseSkeleton.vue';
2
+ import BaseContainer from './BaseContainer.vue';
3
+
4
+ export default {
5
+ title: 'Components/BaseSkeleton',
6
+ component: BaseSkeleton,
7
+ args: {},
8
+ };
9
+
10
+ const Template = (args) => ({
11
+ components: {
12
+ BaseSkeleton,
13
+ BaseContainer,
14
+ },
15
+ setup() {
16
+ return { args };
17
+ },
18
+ template: `
19
+ <BaseContainer size="xl">
20
+ <div class="flex space-x-5">
21
+ <div class="shrink-0">
22
+ <BaseSkeleton class="h-16 rounded-full w-16" v-bind="args"></BaseSkeleton>
23
+ </div>
24
+ <div class="grow">
25
+ <BaseSkeleton class="w-52 h-8 mb-3" v-bind="args"></BaseSkeleton>
26
+ <BaseSkeleton class="w-full h-4 mb-1" v-bind="args"></BaseSkeleton>
27
+ <BaseSkeleton class="w-full h-4 mb-1" v-bind="args"></BaseSkeleton>
28
+ <BaseSkeleton class="w-full h-4 mb-1" v-bind="args"></BaseSkeleton>
29
+ </div>
30
+ </div>
31
+ </BaseContainer>
32
+ `,
33
+ });
34
+
35
+ export const Demo = Template.bind({});
36
+ Demo.args = {};