@vcita/design-system 1.3.2 → 1.3.4
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/config/locales/ds.en.yml +4 -0
- package/dist/@vcita/design-system.esm.js +1882 -1140
- package/dist/@vcita/design-system.min.js +2 -2
- package/dist/@vcita/design-system.ssr.js +1688 -965
- package/init/DesignSystem.js +3 -1
- package/init/initI18n.js +24 -16
- package/package.json +2 -1
- package/src/components/VcActionList/VcActionList.spec.js +16 -7
- package/src/components/VcActionList/VcActionList.stories.js +16 -3
- package/src/components/VcActionList/VcActionList.vue +35 -11
- package/src/components/VcBottomActions/VcBottomActions.vue +2 -1
- package/src/components/VcBottomSheet/VcBottomSheet.stories.js +6 -13
- package/src/components/VcBottomSheet/VcBottomSheet.vue +2 -3
- package/src/components/VcButton/VcButton.vue +1 -1
- package/src/components/VcCheckbox/VcCheckbox.vue +8 -1
- package/src/components/VcColorPicker/VcColorPicker.spec.js +206 -0
- package/src/components/VcColorPicker/VcColorPicker.stories.js +107 -0
- package/src/components/VcColorPicker/VcColorPicker.vue +270 -0
- package/src/components/VcFilterPanel/VcFilterPanel.spec.js +15 -0
- package/src/components/VcFilterPanel/VcFilterPanel.stories.js +9 -1
- package/src/components/VcFilterPanel/VcFilterPanel.vue +24 -3
- package/src/components/VcGalleryItem/VcGalleryItem.stories.js +2 -0
- package/src/components/VcGroupedItems/VcGroupedItems.spec.js +148 -0
- package/src/components/VcGroupedItems/VcGroupedItems.stories.js +135 -0
- package/src/components/VcGroupedItems/VcGroupedItems.vue +155 -0
- package/src/components/VcLink/VcLink.spec.js +3 -3
- package/src/components/VcLink/VcLink.stories.js +2 -6
- package/src/components/VcLink/VcLink.vue +1 -18
- package/src/components/VcMenu/VcDropdown.spec.js +120 -0
- package/src/components/VcMenu/VcDropdown.stories.js +272 -0
- package/src/components/VcMenu/VcDropdown.vue +93 -0
- package/src/components/VcMenu/VcMenu.spec.js +61 -10
- package/src/components/VcMenu/VcMenu.stories.js +38 -33
- package/src/components/VcMenu/VcMenu.vue +19 -3
- package/src/components/VcPopover/VcPopover.stories.js +2 -2
- package/src/components/VcRadioGroup/VcRadioGroup.spec.js +28 -0
- package/src/components/VcRadioGroup/VcRadioGroup.stories.js +3 -1
- package/src/components/VcRadioGroup/VcRadioGroup.vue +6 -1
- package/src/components/VcSearchPicker/VcSearchPicker.stories.js +3 -4
- package/src/components/VcSelectField/VcSelectField.vue +6 -0
- package/src/components/VcSideNav/VcSideNav.spec.js +1 -1
- package/src/components/VcSideNav/VcSideNav.vue +21 -104
- package/src/components/VcTextField/VcTextField.spec.js +13 -0
- package/src/components/VcTextField/VcTextField.stories.js +2 -1
- package/src/components/VcTextField/VcTextField.vue +11 -0
- package/src/components/VcTooltip/VcTooltip.stories.js +3 -1
- package/src/components/VcTooltip/VcTooltip.vue +6 -1
- package/src/components/index.js +4 -0
- package/src/components/list/VcBaseListItem/VcBaseListItem.stories.js +22 -13
- package/src/components/list/VcBaseListItem/VcBaseListItem.vue +4 -1
- package/src/components/list/VcList/VcList.stories.js +245 -240
- package/src/components/list/VcList/VcList.vue +11 -4
- package/src/components/page/layouts/centeredPage/CenteredPageLayout.stories.js +17 -16
- package/styles/variables.scss +1 -0
- package/styles/vuetify-variables.scss +9 -1
- package/CHANGELOG.md +0 -342
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<VcLayout column :data-qa="dataQa" class="grouped-items">
|
|
3
|
+
<div class="grouped-items__group mt-5"
|
|
4
|
+
v-for="(group, groupIndex) in itemGroups"
|
|
5
|
+
:key="group.id"
|
|
6
|
+
:data-qa="`group-${group.id}`">
|
|
7
|
+
<div :class="`grouped-items__group__header ${flavor} mb-2`" >
|
|
8
|
+
<slot :name="`group-${group.id}-header`" :group="group">
|
|
9
|
+
{{group.label}}
|
|
10
|
+
</slot>
|
|
11
|
+
</div>
|
|
12
|
+
<VcLayout column :class="`grouped-items__group__container ${flavor}`">
|
|
13
|
+
<VcLayout @click="$emit('change',item.id)"
|
|
14
|
+
:data-qa="`item-${item.id}`"
|
|
15
|
+
v-if="group.items"
|
|
16
|
+
v-for="(item) in group.items"
|
|
17
|
+
:key="item.id"
|
|
18
|
+
:class="{selected: item.id === selected, disabled: item.disabled, mobile: isMobile, 'rtl': $vuetify.rtl}"
|
|
19
|
+
class="grouped-items__group__container__menu-item d-flex align-center flex-grow-1">
|
|
20
|
+
<slot :name="`item-${item.id}`" :item="item">
|
|
21
|
+
<VcLayout justify-space-between align-center class="px-4 flex-grow-1">
|
|
22
|
+
<span>{{item.label}}</span>
|
|
23
|
+
<vcIcon size="12" v-if="isMobile">$chevron_right</vcIcon>
|
|
24
|
+
</VcLayout>
|
|
25
|
+
</slot>
|
|
26
|
+
</VcLayout>
|
|
27
|
+
</VcLayout>
|
|
28
|
+
<v-divider v-if="showDividers && groupIndex < itemGroups.length - 1"></v-divider>
|
|
29
|
+
</div>
|
|
30
|
+
</VcLayout>
|
|
31
|
+
</template>
|
|
32
|
+
<script>
|
|
33
|
+
|
|
34
|
+
import VcIcon from "@/components/VcIcon/VcIcon.vue";
|
|
35
|
+
import VcLayout from "@/components/VcLayout/VcLayout.vue";
|
|
36
|
+
|
|
37
|
+
export default {
|
|
38
|
+
name: "VcGroupedItems",
|
|
39
|
+
components: {VcLayout, VcIcon},
|
|
40
|
+
props: {
|
|
41
|
+
dataQa: {
|
|
42
|
+
type: String,
|
|
43
|
+
default: 'VcGroupedItems'
|
|
44
|
+
},
|
|
45
|
+
selected: {
|
|
46
|
+
type: String,
|
|
47
|
+
required: false,
|
|
48
|
+
},
|
|
49
|
+
itemGroups: {
|
|
50
|
+
type: Array,
|
|
51
|
+
validator: prop => prop.every((group) => group.label && group.id),
|
|
52
|
+
required: true,
|
|
53
|
+
},
|
|
54
|
+
flavor: {
|
|
55
|
+
type: String,
|
|
56
|
+
default: 'flat',
|
|
57
|
+
validator: value => ['flat', 'elevated'].includes(value),
|
|
58
|
+
},
|
|
59
|
+
showDividers: {
|
|
60
|
+
type: Boolean,
|
|
61
|
+
default: false,
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
model: {
|
|
65
|
+
prop: 'selected',
|
|
66
|
+
event: 'change'
|
|
67
|
+
},
|
|
68
|
+
computed: {
|
|
69
|
+
isMobile(){
|
|
70
|
+
return !this.$vuetify.breakpoint.mdAndUp
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
<style lang="scss" scoped>
|
|
77
|
+
.grouped-items{
|
|
78
|
+
&__group{
|
|
79
|
+
&__header{
|
|
80
|
+
font-size: var(--font-size-xx-small);
|
|
81
|
+
font-weight: var(--font-weight-large);
|
|
82
|
+
line-height: var(--size-value5);
|
|
83
|
+
color: var(--gray-darken-2);
|
|
84
|
+
|
|
85
|
+
&.flat {
|
|
86
|
+
padding-left: var(--size-value4);
|
|
87
|
+
font-size: var(--font-size-xxx-small);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
&__container{
|
|
91
|
+
border-radius: var(--border-radius);
|
|
92
|
+
background-color: var(--modal-bg-color);
|
|
93
|
+
&.elevated {
|
|
94
|
+
box-shadow: var(--shadow-1);
|
|
95
|
+
}
|
|
96
|
+
&__menu-item{
|
|
97
|
+
cursor: pointer;
|
|
98
|
+
box-sizing: border-box;
|
|
99
|
+
height: var(--size-value11);
|
|
100
|
+
font-weight: var(--font-weight-medium2);
|
|
101
|
+
font-size: var(--font-size-x-small);
|
|
102
|
+
border-inline-start: 3px solid var(--modal-bg-color);
|
|
103
|
+
transition: 0.3s;
|
|
104
|
+
transition-property: border-color, background-color;
|
|
105
|
+
&:first-of-type{
|
|
106
|
+
margin-top: var(--size-value1);
|
|
107
|
+
}
|
|
108
|
+
&:last-of-type{
|
|
109
|
+
margin-bottom: var(--size-value1);
|
|
110
|
+
}
|
|
111
|
+
&:hover{
|
|
112
|
+
border-color: var(--gray-lighten-3);
|
|
113
|
+
background-color: var(--gray-lighten-3);
|
|
114
|
+
}
|
|
115
|
+
&:focus{
|
|
116
|
+
border: 3px solid var(--v-secondary-lighten1);
|
|
117
|
+
}
|
|
118
|
+
&:active:not(.mobile){
|
|
119
|
+
border-color: var(--gray-lighten-1);
|
|
120
|
+
background-color: var(--gray-lighten-1);
|
|
121
|
+
}
|
|
122
|
+
&.selected{
|
|
123
|
+
font-weight: var(--font-weight-large);
|
|
124
|
+
}
|
|
125
|
+
&.selected:not(.mobile){
|
|
126
|
+
border-inline-start: 3px solid var(--v-secondary-base);
|
|
127
|
+
}
|
|
128
|
+
&.disabled{
|
|
129
|
+
cursor: unset;
|
|
130
|
+
pointer-events: none;
|
|
131
|
+
border-color: var(--gray-lighten-3);
|
|
132
|
+
background-color: var(--gray-lighten-3);
|
|
133
|
+
color: var(--gray-darken-2);
|
|
134
|
+
}
|
|
135
|
+
&.mobile{
|
|
136
|
+
color: var(--gray-darken-5);
|
|
137
|
+
height: var(--size-value13);
|
|
138
|
+
::v-deep{
|
|
139
|
+
svg.vc-chevron-right {
|
|
140
|
+
fill: var(--gray-darken-2);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
&.rtl{
|
|
144
|
+
::v-deep{
|
|
145
|
+
svg.vc-chevron-right {
|
|
146
|
+
transform: scaleX(-1);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
</style>
|
|
@@ -87,7 +87,7 @@ describe("VcLink.vue", () => {
|
|
|
87
87
|
const vcIconComponent = getByTestId('VcIcon');
|
|
88
88
|
expect(vcIconComponent).toBeInTheDocument();
|
|
89
89
|
expect(vcIconComponent).toHaveClass('prepend-icon');
|
|
90
|
-
expect(vcIconComponent).toHaveTextContent('
|
|
90
|
+
expect(vcIconComponent).toHaveTextContent('trash');
|
|
91
91
|
});
|
|
92
92
|
|
|
93
93
|
it("prepend icon - copy icon shows", () => {
|
|
@@ -101,7 +101,7 @@ describe("VcLink.vue", () => {
|
|
|
101
101
|
const vcIconComponent = getByTestId('VcIcon');
|
|
102
102
|
expect(vcIconComponent).toBeInTheDocument();
|
|
103
103
|
expect(vcIconComponent).toHaveClass('prepend-icon');
|
|
104
|
-
expect(vcIconComponent).toHaveTextContent('
|
|
104
|
+
expect(vcIconComponent).toHaveTextContent('copy');
|
|
105
105
|
});
|
|
106
106
|
|
|
107
107
|
it("prepend icon - left icon shows", () => {
|
|
@@ -115,7 +115,7 @@ describe("VcLink.vue", () => {
|
|
|
115
115
|
const vcIconComponent = getByTestId('VcIcon');
|
|
116
116
|
expect(vcIconComponent).toBeInTheDocument();
|
|
117
117
|
expect(vcIconComponent).toHaveClass('prepend-icon');
|
|
118
|
-
expect(vcIconComponent).toHaveTextContent('
|
|
118
|
+
expect(vcIconComponent).toHaveTextContent('left');
|
|
119
119
|
});
|
|
120
120
|
|
|
121
121
|
it('link click emits event', async () => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {default as VcLinkCmp
|
|
1
|
+
import {default as VcLinkCmp} from './VcLink';
|
|
2
2
|
import VcBaseDocs from "@/stories/VcBaseDocs.mdx";
|
|
3
3
|
|
|
4
4
|
const baseProps = {
|
|
@@ -41,7 +41,7 @@ export const WithPrependIcon = Template.bind({});
|
|
|
41
41
|
// Set default values
|
|
42
42
|
WithPrependIcon.args = {
|
|
43
43
|
...baseProps,
|
|
44
|
-
prependIcon: '
|
|
44
|
+
prependIcon: 'copy'
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
export default {
|
|
@@ -50,10 +50,6 @@ export default {
|
|
|
50
50
|
component: VcLinkCmp,
|
|
51
51
|
argTypes: {
|
|
52
52
|
onClick: {action: 'onClick', table: {disable: true}},
|
|
53
|
-
prependIcon: {
|
|
54
|
-
options: Object.values(VcLinkIcons),
|
|
55
|
-
control: {type: 'select'}
|
|
56
|
-
},
|
|
57
53
|
target:{
|
|
58
54
|
options: ['_blank', '_self', '_parent', '_top', '_system'],
|
|
59
55
|
control: {type: 'radio'}
|
|
@@ -4,16 +4,13 @@
|
|
|
4
4
|
:class="{'link-secondary': secondary, 'disabled' : disabled}"
|
|
5
5
|
:data-qa="dataQa"
|
|
6
6
|
@click="$emit('click')">
|
|
7
|
-
<VcIcon v-if="!!prependIcon" class="prepend-icon" small>{{
|
|
7
|
+
<VcIcon v-if="!!prependIcon" class="prepend-icon" small>{{ prependIcon }}</VcIcon>
|
|
8
8
|
<label>{{ label }}</label>
|
|
9
9
|
</a>
|
|
10
10
|
</template>
|
|
11
11
|
|
|
12
12
|
<script>
|
|
13
13
|
import VcIcon from "@/components/VcIcon/VcIcon.vue";
|
|
14
|
-
|
|
15
|
-
export const VcLinkIcons = ['', 'copy', 'trash', 'left'];
|
|
16
|
-
|
|
17
14
|
export default {
|
|
18
15
|
name: "VcLink",
|
|
19
16
|
components: {VcIcon},
|
|
@@ -33,7 +30,6 @@ export default {
|
|
|
33
30
|
prependIcon: {
|
|
34
31
|
type: String,
|
|
35
32
|
required: false,
|
|
36
|
-
validator: prop => VcLinkIcons.includes(prop)
|
|
37
33
|
},
|
|
38
34
|
dataQa: {
|
|
39
35
|
type: String,
|
|
@@ -48,19 +44,6 @@ export default {
|
|
|
48
44
|
type: Boolean,
|
|
49
45
|
default: false,
|
|
50
46
|
}
|
|
51
|
-
},
|
|
52
|
-
computed: {
|
|
53
|
-
getIcon() {
|
|
54
|
-
switch (this.prependIcon) {
|
|
55
|
-
case 'copy':
|
|
56
|
-
return '$copy';
|
|
57
|
-
case 'trash':
|
|
58
|
-
return '$trash';
|
|
59
|
-
case 'left':
|
|
60
|
-
default:
|
|
61
|
-
return '$chevron_left';
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
47
|
}
|
|
65
48
|
}
|
|
66
49
|
</script>
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import '@testing-library/jest-dom'
|
|
2
|
+
import VcDropdown from "./VcDropdown.vue";
|
|
3
|
+
import Vue from 'vue'
|
|
4
|
+
import Vuetify from 'vuetify'
|
|
5
|
+
import {render} from "@testing-library/vue";
|
|
6
|
+
import init from "../../../testing-library.config";
|
|
7
|
+
|
|
8
|
+
init();
|
|
9
|
+
|
|
10
|
+
Vue.use(Vuetify)
|
|
11
|
+
|
|
12
|
+
describe("VcDropdown.vue", () => {
|
|
13
|
+
|
|
14
|
+
const renderWithVuetify = (component, options, callback, isMobile = false) => {
|
|
15
|
+
const root = document.createElement('div');
|
|
16
|
+
root.setAttribute('data-app', 'true');
|
|
17
|
+
root.setAttribute('id', 'root');
|
|
18
|
+
|
|
19
|
+
const vuetify = new Vuetify()
|
|
20
|
+
if (isMobile) {
|
|
21
|
+
const breakpoint = {
|
|
22
|
+
init: jest.fn(),
|
|
23
|
+
framework: {},
|
|
24
|
+
smAndDown: true,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
vuetify.framework.breakpoint = breakpoint;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return render(
|
|
31
|
+
component,
|
|
32
|
+
{
|
|
33
|
+
container: document.body.appendChild(root),
|
|
34
|
+
// for Vuetify components that use the vuetify instance property
|
|
35
|
+
vuetify,
|
|
36
|
+
...options,
|
|
37
|
+
mocks: {
|
|
38
|
+
$t: value => value,
|
|
39
|
+
$dst: value => value, // <- for the design system
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
callback,
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
it("mounts", () => {
|
|
47
|
+
// Queries: https://testing-library.com/docs/queries/about#types-of-queries
|
|
48
|
+
const {container, getByTestId, getByText} = renderWithVuetify(VcDropdown, {
|
|
49
|
+
props: {
|
|
50
|
+
attach: '#root',
|
|
51
|
+
value: true,
|
|
52
|
+
},
|
|
53
|
+
slots: {
|
|
54
|
+
header: '<div>slot header</div>',
|
|
55
|
+
default: '<div>slot content</div>',
|
|
56
|
+
footer: '<div>slot footer</div>',
|
|
57
|
+
},
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// Expect options: https://github.com/testing-library/jest-dom
|
|
61
|
+
expect(container).toHaveAttribute('data-app', 'true');
|
|
62
|
+
|
|
63
|
+
// Make sure the component has the data-qa attribute
|
|
64
|
+
const header = getByTestId('VcDropdown-header');
|
|
65
|
+
expect(header).toBeInTheDocument();
|
|
66
|
+
const headerSlot = getByText('slot header');
|
|
67
|
+
expect(headerSlot).toBeInTheDocument();
|
|
68
|
+
|
|
69
|
+
const content = getByTestId('VcDropdown-content');
|
|
70
|
+
expect(content).toBeInTheDocument();
|
|
71
|
+
const contentSlot = getByText('slot content');
|
|
72
|
+
expect(contentSlot).toBeInTheDocument();
|
|
73
|
+
|
|
74
|
+
const footer = getByTestId('VcDropdown-footer');
|
|
75
|
+
expect(footer).toBeInTheDocument();
|
|
76
|
+
const footerSlot = getByText('slot footer');
|
|
77
|
+
expect(footerSlot).toBeInTheDocument();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("shows add another", () => {
|
|
81
|
+
// Queries: https://testing-library.com/docs/queries/about#types-of-queries
|
|
82
|
+
const {getByTestId, debug} = renderWithVuetify(VcDropdown, {
|
|
83
|
+
props: {
|
|
84
|
+
attach: '#root',
|
|
85
|
+
value: true,
|
|
86
|
+
showAddAnother: true,
|
|
87
|
+
},
|
|
88
|
+
slots: {
|
|
89
|
+
header: '<div>slot header</div>',
|
|
90
|
+
default: '<div>slot content</div>',
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
expect(getByTestId('VcDropdown-add')).toBeInTheDocument();
|
|
95
|
+
|
|
96
|
+
debug();
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("overrides add another label", () => {
|
|
102
|
+
// Queries: https://testing-library.com/docs/queries/about#types-of-queries
|
|
103
|
+
const {getByTestId, getByText} = renderWithVuetify(VcDropdown, {
|
|
104
|
+
props: {
|
|
105
|
+
attach: '#root',
|
|
106
|
+
value: true,
|
|
107
|
+
showAddAnother: true,
|
|
108
|
+
addAnotherLabel: 'override label',
|
|
109
|
+
},
|
|
110
|
+
slots: {
|
|
111
|
+
header: '<div>slot header</div>',
|
|
112
|
+
default: '<div>slot content</div>',
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
expect(getByTestId('VcDropdown-add')).toBeInTheDocument();
|
|
117
|
+
expect(getByText('override label')).toBeInTheDocument();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
});
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import VcDropdown from './VcDropdown';
|
|
2
|
+
import VcBaseDocs from '@/stories/VcBaseDocs.mdx'
|
|
3
|
+
import VcButton from "@/components/VcButton/VcButton";
|
|
4
|
+
import VcLayout from "@/components/VcLayout/VcLayout";
|
|
5
|
+
import VcSearchBar from "@/components/VcSearchBar/VcSearchBar";
|
|
6
|
+
import VcGroupedItems from "@/components/VcGroupedItems/VcGroupedItems";
|
|
7
|
+
import VcCheckbox from "@/components/VcCheckbox/VcCheckbox";
|
|
8
|
+
import VcList from "@/components/list/VcList/VcList";
|
|
9
|
+
import VcBadge from "@/components/VcBadge/VcBadge";
|
|
10
|
+
|
|
11
|
+
const Template = (args, {argTypes}) => ({
|
|
12
|
+
components: {VcDropdown, VcButton, VcLayout, VcSearchBar, VcGroupedItems, VcList, VcCheckbox, VcBadge},
|
|
13
|
+
props: Object.keys(argTypes),
|
|
14
|
+
data: () => ({
|
|
15
|
+
filter: '',
|
|
16
|
+
}),
|
|
17
|
+
template: `
|
|
18
|
+
<div>
|
|
19
|
+
You can use any props and events on this component that you can use on VcMenu
|
|
20
|
+
<br>
|
|
21
|
+
<VcDropdown :max-height="maxHeight" :dataQa="dataQa"
|
|
22
|
+
:show-add-another="showAddAnother" :add-another-label="addAnotherLabel"
|
|
23
|
+
@onAddItem="onAddItem">
|
|
24
|
+
<template #activator="{ on, attrs }">
|
|
25
|
+
${args.activator}
|
|
26
|
+
</template>
|
|
27
|
+
<template #header v-if="header">
|
|
28
|
+
${args.header}
|
|
29
|
+
</template>
|
|
30
|
+
${args.default}
|
|
31
|
+
<template #footer v-if="footer">
|
|
32
|
+
${args.footer}
|
|
33
|
+
</template>
|
|
34
|
+
</VcDropdown>
|
|
35
|
+
</div>`,
|
|
36
|
+
methods: {
|
|
37
|
+
onSearch(data) {
|
|
38
|
+
this.onSearchEvent(data);
|
|
39
|
+
this.filter = data;
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
computed: {
|
|
43
|
+
filteredItems() {
|
|
44
|
+
return this.listItems.filter(item => {
|
|
45
|
+
if (item.avatar?.name)
|
|
46
|
+
return item.avatar.name.toLowerCase().includes(this.filter);
|
|
47
|
+
else
|
|
48
|
+
return true;
|
|
49
|
+
});
|
|
50
|
+
},
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
export const Playground = Template.bind({});
|
|
55
|
+
|
|
56
|
+
// Set default values
|
|
57
|
+
Playground.args = {
|
|
58
|
+
dataQa: 'VcDropdown',
|
|
59
|
+
maxHeight: 297,
|
|
60
|
+
activator: `<VcButton v-bind='attrs' v-on='on'>Click me</VcButton>`,
|
|
61
|
+
header: `<VcLayout :style="{ minHeight: '48px', minWidth: '220px' ,backgroundColor: 'var(--green-lighten-2)', border: 'dashed var(--green)'}">header slot (sticky)</VcLayout>`,
|
|
62
|
+
default: `<VcLayout :style="{ minHeight: '400px', backgroundColor: 'var(--green-lighten-2)',border: 'dashed var(--green)'}">content slot (scrolling)</VcLayout>`,
|
|
63
|
+
footer: `<VcLayout align-center justify-center :style="{ minHeight: '48px', backgroundColor: 'var(--green-lighten-2)', border: 'dashed var(--green)'}">footer slot (sticky)</VcLayout>`,
|
|
64
|
+
showAddAnother: false,
|
|
65
|
+
addAnotherLabel: '',
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const listItems = [
|
|
69
|
+
{
|
|
70
|
+
disabled: true,
|
|
71
|
+
avatar:
|
|
72
|
+
{
|
|
73
|
+
name: 'Person One',
|
|
74
|
+
path: require('@/stories/assets/pics/avatar4.png'),
|
|
75
|
+
},
|
|
76
|
+
identifier: 0
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
disabled: true,
|
|
80
|
+
avatar: {
|
|
81
|
+
name: 'Person Two',
|
|
82
|
+
path: require('@/stories/assets/pics/avatar2.png'),
|
|
83
|
+
},
|
|
84
|
+
identifier: 1
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
selected: true,
|
|
88
|
+
avatar: {
|
|
89
|
+
name: 'Person Three',
|
|
90
|
+
path: require('@/stories/assets/pics/avatar1.png'),
|
|
91
|
+
},
|
|
92
|
+
identifier: 2
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
selected: true,
|
|
96
|
+
avatar: {
|
|
97
|
+
name: 'Person Four',
|
|
98
|
+
colorId: 3,
|
|
99
|
+
},
|
|
100
|
+
identifier: 3
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
avatar: {
|
|
104
|
+
name: 'Person Five',
|
|
105
|
+
colorId: 4,
|
|
106
|
+
},
|
|
107
|
+
identifier: 4
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
export const SimpleListMenu = Template.bind({});
|
|
112
|
+
|
|
113
|
+
// Set default values
|
|
114
|
+
SimpleListMenu.args = {
|
|
115
|
+
dataQa: 'VcDropdown',
|
|
116
|
+
maxHeight: 297,
|
|
117
|
+
activator: `<VcButton v-bind='attrs' v-on='on'>Click me</VcButton>`,
|
|
118
|
+
default: `<VcList :items='filteredItems' multiple @select='onSelect'>
|
|
119
|
+
<template #default='item'>
|
|
120
|
+
<VcCheckbox :label='item.avatar.name'
|
|
121
|
+
:avatar='item.avatar'
|
|
122
|
+
:checked='item.selected'
|
|
123
|
+
:disabled='item.disabled'
|
|
124
|
+
:show-border='false'
|
|
125
|
+
style='padding: 0; margin: 0; flex: 1 1 auto'/>
|
|
126
|
+
</template>
|
|
127
|
+
</VcList>`,
|
|
128
|
+
listItems,
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export const WithSearchAndAddItem = Template.bind({});
|
|
132
|
+
|
|
133
|
+
// Set default values
|
|
134
|
+
WithSearchAndAddItem.args = {
|
|
135
|
+
dataQa: 'VcDropdown',
|
|
136
|
+
activator: `<VcButton v-bind='attrs' v-on='on'>Click me</VcButton>`,
|
|
137
|
+
header: `<VcLayout :style="{margin: '4px'}"><VcSearchBar size='medium' @search='onSearch'></VcSearchBar></VcLayout>`,
|
|
138
|
+
default: `<VcList :items='filteredItems' multiple @select='onSelect'>
|
|
139
|
+
<template #default='item'>
|
|
140
|
+
<VcCheckbox :label='item.avatar.name'
|
|
141
|
+
:avatar='item.avatar'
|
|
142
|
+
:checked='item.selected'
|
|
143
|
+
:disabled='item.disabled'
|
|
144
|
+
show-border='false'
|
|
145
|
+
style='padding: 0; margin: 0; flex: 1 1 auto'/>
|
|
146
|
+
</template>
|
|
147
|
+
</VcList>`,
|
|
148
|
+
showAddAnother: true,
|
|
149
|
+
listItems,
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const menuItems = [
|
|
153
|
+
{
|
|
154
|
+
label: 'GROUP 1',
|
|
155
|
+
id: 1,
|
|
156
|
+
items: [
|
|
157
|
+
{id: '1', label: 'Menu Item 1'},
|
|
158
|
+
{id: '2', label: 'Menu Item 2'},
|
|
159
|
+
{id: '3', label: 'Menu Item 3'},
|
|
160
|
+
{id: '4', label: 'Menu Item 4'},
|
|
161
|
+
{id: '5', label: 'Menu Item 5', disabled: true},
|
|
162
|
+
]
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
label: 'GROUP 2',
|
|
166
|
+
id: 2,
|
|
167
|
+
items: [
|
|
168
|
+
{id: '6', label: 'Menu Item 6'},
|
|
169
|
+
{id: '7', label: 'Menu Item 7'},
|
|
170
|
+
{id: '8', label: 'Menu Item 8'},
|
|
171
|
+
{id: '9', label: 'Menu Item 9'},
|
|
172
|
+
{id: '10', label: 'Menu Item 10'},
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
];
|
|
176
|
+
|
|
177
|
+
const GroupedTemplate = (args, {argTypes}) => ({
|
|
178
|
+
components: {VcDropdown, VcButton, VcLayout, VcGroupedItems, VcCheckbox},
|
|
179
|
+
props: Object.keys(argTypes),
|
|
180
|
+
template: `
|
|
181
|
+
<div>
|
|
182
|
+
You can use any props and events on this component that you can use on VcMenu
|
|
183
|
+
<br>
|
|
184
|
+
<VcDropdown :max-height="maxHeight" :dataQa="dataQa"
|
|
185
|
+
:show-add-another="showAddAnother" :add-another-label="addAnotherLabel"
|
|
186
|
+
@onAddItem="onAddItem">
|
|
187
|
+
<template #activator="{ on, attrs }">
|
|
188
|
+
${args.activator}
|
|
189
|
+
</template>
|
|
190
|
+
<template #header v-if="header">
|
|
191
|
+
${args.header}
|
|
192
|
+
</template>
|
|
193
|
+
${args.default}
|
|
194
|
+
<template #footer v-if="footer">
|
|
195
|
+
${args.footer}
|
|
196
|
+
</template>
|
|
197
|
+
</VcDropdown>
|
|
198
|
+
</div>`,
|
|
199
|
+
methods: {
|
|
200
|
+
getItemSlotName(itemId) {
|
|
201
|
+
return `item-${itemId}`;
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
computed: {
|
|
205
|
+
allGroupedItems() {
|
|
206
|
+
return this.menuItems.reduce((acc, group) => acc.concat(group.items), []);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
export const WithGroupedItems = GroupedTemplate.bind({});
|
|
212
|
+
|
|
213
|
+
// Set default values
|
|
214
|
+
WithGroupedItems.args = {
|
|
215
|
+
dataQa: 'VcDropdown',
|
|
216
|
+
maxHeight: 297,
|
|
217
|
+
activator: `<VcButton v-bind='attrs' v-on='on'>Click me</VcButton>`,
|
|
218
|
+
default: `<VcLayout :style="{ minHeight: '400px'}">
|
|
219
|
+
<VcGroupedItems :item-groups='menuItems' show-dividers @change='onChange'>
|
|
220
|
+
<template #group-1-header='groupData'>
|
|
221
|
+
<div class='d-flex align-center'>
|
|
222
|
+
<span>{{groupData.group.label}}</span>
|
|
223
|
+
<VcBadge class='ps-2' badgeText='new' :offsetX='-2' :offsetY='0'></VcBadge>
|
|
224
|
+
</div>
|
|
225
|
+
</template>
|
|
226
|
+
|
|
227
|
+
<template v-for='item in allGroupedItems' #[getItemSlotName(item.id)]='data'>
|
|
228
|
+
<div class='d-flex align-center flex-grow-1 px-4'>
|
|
229
|
+
<VcCheckbox :label='item.label'
|
|
230
|
+
:checked='item.selected'
|
|
231
|
+
:disabled='item.disabled'
|
|
232
|
+
:show-border='false'
|
|
233
|
+
style='padding: 0; margin: 0; flex: 1 1 auto'/>
|
|
234
|
+
</div>
|
|
235
|
+
</template>
|
|
236
|
+
<template v-for='item in allGroupedItems' #item-4>
|
|
237
|
+
<div class='d-flex align-center flex-grow-1 px-4'>
|
|
238
|
+
<span>Slot display override</span>
|
|
239
|
+
<VcBadge class='ps-2' badgeText='new' :offsetX='-2' :offsetY='0'></VcBadge>
|
|
240
|
+
</div>
|
|
241
|
+
</template>
|
|
242
|
+
</VcGroupedItems>
|
|
243
|
+
</VcLayout>`,
|
|
244
|
+
menuItems,
|
|
245
|
+
showAddAnother: true,
|
|
246
|
+
addAnotherLabel: 'Click to add item',
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export default {
|
|
250
|
+
title: 'containers / menu / VcDropdown', // This will control the story sidebar position
|
|
251
|
+
id: 'VcDropdown', // This will be the permanent link to this component
|
|
252
|
+
component: VcDropdown,
|
|
253
|
+
argTypes: {
|
|
254
|
+
onSelect: {action: 'select', table: {disable: true}},
|
|
255
|
+
onSearchEvent: {action: 'search', table: {disable: true}},
|
|
256
|
+
onChange: {action: 'change', table: {disable: true}},
|
|
257
|
+
},
|
|
258
|
+
parameters: {
|
|
259
|
+
design: {
|
|
260
|
+
type: 'figma',
|
|
261
|
+
url: 'https://www.figma.com/file/xIOY6fBoA1wpy1tHv3i5js/vcita---ui-library?node-id=251%3A908',
|
|
262
|
+
},
|
|
263
|
+
status: {
|
|
264
|
+
type: 'beta', // 'beta' | 'stable' | 'deprecated' | 'releaseCandidate'
|
|
265
|
+
},
|
|
266
|
+
docs: {
|
|
267
|
+
page: VcBaseDocs,
|
|
268
|
+
inlineStories: false,
|
|
269
|
+
iframeHeight: 400,
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
};
|