@vcita/design-system 1.1.6 → 1.1.7-beta.1
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 +1097 -896
- package/dist/@vcita/design-system.min.js +2 -2
- package/dist/@vcita/design-system.ssr.js +1000 -796
- package/init/DesignSystem.js +8 -2
- package/package.json +1 -1
- package/src/components/VcDocItem/VcDocItem.vue +1 -1
- package/src/components/VcSearchPicker/VcSearchPicker.spec.js +15 -0
- package/src/components/VcSearchPicker/VcSearchPicker.stories.js +5 -0
- package/src/components/VcSearchPicker/VcSearchPicker.vue +10 -3
- package/src/components/VcSearchPicker/mockData.js +1 -1
- package/src/components/VcTabs/VcTabs.spec.js +57 -0
- package/src/components/VcTabs/VcTabs.stories.js +182 -0
- package/src/components/VcTabs/VcTabs.vue +125 -0
- package/src/components/VcUpsellBlock/VcUpsellBlock.stories.js +24 -0
- package/src/components/index.js +1 -0
- package/src/components/wizard/VcWizard/VcWizard.stories.js +2 -2
- package/src/stories/welcome.stories.mdx +0 -6
- package/styles/variables.scss +0 -4
package/init/DesignSystem.js
CHANGED
|
@@ -43,7 +43,10 @@ import {
|
|
|
43
43
|
VBadge,
|
|
44
44
|
VRadioGroup,
|
|
45
45
|
VRadio,
|
|
46
|
-
|
|
46
|
+
VTabs,
|
|
47
|
+
VTab,
|
|
48
|
+
VTabsItems,
|
|
49
|
+
VTabItem,
|
|
47
50
|
} from "vuetify/lib/components";
|
|
48
51
|
// import initI18n from "./initI18n";
|
|
49
52
|
import svgImages from "./svgImages";
|
|
@@ -91,7 +94,10 @@ Vue.use(Vuetify, {
|
|
|
91
94
|
VBadge,
|
|
92
95
|
VRadioGroup,
|
|
93
96
|
VRadio,
|
|
94
|
-
|
|
97
|
+
VTabs,
|
|
98
|
+
VTab,
|
|
99
|
+
VTabsItems,
|
|
100
|
+
VTabItem,
|
|
95
101
|
}
|
|
96
102
|
});
|
|
97
103
|
|
package/package.json
CHANGED
|
@@ -47,7 +47,7 @@ import VcIcon from "@/components/VcIcon/VcIcon.vue";
|
|
|
47
47
|
import VcButton from "../VcButton/VcButton.vue";
|
|
48
48
|
const FORMATS = {
|
|
49
49
|
DOCUMENT: ['doc', 'docx'],
|
|
50
|
-
IMAGE: ['jpg', 'jpeg', 'png', 'gif', 'bmp'],
|
|
50
|
+
IMAGE: ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg'],
|
|
51
51
|
PDF: ['pdf'],
|
|
52
52
|
SPREADSHEET: ['csv', 'xls', 'xlsx'],
|
|
53
53
|
SLIDESHOW: ['ppt', 'pptx'],
|
|
@@ -166,4 +166,19 @@ describe("VcSearchPicker.vue", () => {
|
|
|
166
166
|
await updateProps({ loading: false });
|
|
167
167
|
expect(spinner).not.toBeInTheDocument();
|
|
168
168
|
});
|
|
169
|
+
|
|
170
|
+
it("Renders custom menu class name", async () => {
|
|
171
|
+
const CLASSNAME_A = 'abc'
|
|
172
|
+
const CLASSNAME_B = 'def'
|
|
173
|
+
const { container, updateProps } = renderWithVuetify(VcSearchPicker, {
|
|
174
|
+
props: { menuContentClass: CLASSNAME_A }
|
|
175
|
+
});
|
|
176
|
+
const autoComplete = await container.getElementsByClassName('autocomplete')[0];
|
|
177
|
+
await fireEvent.click(autoComplete);
|
|
178
|
+
const menuContent = await container.querySelector('.v-menu__content');
|
|
179
|
+
expect(menuContent).toHaveClass(CLASSNAME_A);
|
|
180
|
+
await updateProps({ menuContentClass: CLASSNAME_B });
|
|
181
|
+
expect(menuContent).not.toHaveClass(CLASSNAME_A);
|
|
182
|
+
expect(menuContent).toHaveClass(CLASSNAME_B);
|
|
183
|
+
});
|
|
169
184
|
});
|
|
@@ -20,6 +20,7 @@ const Template = (args, {argTypes}) => ({
|
|
|
20
20
|
:showInnerIcon="showInnerIcon"
|
|
21
21
|
:items="this.items"
|
|
22
22
|
:selectedItems="exampleSelected"
|
|
23
|
+
:menuContentClass="menuContentClass"
|
|
23
24
|
@onSelectionChange="newVal => this.exampleSelected = newVal"
|
|
24
25
|
@onSearchInput="searchInput"
|
|
25
26
|
@onScrollEnd="scrollEnd"
|
|
@@ -54,6 +55,7 @@ const Template2 = (args, {argTypes}) => ({
|
|
|
54
55
|
:showInnerIcon="showInnerIcon"
|
|
55
56
|
:items="this.items"
|
|
56
57
|
:selectedItems="exampleSelected"
|
|
58
|
+
:menuContentClass="menuContentClass"
|
|
57
59
|
@onSelectionChange="newVal => this.exampleSelected = newVal"
|
|
58
60
|
@onSearchInput="searchInput"
|
|
59
61
|
@onScrollEnd="scrollEnd"
|
|
@@ -74,6 +76,7 @@ DocumentItem.args = {
|
|
|
74
76
|
errorLabelText: 'Please select A document',
|
|
75
77
|
noDataText: 'No documents found',
|
|
76
78
|
iconType: 'folder',
|
|
79
|
+
menuContentClass: 'custom- content- class',
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
|
|
@@ -94,6 +97,7 @@ const Template3 = (args, {argTypes}) => ({
|
|
|
94
97
|
:showInnerIcon="showInnerIcon"
|
|
95
98
|
:items="this.items"
|
|
96
99
|
:selectedItems="exampleSelected"
|
|
100
|
+
:menuContentClass="menuContentClass"
|
|
97
101
|
@onSelectionChange="newVal => this.exampleSelected = newVal"
|
|
98
102
|
@onSearchInput="searchInput"
|
|
99
103
|
@onScrollEnd="scrollEnd"
|
|
@@ -138,6 +142,7 @@ const Template4 = (args, {argTypes}) => ({
|
|
|
138
142
|
:showInnerIcon="showInnerIcon"
|
|
139
143
|
:items="this.items"
|
|
140
144
|
v-model="exampleSelected"
|
|
145
|
+
:menuContentClass="menuContentClass"
|
|
141
146
|
@onSelectionChange="selectionChange"
|
|
142
147
|
@onSearchInput="searchInput"
|
|
143
148
|
@onScrollEnd="scrollEnd"
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
'autocomplete--has-items': selectedItems.length,
|
|
11
11
|
'autocomplete--search-content': searchInput && searchInput.length,
|
|
12
12
|
}"
|
|
13
|
+
:menu-content-class="menuContentClass"
|
|
13
14
|
:menu-props="menuProps"
|
|
14
15
|
:search-input.sync="searchInput"
|
|
15
16
|
@update:search-input="(text) => text && text.length && $emit('onSearchInput', text)"
|
|
@@ -105,6 +106,10 @@ export default {
|
|
|
105
106
|
error: {
|
|
106
107
|
type: Boolean,
|
|
107
108
|
default: false,
|
|
109
|
+
},
|
|
110
|
+
menuContentClass: {
|
|
111
|
+
type: String,
|
|
112
|
+
default: ''
|
|
108
113
|
}
|
|
109
114
|
},
|
|
110
115
|
data() {
|
|
@@ -120,7 +125,7 @@ export default {
|
|
|
120
125
|
menuProps() {
|
|
121
126
|
return {
|
|
122
127
|
value: this.focused,
|
|
123
|
-
contentClass:
|
|
128
|
+
contentClass: `vc-select-field-menu ${this.menuContentClass}`
|
|
124
129
|
}
|
|
125
130
|
},
|
|
126
131
|
noData() {
|
|
@@ -173,14 +178,15 @@ export default {
|
|
|
173
178
|
}
|
|
174
179
|
.v-input__icon--append .v-icon {
|
|
175
180
|
transform: rotate(0deg);
|
|
181
|
+
color: var(--gray-darken-3)!important;
|
|
176
182
|
}
|
|
177
183
|
.autocomplete--open {
|
|
178
184
|
.v-input__icon--append .v-icon {
|
|
179
185
|
transform: rotate(180deg)
|
|
180
186
|
}
|
|
181
187
|
.v-input__slot {
|
|
182
|
-
border-color: var(--
|
|
183
|
-
outline:
|
|
188
|
+
border-color: var(--v-primary-base);
|
|
189
|
+
outline: 2px solid var(--v-primary-lighten5);
|
|
184
190
|
}
|
|
185
191
|
}
|
|
186
192
|
.autocomplete {
|
|
@@ -241,6 +247,7 @@ export default {
|
|
|
241
247
|
display: inline-block;
|
|
242
248
|
font-size: var(--font-size-small2);
|
|
243
249
|
color: var(--gray-darken-5);
|
|
250
|
+
caret-color: currentColor;
|
|
244
251
|
}
|
|
245
252
|
}
|
|
246
253
|
|
|
@@ -12,7 +12,7 @@ const characters = [
|
|
|
12
12
|
const documents = [
|
|
13
13
|
{ text: 'Client Contract.pdf', value: 'f22fbda2-637e-4df5-9106-435dc8ade089'},
|
|
14
14
|
{ text: 'Brochure.jpeg', value: '03f95bb8-8435-499f-9ca7-efb23a3692f2'},
|
|
15
|
-
{ text: 'Application and Offer Logic And a very long text', value: '13a34bf5-230e-481b-9808-d2d6ac4364dd' },
|
|
15
|
+
{ text: 'Application and Offer Logic And a very long text'.repeat(10), value: '13a34bf5-230e-481b-9808-d2d6ac4364dd' },
|
|
16
16
|
{ text: 'Great music.mp3', value: '758f20ee-499e-4892-abb5-65626bd31b35' },
|
|
17
17
|
{ text: 'Client Contract1.xls', value: '84e3c394-d92a-4a21-8b05-5680c3f10eb0' },
|
|
18
18
|
{ text: 'Brochure.pptx', value: '17efc973-8a0f-4b6e-a3a1-db65d663032f' },
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import '@testing-library/jest-dom'
|
|
2
|
+
import VcTabs from "./VcTabs.vue";
|
|
3
|
+
import Vue from 'vue'
|
|
4
|
+
import Vuetify from 'vuetify'
|
|
5
|
+
import {render} from "@testing-library/vue";
|
|
6
|
+
import userEvent from '@testing-library/user-event';
|
|
7
|
+
|
|
8
|
+
Vue.use(Vuetify)
|
|
9
|
+
|
|
10
|
+
describe("VcTabs.vue", () => {
|
|
11
|
+
|
|
12
|
+
const renderWithVuetify = (component, options, callback, isMobile = false) => {
|
|
13
|
+
const root = document.createElement('div')
|
|
14
|
+
root.setAttribute('data-app', 'true')
|
|
15
|
+
|
|
16
|
+
const vuetify = new Vuetify()
|
|
17
|
+
if (isMobile) {
|
|
18
|
+
const breakpoint = {
|
|
19
|
+
init: jest.fn(),
|
|
20
|
+
framework: {},
|
|
21
|
+
smAndDown: true,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
vuetify.framework.breakpoint = breakpoint;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return render(
|
|
28
|
+
component,
|
|
29
|
+
{
|
|
30
|
+
container: document.body.appendChild(root),
|
|
31
|
+
// for Vuetify components that use the vuetify instance property
|
|
32
|
+
vuetify,
|
|
33
|
+
...options,
|
|
34
|
+
mocks: {
|
|
35
|
+
$t: value => value,
|
|
36
|
+
$dst: value => value, // <- for the design system
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
callback,
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
it("mounts", () => {
|
|
44
|
+
// Queries: https://testing-library.com/docs/queries/about#types-of-queries
|
|
45
|
+
const {container, getByTestId} = renderWithVuetify(VcTabs, {
|
|
46
|
+
props: {}
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
// Expect options: https://github.com/testing-library/jest-dom
|
|
50
|
+
expect(container).toHaveAttribute('data-app', 'true');
|
|
51
|
+
|
|
52
|
+
// Make sure the component has the data-qa attribute
|
|
53
|
+
const component = getByTestId('VcTabs');
|
|
54
|
+
expect(component).toBeInTheDocument();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
});
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import VcTabsCmp from './VcTabs';
|
|
2
|
+
import VcForm from "@/components/VcForm/VcForm";
|
|
3
|
+
import VcTextField from "@/components/VcTextField/VcTextField";
|
|
4
|
+
import VcImage from "@/components/VcImage/VcImage";
|
|
5
|
+
import VcLoader from "@/components/VcLoader/VcLoader";
|
|
6
|
+
import VcIcon from "@/components/VcIcon/VcIcon";
|
|
7
|
+
|
|
8
|
+
const basicProps = {
|
|
9
|
+
tabs: [{label: 'Tab 1'}, {label: 'Tab 2'}, {label: 'Tab 3'}, {label: 'Tab 4'},],
|
|
10
|
+
distribution: 'start',
|
|
11
|
+
tabSize: 'M',
|
|
12
|
+
separatorStyle: 'default',
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const Template = (args, {argTypes}) => ({
|
|
16
|
+
components: {VcTabs: VcTabsCmp},
|
|
17
|
+
props: Object.keys(argTypes),
|
|
18
|
+
data: () => ({
|
|
19
|
+
currentIndex: null,
|
|
20
|
+
}),
|
|
21
|
+
template: `
|
|
22
|
+
<div>
|
|
23
|
+
Known issue: When using the tab key in the keyboard to navigate between tabs, you can reach disabled tabs.
|
|
24
|
+
This issue is fixed in Vuetify 2.6.8, and so will be fixed once we upgrade the Vuetify version.
|
|
25
|
+
<VcTabs :tabs="tabs"
|
|
26
|
+
:distribution="distribution"
|
|
27
|
+
:tab-size="tabSize"
|
|
28
|
+
:separator-style="separatorStyle"
|
|
29
|
+
v-model="currentIndex"
|
|
30
|
+
@change="onChange">
|
|
31
|
+
</VcTabs>
|
|
32
|
+
</div>`,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export const Playground = Template.bind({});
|
|
36
|
+
|
|
37
|
+
// Set default values
|
|
38
|
+
Playground.args = {
|
|
39
|
+
...basicProps,
|
|
40
|
+
tabs: [{label: 'Tab 1'}, {label: 'Tab 2'}, {label: 'Tab 3', disabled: true}, {label: 'Tab 4'},],
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const UsingTabSlotTemplate = (args, {argTypes}) => ({
|
|
44
|
+
components: {VcTabs: VcTabsCmp, VcIcon},
|
|
45
|
+
props: Object.keys(argTypes),
|
|
46
|
+
data: () => ({
|
|
47
|
+
currentIndex: null,
|
|
48
|
+
}),
|
|
49
|
+
template: `
|
|
50
|
+
<div>
|
|
51
|
+
<VcTabs :tabs="tabs"
|
|
52
|
+
v-model="currentIndex"
|
|
53
|
+
:distribution="distribution"
|
|
54
|
+
:tab-size="tabSize"
|
|
55
|
+
:separator-style="separatorStyle"
|
|
56
|
+
@change="onChange">
|
|
57
|
+
<template #tab-0>
|
|
58
|
+
<VcIcon color="black">$success</VcIcon>
|
|
59
|
+
</template>
|
|
60
|
+
<template #tab-1>
|
|
61
|
+
<VcIcon color="black">$plus</VcIcon>
|
|
62
|
+
</template>
|
|
63
|
+
<template #tab-2>
|
|
64
|
+
<VcIcon color="black">$magnify_glass</VcIcon>
|
|
65
|
+
</template>
|
|
66
|
+
<template #tab-3>
|
|
67
|
+
<VcIcon color="black">$corrupted_flag</VcIcon>
|
|
68
|
+
</template>
|
|
69
|
+
</VcTabs>
|
|
70
|
+
</div>`,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
export const UsingTabSlot = UsingTabSlotTemplate.bind({});
|
|
74
|
+
|
|
75
|
+
// Set default values
|
|
76
|
+
UsingTabSlot.args = {
|
|
77
|
+
...basicProps,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const Initialized = (args, {argTypes}) => ({
|
|
81
|
+
components: {VcTabs: VcTabsCmp, VcForm, VcTextField, VcImage, VcLoader},
|
|
82
|
+
props: Object.keys(argTypes),
|
|
83
|
+
data: () => ({
|
|
84
|
+
currentIndex: 1,
|
|
85
|
+
}),
|
|
86
|
+
template: `
|
|
87
|
+
<div>
|
|
88
|
+
<VcTabs :tabs="tabs" v-model="currentIndex"
|
|
89
|
+
:distribution="distribution"
|
|
90
|
+
:tab-size="tabSize"
|
|
91
|
+
:separator-style="separatorStyle"
|
|
92
|
+
@change="onChange">
|
|
93
|
+
<template #tab-content-0="data">
|
|
94
|
+
<div>{{ data.item.label }}</div>
|
|
95
|
+
<div>This tab is an example of how you can access the title of the tab, if you need to</div>
|
|
96
|
+
</template>
|
|
97
|
+
<template #tab-content-1>
|
|
98
|
+
<div>You can put anything you want in your tab</div>
|
|
99
|
+
<VcLoader/>
|
|
100
|
+
</template>
|
|
101
|
+
<template #tab-content-2>
|
|
102
|
+
<div>Really, even an image</div>
|
|
103
|
+
<VcImage image="static/media/src/stories/assets/upgrade.svg"/>
|
|
104
|
+
</template>
|
|
105
|
+
<template #tab-content-3>
|
|
106
|
+
<div>Or a form, it's totally flexible</div>
|
|
107
|
+
<template>
|
|
108
|
+
<div>
|
|
109
|
+
<VcForm>
|
|
110
|
+
<VcTextField
|
|
111
|
+
label="Name"
|
|
112
|
+
:counter="10"/>
|
|
113
|
+
</VcForm>
|
|
114
|
+
</div>
|
|
115
|
+
</template>
|
|
116
|
+
</template>
|
|
117
|
+
</VcTabs>
|
|
118
|
+
</div>`,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
export const SelectInitialTab = Initialized.bind({});
|
|
122
|
+
|
|
123
|
+
SelectInitialTab.args = {
|
|
124
|
+
...basicProps,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const BGColorTemplate = (args, {argTypes}) => ({
|
|
128
|
+
components: {VcTabs: VcTabsCmp},
|
|
129
|
+
props: Object.keys(argTypes),
|
|
130
|
+
data: () => ({
|
|
131
|
+
currentIndex: null,
|
|
132
|
+
}),
|
|
133
|
+
template: `
|
|
134
|
+
<div style="background-color: #aaee93">
|
|
135
|
+
The elements of the component are all background-color: transparent
|
|
136
|
+
That means that they will receive the color of the elements behind it.
|
|
137
|
+
<VcTabs :tabs="tabs"
|
|
138
|
+
:distribution="distribution"
|
|
139
|
+
:tab-size="tabSize"
|
|
140
|
+
:separator-style="separatorStyle"
|
|
141
|
+
v-model="currentIndex"
|
|
142
|
+
@change="onChange">
|
|
143
|
+
</VcTabs>
|
|
144
|
+
</div>`,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
export const BgColor = BGColorTemplate.bind({});
|
|
148
|
+
|
|
149
|
+
BgColor.args = {
|
|
150
|
+
...basicProps,
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export default {
|
|
154
|
+
title: 'containers / VcTabs', // This will control the story sidebar position
|
|
155
|
+
id: 'VcTabs', // This will be the permanent link to this component
|
|
156
|
+
component: VcTabsCmp,
|
|
157
|
+
argTypes: {
|
|
158
|
+
distribution: {
|
|
159
|
+
options: ['start', 'equal', 'grow'],
|
|
160
|
+
control: {type: 'radio'}
|
|
161
|
+
},
|
|
162
|
+
tabSize: {
|
|
163
|
+
options: ['M', 'L'],
|
|
164
|
+
control: {type: 'radio'}
|
|
165
|
+
},
|
|
166
|
+
separatorStyle: {
|
|
167
|
+
options: ['default','shadow', 'divider'],
|
|
168
|
+
control: {type: 'radio'}
|
|
169
|
+
},
|
|
170
|
+
onChange: {action: 'change', table: {disable: true}},
|
|
171
|
+
},
|
|
172
|
+
parameters: {
|
|
173
|
+
design: {
|
|
174
|
+
type: 'figma',
|
|
175
|
+
url: 'https://www.figma.com/file/xIOY6fBoA1wpy1tHv3i5js/vcita---ui-library?node-id=251%3A912',
|
|
176
|
+
},
|
|
177
|
+
status: {
|
|
178
|
+
type: 'beta', // 'beta' | 'stable' | 'deprecated' | 'releaseCandidate'
|
|
179
|
+
url: 'https://vuetifyjs.com/en/components/tabs',
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :data-qa="dataQa" class="VcTabs--wrapper">
|
|
3
|
+
<v-tabs :value="safeCurrentIndex"
|
|
4
|
+
background-color="transparent"
|
|
5
|
+
slider-color="secondary"
|
|
6
|
+
slider-size="4"
|
|
7
|
+
:height="tabSize === 'M' ? 48 : 60"
|
|
8
|
+
:grow="distribution === 'grow'"
|
|
9
|
+
:fixed-tabs="distribution==='equal'"
|
|
10
|
+
class="VcTabs--content"
|
|
11
|
+
:class="{'separatorShadow': separatorStyle === 'shadow', 'separatorDivider' : separatorStyle === 'divider'}"
|
|
12
|
+
@change="(newIndex) => $emit('change', newIndex)">
|
|
13
|
+
<v-tab v-for="(item, index) in tabs" :key="`tab-${index}`"
|
|
14
|
+
:class="{'VcTab': true, 'VcTabDisabled': item.disabled}"
|
|
15
|
+
active-class="VcTabActive"
|
|
16
|
+
:disabled="item.disabled"
|
|
17
|
+
:data-qa="`${dataQa}-tab-${index}`" >
|
|
18
|
+
<slot :name="`tab-${index}`" :item="item">
|
|
19
|
+
<span class="VcTab-label">{{ item.label }}</span>
|
|
20
|
+
</slot>
|
|
21
|
+
</v-tab>
|
|
22
|
+
</v-tabs>
|
|
23
|
+
|
|
24
|
+
<v-tabs-items :value="safeCurrentIndex" class="VcTabsContent">
|
|
25
|
+
<v-tab-item v-for="(item, index) in tabs" :key="`tab-content-${index}`" :data-qa="`${dataQa}-tab-content-${index}`">
|
|
26
|
+
<slot :name="`tab-content-${index}`" :item="item">
|
|
27
|
+
<div>{{item.label}}</div>
|
|
28
|
+
</slot>
|
|
29
|
+
</v-tab-item>
|
|
30
|
+
</v-tabs-items>
|
|
31
|
+
</div>
|
|
32
|
+
</template>
|
|
33
|
+
|
|
34
|
+
<script>
|
|
35
|
+
export default {
|
|
36
|
+
name: "VcTabs",
|
|
37
|
+
model: {
|
|
38
|
+
prop: 'currentIndex',
|
|
39
|
+
event: 'change',
|
|
40
|
+
},
|
|
41
|
+
props: {
|
|
42
|
+
tabs: {
|
|
43
|
+
type: Array,
|
|
44
|
+
required: true,
|
|
45
|
+
validator: value => value.every(tab => tab.label)
|
|
46
|
+
},
|
|
47
|
+
tabSize: {
|
|
48
|
+
type: String,
|
|
49
|
+
default: 'M',
|
|
50
|
+
validator: value => ['M', 'L'].includes(value)
|
|
51
|
+
},
|
|
52
|
+
currentIndex: {
|
|
53
|
+
type: Number,
|
|
54
|
+
default: 0,
|
|
55
|
+
validator: prop => prop >= 0,
|
|
56
|
+
},
|
|
57
|
+
distribution: {
|
|
58
|
+
type: String,
|
|
59
|
+
default: "start",
|
|
60
|
+
validator: prop => ['start','equal', 'grow'].includes(prop)
|
|
61
|
+
},
|
|
62
|
+
separatorStyle: {
|
|
63
|
+
type: String,
|
|
64
|
+
default: 'default',
|
|
65
|
+
validator: prop => ['default','shadow', 'divider'].includes(prop)
|
|
66
|
+
},
|
|
67
|
+
dataQa: {
|
|
68
|
+
type: String,
|
|
69
|
+
default: 'VcTabs'
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
computed: {
|
|
73
|
+
safeCurrentIndex() {
|
|
74
|
+
return Math.max(0, Math.min(this.currentIndex, this.tabs.length - 1));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
</script>
|
|
79
|
+
|
|
80
|
+
<style lang="scss" scoped>
|
|
81
|
+
|
|
82
|
+
.VcTabs--wrapper {
|
|
83
|
+
|
|
84
|
+
.separatorShadow {
|
|
85
|
+
border-bottom: 1px solid var(--gray-lighten-1);
|
|
86
|
+
box-shadow: var(--shadow-1);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.separatorDivider {
|
|
90
|
+
border-bottom: 1px solid var(--gray-lighten-1);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.VcTab:focus {
|
|
95
|
+
color: rgba(255,255,255,0) !important; // The tabs should take the color of what's behind them
|
|
96
|
+
box-shadow: inset 0 0 0 3px var(--v-secondary-lighten1);
|
|
97
|
+
border-radius: 2px;
|
|
98
|
+
|
|
99
|
+
.VcTab-label {
|
|
100
|
+
color: var(--gray-darken-4);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
&.VcTabDisabled {
|
|
104
|
+
background: rgba(0, 0, 0, 0.04);
|
|
105
|
+
color: #999999;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.VcTabActive {
|
|
110
|
+
color: var(--gray-darken-5);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.VcTab-label {
|
|
114
|
+
font-size: var(--font-size-x-small);
|
|
115
|
+
font-weight: var(--font-weight-medium2);
|
|
116
|
+
line-height: var(--size-value4);
|
|
117
|
+
letter-spacing: 0px;
|
|
118
|
+
text-transform: initial;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.VcTabsContent {
|
|
122
|
+
background-color: transparent;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
</style>
|
|
@@ -89,6 +89,14 @@ dialogPlayground.args = {
|
|
|
89
89
|
description: `Upsell block - dialog view. Pass mode=dialog to VcUpsellBlock component and wrap it with VcModalContainer. \nIf 'responsive' size is used and width/height changes are needed - you may change the css of VcModalContainer according to your development needs.`
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
dialogPlayground.parameters = {
|
|
93
|
+
docs: {
|
|
94
|
+
source: {
|
|
95
|
+
type: 'code'
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
92
100
|
export const dialogWithoutBulletsIcon = dialogTemplate.bind({});
|
|
93
101
|
|
|
94
102
|
dialogWithoutBulletsIcon.args = {
|
|
@@ -104,6 +112,14 @@ dialogWithoutBulletsIcon.args = {
|
|
|
104
112
|
description: `Upsell block - dialog view. Icon is optional.`
|
|
105
113
|
}
|
|
106
114
|
|
|
115
|
+
dialogWithoutBulletsIcon.parameters = {
|
|
116
|
+
docs: {
|
|
117
|
+
source: {
|
|
118
|
+
type: 'code'
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
107
123
|
export default {
|
|
108
124
|
title: ' Content Display / VcUpsellBlock', // This will control the story sidebar position
|
|
109
125
|
id: 'VcUpsellBlock', // This will be the permanent link to this component
|
|
@@ -120,5 +136,13 @@ export default {
|
|
|
120
136
|
type: 'stable', // 'beta' | 'stable' | 'deprecated' | 'releaseCandidate'
|
|
121
137
|
url: 'www.vcita.com', // will make the tag a link
|
|
122
138
|
},
|
|
139
|
+
docs: {
|
|
140
|
+
source: {
|
|
141
|
+
// code: 'Your code snippet goes here.',
|
|
142
|
+
// format: false,
|
|
143
|
+
language: "html",
|
|
144
|
+
// type: "auto",
|
|
145
|
+
},
|
|
146
|
+
},
|
|
123
147
|
},
|
|
124
148
|
};
|
package/src/components/index.js
CHANGED
|
@@ -62,3 +62,4 @@ export {default as VcDocItem} from './VcDocItem/VcDocItem.vue';
|
|
|
62
62
|
export {default as VcTimeSince} from './VcTimeSince/VcTimeSince.vue';
|
|
63
63
|
export {default as VcSearchPicker} from './VcSearchPicker/VcSearchPicker.vue';
|
|
64
64
|
export {default as VcDraggableList} from './VcDraggableList/VcDraggableList.vue';
|
|
65
|
+
export {default as VcTabs} from './VcTabs/VcTabs.vue';
|
|
@@ -10,7 +10,7 @@ const GeneralTemplate = (args, {argTypes}) => ({
|
|
|
10
10
|
template: `
|
|
11
11
|
<div>
|
|
12
12
|
<VcWizard
|
|
13
|
-
v-model="currentStep"
|
|
13
|
+
v-model.number="currentStep"
|
|
14
14
|
:steps="steps"
|
|
15
15
|
@submit="onSubmit"
|
|
16
16
|
:size="size"
|
|
@@ -95,7 +95,7 @@ Playground.args = {
|
|
|
95
95
|
},
|
|
96
96
|
],
|
|
97
97
|
dataQa: 'vc-wizard',
|
|
98
|
-
size: 'md'
|
|
98
|
+
size: 'md'
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
export default {
|
|
@@ -233,9 +233,3 @@ variables for `Dropzone`:
|
|
|
233
233
|
Variables for `VcSelectField`:
|
|
234
234
|
|
|
235
235
|
<div><code>--select-field-height: 52px;</code></div>
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
variables for `VcSearchPicker`:
|
|
239
|
-
|
|
240
|
-
<div><code>--search-picker-border-color: #1e93b7;</code></div>
|
|
241
|
-
<div><code>--search-picker-second-border-color: #95cddb;</code></div>
|
package/styles/variables.scss
CHANGED