@vcita/design-system 1.11.15 → 1.11.17
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/dist/@vcita/design-system.esm.js +558 -501
- package/dist/@vcita/design-system.min.js +2 -2
- package/dist/@vcita/design-system.ssr.js +441 -384
- package/package.json +1 -1
- package/src/components/VcMenuItem/VcMenuItem.vue +7 -2
- package/src/components/VcSearchLayout/VcSearchLayout.spec.js +2 -2
- package/src/components/VcSearchLayout/VcSearchLayout.stories.js +3 -3
- package/src/components/VcSearchLayout/VcSearchLayout.vue +4 -4
- package/src/components/VcSkeleton/VcSkeleton.stories.js +40 -3
- package/src/components/VcWideTopMenuBar/VcWideTopMenuBar.spec.js +26 -0
- package/src/components/VcWideTopMenuBar/VcWideTopMenuBar.stories.js +18 -1
- package/src/components/VcWideTopMenuBar/VcWideTopMenuBar.vue +37 -7
- package/styles/vuetify-variables.scss +6 -0
package/package.json
CHANGED
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
<v-expansion-panel-content eager v-for="(item, index) in submenuItems"
|
|
46
46
|
:class="`${isSelected && selectedSubitem === index ? 'selected' : ''} ${flavor}`">
|
|
47
47
|
<VcLayout
|
|
48
|
-
:class="`VcMenuItem-subitem VcMenuItem-userSelectNone ps-
|
|
48
|
+
:class="`VcMenuItem-subitem VcMenuItem-userSelectNone ps-6 ${size} ${flavor}`"
|
|
49
49
|
:data-qa="`${dataQa}-subitem-${item.name}`"
|
|
50
50
|
align-center
|
|
51
51
|
@click="$emit('onSubmenuClicked', item, index)">
|
|
@@ -193,13 +193,16 @@ export default {
|
|
|
193
193
|
|
|
194
194
|
.VcMenuItem-complex {
|
|
195
195
|
padding-inline-start: var(--size-value5);
|
|
196
|
-
border-inline-start: 3px solid transparent;
|
|
197
196
|
|
|
198
197
|
&.desktop {
|
|
199
198
|
padding-inline-start: 17px;
|
|
200
199
|
}
|
|
201
200
|
}
|
|
202
201
|
|
|
202
|
+
.v-expansion-panels:not(.v-expansion-panels--accordion):not(.v-expansion-panels--tile) > .v-expansion-panel--active {
|
|
203
|
+
border-radius: 0;
|
|
204
|
+
}
|
|
205
|
+
|
|
203
206
|
.desktop {
|
|
204
207
|
::v-deep {
|
|
205
208
|
.v-expansion-panel-header:hover {
|
|
@@ -284,6 +287,8 @@ export default {
|
|
|
284
287
|
&.desktop {
|
|
285
288
|
height: var(--size-value6);
|
|
286
289
|
color: var(--v-text-base);
|
|
290
|
+
margin: -8px 0px;
|
|
291
|
+
padding: var(--size-value5) var(--size-value12);
|
|
287
292
|
|
|
288
293
|
&:hover {
|
|
289
294
|
cursor: pointer;
|
|
@@ -75,7 +75,7 @@ const baseProps = {
|
|
|
75
75
|
label: 'Search with results',
|
|
76
76
|
value: false,
|
|
77
77
|
itemGroups: itemGroupsInput,
|
|
78
|
-
|
|
78
|
+
isSearching: false,
|
|
79
79
|
emptyStateTitle: undefined,
|
|
80
80
|
emptyStateSubtitle: undefined,
|
|
81
81
|
emptyStateImage: require('@/stories/assets/rabbit.svg'),
|
|
@@ -193,7 +193,7 @@ describe("VcSearchLayout.vue", () => {
|
|
|
193
193
|
props: {
|
|
194
194
|
...baseProps,
|
|
195
195
|
value: true,
|
|
196
|
-
|
|
196
|
+
isSearching: true,
|
|
197
197
|
},
|
|
198
198
|
});
|
|
199
199
|
|
|
@@ -64,7 +64,7 @@ const itemGroupsInput = [
|
|
|
64
64
|
|
|
65
65
|
const baseProps = {
|
|
66
66
|
label: 'Search with results',
|
|
67
|
-
|
|
67
|
+
isSearching: false,
|
|
68
68
|
emptyStateTitle: undefined,
|
|
69
69
|
emptyStateSubtitle: undefined,
|
|
70
70
|
emptyStateImage: require('@/stories/assets/rabbit.svg'),
|
|
@@ -85,7 +85,7 @@ const Template = (args, {argTypes}) => ({
|
|
|
85
85
|
:label="label"
|
|
86
86
|
:dataQa="dataQa"
|
|
87
87
|
:itemGroups="itemGroups"
|
|
88
|
-
:is-
|
|
88
|
+
:is-searching="isSearching"
|
|
89
89
|
:empty-state-title="emptyStateTitle"
|
|
90
90
|
:empty-state-subtitle="emptyStateSubtitle"
|
|
91
91
|
:empty-state-image="emptyStateImage"
|
|
@@ -121,7 +121,7 @@ export const Loading = Template.bind({});
|
|
|
121
121
|
// Set default values
|
|
122
122
|
Loading.args = {
|
|
123
123
|
...baseProps,
|
|
124
|
-
|
|
124
|
+
isSearching: true,
|
|
125
125
|
value: true,
|
|
126
126
|
itemGroups: undefined,
|
|
127
127
|
}
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
<VcSearchBar size="small" v-bind="$attrs" :data-qa="`${dataQa}-searchBar`" @search="onSearch"/>
|
|
7
7
|
</template>
|
|
8
8
|
<VcLayout class="searchResults" flex-wrap
|
|
9
|
-
:class="{loadingState:
|
|
10
|
-
<VcLoader v-if="
|
|
9
|
+
:class="{loadingState: isSearching, emptyState: !$attrs.itemGroups || $attrs.itemGroups.length === 0}">
|
|
10
|
+
<VcLoader v-if="isSearching"/>
|
|
11
11
|
<VcGroupedItems :item-groups="itemGroupsBolded" v-else-if="$attrs.itemGroups && $attrs.itemGroups.length > 0"
|
|
12
12
|
showDividers group-class="searchLayoutGroup" item-class="searchLayoutItem"
|
|
13
13
|
:data-qa="`${dataQa}-groupedItems`"
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
<template #footer>
|
|
37
37
|
<VcLayout column @click="$emit('onSeeAllClicked')">
|
|
38
38
|
<v-divider></v-divider>
|
|
39
|
-
<VcLayout v-if="!
|
|
39
|
+
<VcLayout v-if="!isSearching && $attrs.itemGroups && $attrs.itemGroups.length > 0" justify-center flex-wrap
|
|
40
40
|
align-center
|
|
41
41
|
class="viewAll">
|
|
42
42
|
<VcIcon small color="var(--blue)">$magnify_glass</VcIcon>
|
|
@@ -68,7 +68,7 @@ export default {
|
|
|
68
68
|
type: Boolean,
|
|
69
69
|
default: false,
|
|
70
70
|
},
|
|
71
|
-
|
|
71
|
+
isSearching: {
|
|
72
72
|
type: Boolean,
|
|
73
73
|
default: false,
|
|
74
74
|
},
|
|
@@ -4,14 +4,17 @@ import VcBaseDocs from '@/stories/VcBaseDocs.mdx';
|
|
|
4
4
|
const baseProps = {
|
|
5
5
|
type: 'list-item',
|
|
6
6
|
width: '100%',
|
|
7
|
+
height: '100%',
|
|
7
8
|
dataQa: 'VcSkeleton',
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
const Template = (args, {argTypes}) => ({
|
|
11
12
|
components: {VcSkeleton: VcSkeletonCmp},
|
|
12
13
|
props: Object.keys(argTypes),
|
|
13
|
-
template:
|
|
14
|
-
<
|
|
14
|
+
template: `
|
|
15
|
+
<div> for options see <a ref="https://vuetifyjs.com/en/components/skeleton-loaders">Vuetify skeleton loaders</a>
|
|
16
|
+
<VcSkeleton :type="type" :width="width" :height="height" :data-qa="dataQa"/>
|
|
17
|
+
</div>
|
|
15
18
|
`,
|
|
16
19
|
})
|
|
17
20
|
|
|
@@ -26,9 +29,43 @@ export default {
|
|
|
26
29
|
title: 'content display / VcSkeleton', // This will control the story sidebar position
|
|
27
30
|
id: 'VcSkeleton', // This will be the permanent link to this component
|
|
28
31
|
component: VcSkeletonCmp,
|
|
32
|
+
argTypes: {
|
|
33
|
+
type: {
|
|
34
|
+
options: ['button',
|
|
35
|
+
'chip',
|
|
36
|
+
'avatar',
|
|
37
|
+
'divider',
|
|
38
|
+
'heading',
|
|
39
|
+
'image',
|
|
40
|
+
'text',
|
|
41
|
+
'sentences',
|
|
42
|
+
'paragraph',
|
|
43
|
+
'actions',
|
|
44
|
+
'article',
|
|
45
|
+
'card',
|
|
46
|
+
'card-avatar',
|
|
47
|
+
'date-picker',
|
|
48
|
+
'date-picker-options',
|
|
49
|
+
'date-picker-days',
|
|
50
|
+
'list-item',
|
|
51
|
+
'list-item-avatar',
|
|
52
|
+
'list-item-two-line',
|
|
53
|
+
'list-item-avatar-two-line',
|
|
54
|
+
'list-item-three-line',
|
|
55
|
+
'list-item-avatar-three-line',
|
|
56
|
+
'table',
|
|
57
|
+
'table-heading',
|
|
58
|
+
'table-thead',
|
|
59
|
+
'table-tbody',
|
|
60
|
+
'table-row-divider',
|
|
61
|
+
'table-row',
|
|
62
|
+
'table-tfoot'],
|
|
63
|
+
control: {type: 'radio'}
|
|
64
|
+
},
|
|
65
|
+
},
|
|
29
66
|
parameters: {
|
|
30
67
|
status: {
|
|
31
|
-
type: 'beta', // 'beta'
|
|
68
|
+
type: 'beta', // 'beta' 'stable' 'deprecated' 'releaseCandidate'
|
|
32
69
|
url: 'https://vuetifyjs.com/en/components/skeleton-loaders', // will make the tag a link
|
|
33
70
|
},
|
|
34
71
|
docs: {
|
|
@@ -185,4 +185,30 @@ describe("VcWideTopMenuBar.vue", () => {
|
|
|
185
185
|
await VcWideTopMenuBar.methods.onAccountMenuClick.apply(params);
|
|
186
186
|
expect(params.isAccountMenuOpen).toBeFalsy();
|
|
187
187
|
});
|
|
188
|
+
|
|
189
|
+
it("should contain the 'customMenuItems' slot", async () => {
|
|
190
|
+
const innerElementText = 'Custom Menu Items';
|
|
191
|
+
const { getByText }= renderWithVuetify(VcWideTopMenuBar, {
|
|
192
|
+
props: {
|
|
193
|
+
...baseProps,
|
|
194
|
+
},
|
|
195
|
+
slots: {
|
|
196
|
+
customMenuItems: `<div>${innerElementText}</div>`
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
expect(getByText(innerElementText)).toBeInTheDocument();
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it("has loading state", async () => {
|
|
204
|
+
const { getAllByTestId }= renderWithVuetify(VcWideTopMenuBar, {
|
|
205
|
+
props: {
|
|
206
|
+
...baseProps,
|
|
207
|
+
isLoading: true,
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// test loading state
|
|
212
|
+
expect(getAllByTestId('VcSkeleton')).toHaveLength(6);
|
|
213
|
+
});
|
|
188
214
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import VcWideTopMenuBarCmp from './VcWideTopMenuBar';
|
|
2
2
|
import VcBaseDocs from '@/stories/VcBaseDocs.mdx'
|
|
3
|
+
import VcButton from "@/components/VcButton/VcButton.vue";
|
|
3
4
|
|
|
4
5
|
const baseProps = {
|
|
5
6
|
name: "John Smith",
|
|
@@ -39,10 +40,12 @@ const baseProps = {
|
|
|
39
40
|
showBackButton: true,
|
|
40
41
|
isNotificationsDialogOpen:false,
|
|
41
42
|
notificationsPane: '',
|
|
43
|
+
isLoading: false,
|
|
44
|
+
isSearching: false,
|
|
42
45
|
};
|
|
43
46
|
|
|
44
47
|
const Template = (args, {argTypes}) => ({
|
|
45
|
-
components: {VcWideTopMenuBar: VcWideTopMenuBarCmp},
|
|
48
|
+
components: {VcWideTopMenuBar: VcWideTopMenuBarCmp, VcButton},
|
|
46
49
|
props: Object.keys(argTypes),
|
|
47
50
|
template: `
|
|
48
51
|
<div>
|
|
@@ -61,6 +64,8 @@ const Template = (args, {argTypes}) => ({
|
|
|
61
64
|
:show-back-button="showBackButton"
|
|
62
65
|
:back-button-label="backButtonLabel"
|
|
63
66
|
:is-notifications-dialog-open="isNotificationsDialogOpen"
|
|
67
|
+
:is-loading="isLoading"
|
|
68
|
+
:is-searching="isSearching"
|
|
64
69
|
@onAccountButtonClicked="onAccountButtonClicked"
|
|
65
70
|
@onAccountMenuChange="onAccountMenuChange"
|
|
66
71
|
@onAccountMenuClick="onAccountMenuClick"
|
|
@@ -71,6 +76,9 @@ const Template = (args, {argTypes}) => ({
|
|
|
71
76
|
@onNotificationsDropdownToggle="onNotificationsDropdownToggle"
|
|
72
77
|
@onSearch="onSearch"
|
|
73
78
|
@onBackButtonClicked="onBackButtonClicked">
|
|
79
|
+
<template v-if="${Boolean(args.customMenuItems)}" #customMenuItems>
|
|
80
|
+
${args.customMenuItems}
|
|
81
|
+
</template>
|
|
74
82
|
<template #notificationsPane>
|
|
75
83
|
${args.notificationsPane}
|
|
76
84
|
</template>
|
|
@@ -108,7 +116,16 @@ WithNotificationsBadgeSlotContent.args = {
|
|
|
108
116
|
</div>`
|
|
109
117
|
}
|
|
110
118
|
|
|
119
|
+
export const WithCustomMenuItemsSlotContent = Template.bind({});
|
|
120
|
+
WithCustomMenuItemsSlotContent.args = {
|
|
121
|
+
...baseProps,
|
|
122
|
+
customMenuItems: `<VcButton ghost flavor="secondary">
|
|
123
|
+
Custom template
|
|
124
|
+
</VcButton>`
|
|
125
|
+
}
|
|
126
|
+
|
|
111
127
|
export default {
|
|
128
|
+
components: {VcButton},
|
|
112
129
|
title: 'desktop layout / VcWideTopMenuBar', // This will control the story sidebar position
|
|
113
130
|
id: 'VcWideTopMenuBar', // This will be the permanent link to this component
|
|
114
131
|
component: VcWideTopMenuBarCmp,
|
|
@@ -2,18 +2,26 @@
|
|
|
2
2
|
<VcLayout class="VcWideTopMenuBar" ref="compRoot" :data-qa="dataQa">
|
|
3
3
|
<VcLayout class="topBarSection leftSection" justify-end>
|
|
4
4
|
<VcLayout v-if="showBackButton" class="backButtonSection">
|
|
5
|
-
<div @click="$emit('onBackButtonClicked')" :data-qa="`${dataQa}-backButton`">
|
|
6
|
-
<VcIcon color="var(--gray-darken-3)" size="
|
|
5
|
+
<div v-if="!isLoading" @click="$emit('onBackButtonClicked')" :data-qa="`${dataQa}-backButton`">
|
|
6
|
+
<VcIcon color="var(--gray-darken-3)" size="var(--font-size-small2)">{{ $vuetify.rtl ? '$chevron_right' : '$chevron_left' }}</VcIcon>
|
|
7
7
|
<span class="backButtonLabel"> {{ backButtonLabel }} </span>
|
|
8
8
|
</div>
|
|
9
9
|
</VcLayout>
|
|
10
10
|
|
|
11
11
|
<VcLayout class="topBarSection searchSection">
|
|
12
|
-
<
|
|
12
|
+
<VcSkeleton v-if="isLoading" type="avatar"></VcSkeleton>
|
|
13
|
+
<VcSkeleton v-if="isLoading" type="list-item" width="100%"/>
|
|
14
|
+
<VcSearchLayout v-else v-bind="$attrs" v-on="$listeners" :data-qa="dataQa"/>
|
|
13
15
|
</VcLayout>
|
|
14
16
|
</VcLayout>
|
|
15
17
|
<VcLayout class="topBarSection rightSection" flex-wrap justify-end>
|
|
16
|
-
<
|
|
18
|
+
<template>
|
|
19
|
+
<VcSkeleton v-if="isLoading && $slots.customMenuItems" type="avatar"></VcSkeleton>
|
|
20
|
+
<!-- Slot for custom addition of items in top-bar -->
|
|
21
|
+
<slot v-else name="customMenuItems"/>
|
|
22
|
+
</template>
|
|
23
|
+
<VcSkeleton v-if="isLoading" type="avatar"></VcSkeleton>
|
|
24
|
+
<VcDropdown v-else v-model:value="isNotificationsDialogOpen"
|
|
17
25
|
:max-height="700"
|
|
18
26
|
:data-qa="`${dataQa}-notificationsPaneDropdown`"
|
|
19
27
|
@input="data => $emit('onNotificationsDropdownToggle', data)">
|
|
@@ -29,7 +37,9 @@
|
|
|
29
37
|
</template>
|
|
30
38
|
<slot name="notificationsPane"/>
|
|
31
39
|
</VcDropdown>
|
|
32
|
-
<
|
|
40
|
+
<VcSkeleton v-if="isLoading" type="avatar"></VcSkeleton>
|
|
41
|
+
<VcSkeleton v-if="isLoading && width > 1200" type="list-item" width="32"/>
|
|
42
|
+
<VcDropdown v-else-if="!isLoading" :data-qa="`${dataQa}-helpMenu`">
|
|
33
43
|
<template #activator="{ on, attrs }">
|
|
34
44
|
<VcButton class="helpButton specialButtonHeight" flavor="secondary" ghost :data-qa="`${dataQa}-help`"
|
|
35
45
|
@click="$emit('onHelpButtonClicked')" v-bind='attrs' v-on='on'>
|
|
@@ -50,7 +60,9 @@
|
|
|
50
60
|
</template>
|
|
51
61
|
</VcList>
|
|
52
62
|
</VcDropdown>
|
|
53
|
-
<
|
|
63
|
+
<VcSkeleton v-if="isLoading" type="avatar"></VcSkeleton>
|
|
64
|
+
<VcSkeleton v-if="isLoading && width > 784" type="list-item" width="59"/>
|
|
65
|
+
<VcButton v-else-if="!isLoading && upgradeButtonLabel" outlined small class="upgradeButton specialButtonHeight" :data-qa="`${dataQa}-upgrade`"
|
|
54
66
|
@click="$emit('onUpgradeButtonClicked')">
|
|
55
67
|
<template #prepend>
|
|
56
68
|
<VcIcon color="var(--v-secondary-base)">$upgrade</VcIcon>
|
|
@@ -63,7 +75,8 @@
|
|
|
63
75
|
@click="onAccountMenuClick"
|
|
64
76
|
:data-qa="`${dataQa}-accountMenu`">
|
|
65
77
|
<template #activator="{ on, attrs }">
|
|
66
|
-
<
|
|
78
|
+
<VcSkeleton v-if="isLoading" :type="width > 1040 ? 'list-item' : 'avatar'" width="59"/>
|
|
79
|
+
<VcButton v-else flavor="secondary" ghost class="accountMenuButton specialButtonHeight" :data-qa="`${dataQa}-account`"
|
|
67
80
|
@click="onAccountButtonClicked">
|
|
68
81
|
<template #prepend>
|
|
69
82
|
<VcAvatar :name="name" :color-id="colorId" :image-path="imagePath" size="x-sm" :data-qa="`${dataQa}-accountAvatar`"/>
|
|
@@ -91,10 +104,12 @@ import VcBadge from "@/components/VcBadge/VcBadge.vue";
|
|
|
91
104
|
import VcSearchLayout from "@/components/VcSearchLayout/VcSearchLayout.vue";
|
|
92
105
|
import VcDropdown from "@/components/VcMenu/VcDropdown.vue";
|
|
93
106
|
import VcList from "@/components/list/VcList/VcList.vue";
|
|
107
|
+
import VcSkeleton from "@/components/VcSkeleton/VcSkeleton.vue";
|
|
94
108
|
|
|
95
109
|
export default {
|
|
96
110
|
name: 'VcWideTopMenuBar',
|
|
97
111
|
components: {
|
|
112
|
+
VcSkeleton,
|
|
98
113
|
VcList,
|
|
99
114
|
VcDropdown, VcSearchLayout, VcIcon, VcLayout, VcAvatar, VcAccountMenu, VcButton, VcBadge
|
|
100
115
|
},
|
|
@@ -155,6 +170,20 @@ export default {
|
|
|
155
170
|
type: Boolean,
|
|
156
171
|
default: false
|
|
157
172
|
},
|
|
173
|
+
/**
|
|
174
|
+
* Indicates if the component is in loading state, which will display skeleton loaders
|
|
175
|
+
*/
|
|
176
|
+
isLoading: {
|
|
177
|
+
type: Boolean,
|
|
178
|
+
default: false,
|
|
179
|
+
},
|
|
180
|
+
/**
|
|
181
|
+
* This prop is passed down to VcSearchLayout
|
|
182
|
+
*/
|
|
183
|
+
isSearching: {
|
|
184
|
+
type: Boolean,
|
|
185
|
+
default: false,
|
|
186
|
+
},
|
|
158
187
|
dataQa: {
|
|
159
188
|
type: String,
|
|
160
189
|
default: 'VcWideTopMenuBar'
|
|
@@ -211,6 +240,7 @@ export default {
|
|
|
211
240
|
.searchSection {
|
|
212
241
|
flex-basis: 50%;
|
|
213
242
|
flex-grow: 0;
|
|
243
|
+
gap: var(--size-value2);
|
|
214
244
|
}
|
|
215
245
|
|
|
216
246
|
.rightSection {
|
|
@@ -46,3 +46,9 @@ $color-picker-border-radius: 4px;
|
|
|
46
46
|
// VcMenuItem - skeleton
|
|
47
47
|
$skeleton-loader-text-border-radius: 4px;
|
|
48
48
|
$skeleton-loader-item-padding: 0;
|
|
49
|
+
|
|
50
|
+
// Skeleton
|
|
51
|
+
$skeleton-loader-button-border-radius: 8px;
|
|
52
|
+
$skeleton-loader-list-item-height: 15px;
|
|
53
|
+
$skeleton-loader-avatar-height: 15px;
|
|
54
|
+
$skeleton-loader-avatar-width: 15px;
|