@vcita/design-system 1.2.2 → 1.3.0
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/CHANGELOG.md +16 -1
- package/config/locales/ds.en.yml +8 -1
- package/config/locales/ds.he.yml +3 -0
- package/dist/@vcita/design-system.esm.js +1652 -958
- package/dist/@vcita/design-system.min.js +2 -2
- package/dist/@vcita/design-system.ssr.js +1468 -854
- package/init/DesignSystem.js +2 -0
- package/init/SvgIcons.js +12 -2
- package/package.json +1 -1
- package/src/components/VcAvatar/VcAvatar.stories.js +0 -1
- package/src/components/VcBreadcrumbs/VcBreadcrumbs.spec.js +82 -0
- package/src/components/VcBreadcrumbs/VcBreadcrumbs.stories.js +86 -0
- package/src/components/VcBreadcrumbs/VcBreadcrumbs.vue +59 -0
- package/src/components/VcButton/VcButton.stories.js +13 -2
- package/src/components/VcButton/VcButton.vue +16 -7
- package/src/components/VcGalleryItem/VcGalleryItem.spec.js +120 -0
- package/src/components/VcGalleryItem/VcGalleryItem.stories.js +94 -0
- package/src/components/VcGalleryItem/VcGalleryItem.vue +161 -0
- package/src/components/VcGalleryList/VcGalleryList.spec.js +86 -0
- package/src/components/VcGalleryList/VcGalleryList.stories.js +63 -0
- package/src/components/VcGalleryList/VcGalleryList.vue +102 -0
- package/src/components/VcGalleryList/mockData.js +50 -0
- package/src/components/VcLink/VcLink.vue +13 -1
- package/src/components/VcMiniBanner/VcMiniBanner.spec.js +74 -0
- package/src/components/VcMiniBanner/VcMiniBanner.stories.js +75 -0
- package/src/components/VcMiniBanner/VcMiniBanner.vue +129 -0
- package/src/components/VcSearchPicker/VcSearchPicker.vue +12 -5
- package/src/components/VcSideNav/VcSideNav.vue +2 -0
- package/src/components/VcTextField/VcTextField.stories.js +2 -1
- package/src/components/VcUpsellBlock/VcUpsellBlock.stories.js +7 -2
- package/src/components/VcUpsellBlock/VcUpsellBlock.vue +3 -0
- package/src/components/index.js +5 -0
- package/src/components/list/VcList/pattern/VcMobilePickerPattern.stories.js +3 -0
- package/src/components/modal/elements/VcModalContainer.stories.js +6 -0
- package/src/components/modal/elements/VcModalContainer.vue +7 -14
- package/src/components/page/elements/VcPageHeader.spec.js +123 -0
- package/src/components/page/elements/VcPageHeader.stories.js +80 -0
- package/src/components/page/elements/VcPageHeader.vue +96 -0
- package/src/components/page/layouts/SideNavPage/SideNavLayout.stories.js +223 -0
- package/src/components/page/layouts/centeredPage/CenteredPageLayout.stories.js +162 -0
- package/src/stories/assets/app-market/fc.svg +31 -0
- package/src/stories/assets/app-market/google.svg +1 -0
- package/src/stories/assets/app-market/qb.svg +9 -0
- package/src/stories/assets/app-market/stripe.svg +1 -0
- package/src/stories/assets/app-market/zapier.svg +1 -0
- package/src/stories/assets/pics/gallery-item-1.jpg +0 -0
- package/src/stories/assets/pics/gallery-item-2.jpg +0 -0
- package/src/stories/assets/pics/gallery-item-3.jpg +0 -0
- package/src/stories/assets/pics/gallery-item-4.jpg +0 -0
- package/src/stories/assets/pics/gallery-item-5.jpg +0 -0
- package/src/stories/variables.stories.mdx +9 -2
- package/styles/variables.scss +9 -0
- package/src/components/.DS_Store +0 -0
- package/src/components/VcMenu/.DS_Store +0 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="vc-mini-banner d-flex flex-column flex-sm-row justify-space-between justify-sm-start align-start align-sm-center"
|
|
3
|
+
:data-qa="dataQa" :style="{ background: gradientHue
|
|
4
|
+
? `linear-gradient(${ $vuetify.breakpoint.smAndUp ? 90 : 180 }deg, ${ gradientHue } 0%, #fff 42%, #fff 100%)`
|
|
5
|
+
: 'transparent' }"
|
|
6
|
+
@click="$emit('onAction')">
|
|
7
|
+
<div class="vc-mini-banner__thumbnail">
|
|
8
|
+
<div class="vc-mini-banner__image-wrap">
|
|
9
|
+
<div class="vc-mini-banner__image" :style="{ backgroundImage: `url(${ thumbImage })` }" />
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
<div class="vc-mini-banner__text-content">
|
|
13
|
+
<h3 class="vc-mini-banner__title" :data-qa="`${dataQa}-title`">{{ title }}</h3>
|
|
14
|
+
<h4 class="vc-mini-banner__subtitle" v-if="subtitle" :data-qa="`${dataQa}-subtitle`">{{ subtitle }}</h4>
|
|
15
|
+
</div>
|
|
16
|
+
<div class="vc-mini-banner__cta">
|
|
17
|
+
<VcButton pill small class="primary-cta" :data-qa="`${dataQa}-button`">
|
|
18
|
+
{{ ctaLabel }}
|
|
19
|
+
</VcButton>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<script>
|
|
25
|
+
import VcButton from "@/components/VcButton/VcButton.vue";
|
|
26
|
+
|
|
27
|
+
export default {
|
|
28
|
+
name: "VcBanner",
|
|
29
|
+
components: { VcButton },
|
|
30
|
+
props: {
|
|
31
|
+
dataQa: {
|
|
32
|
+
type: String,
|
|
33
|
+
default: 'VcMiniBanner'
|
|
34
|
+
},
|
|
35
|
+
thumbImage: {
|
|
36
|
+
type: String,
|
|
37
|
+
required: false
|
|
38
|
+
},
|
|
39
|
+
title: {
|
|
40
|
+
type: String,
|
|
41
|
+
required: true
|
|
42
|
+
},
|
|
43
|
+
subtitle: {
|
|
44
|
+
type: String,
|
|
45
|
+
required: false
|
|
46
|
+
},
|
|
47
|
+
ctaLabel: {
|
|
48
|
+
type: String,
|
|
49
|
+
required: true
|
|
50
|
+
},
|
|
51
|
+
gradientHue: {
|
|
52
|
+
type: String,
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<style lang="scss" scoped>
|
|
59
|
+
@import "../../scss/mixins.scss";
|
|
60
|
+
|
|
61
|
+
.vc-mini-banner {
|
|
62
|
+
min-height: 66px;
|
|
63
|
+
overflow: hidden;
|
|
64
|
+
border-radius: var(--size-value2);
|
|
65
|
+
border: 1px solid var(--neutral-lighten-2);
|
|
66
|
+
padding: var(--size-value4);
|
|
67
|
+
padding-inline-start: var(--size-value5);
|
|
68
|
+
padding-inline-end: var(--size-value8);
|
|
69
|
+
grid-gap: var(--size-value5);
|
|
70
|
+
cursor: pointer;
|
|
71
|
+
background-color: var(--modal-bg-color);
|
|
72
|
+
|
|
73
|
+
&__thumbnail {
|
|
74
|
+
background: var(--modal-bg-color);
|
|
75
|
+
height: var(--size-value12);
|
|
76
|
+
width: var(--size-value12);
|
|
77
|
+
box-shadow: var(--shadow-5);
|
|
78
|
+
border-radius: var(--border-radius);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
&__image-wrap {
|
|
82
|
+
height: inherit;
|
|
83
|
+
width: inherit;
|
|
84
|
+
padding: var(--size-value2);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
&__image {
|
|
88
|
+
height: 100%;
|
|
89
|
+
background-repeat: no-repeat;
|
|
90
|
+
background-size: contain;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
&__text-content {
|
|
94
|
+
color: var(--gray-darken-5);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
&__title {
|
|
98
|
+
font-weight: var(--font-weight-large2);
|
|
99
|
+
font-size: var(--font-size-small3);
|
|
100
|
+
|
|
101
|
+
@include sm-and-up {
|
|
102
|
+
font-weight: var(--font-weight-large);
|
|
103
|
+
font-size: var(--font-size-small2);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
&__subtitle {
|
|
108
|
+
margin-top: var(--size-value1);
|
|
109
|
+
font-weight: var(--font-weight-medium);
|
|
110
|
+
font-size: var(--font-size-small2);
|
|
111
|
+
|
|
112
|
+
@include sm-and-up {
|
|
113
|
+
font-weight: var(--font-weight-medium);
|
|
114
|
+
font-size: var(--font-size-xx-small);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
&__title, &__subtitle {
|
|
119
|
+
user-select: none;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
&__cta {
|
|
123
|
+
@include sm-and-up {
|
|
124
|
+
margin-inline-start: auto;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
}
|
|
129
|
+
</style>
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
@update:search-input="(text) => text && text.length && $emit('onSearchInput', text)"
|
|
17
17
|
@change="(newVal) => $emit('onSelectionChange', newVal)"
|
|
18
18
|
@click.native="toggleMenu"
|
|
19
|
-
@click:append="toggleMenu"
|
|
20
19
|
@blur="focused = false;$emit('onMenuToggled', { isOpen: false })"
|
|
21
20
|
multiple
|
|
22
21
|
>
|
|
@@ -271,12 +270,20 @@ export default {
|
|
|
271
270
|
}
|
|
272
271
|
}
|
|
273
272
|
|
|
274
|
-
::v-deep
|
|
275
|
-
|
|
273
|
+
::v-deep {
|
|
274
|
+
.v-list-item--link {
|
|
275
|
+
font-size: var(--font-size-x-small);
|
|
276
276
|
|
|
277
|
-
|
|
278
|
-
|
|
277
|
+
&:before {
|
|
278
|
+
content: initial;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.v-input__append-inner {
|
|
283
|
+
pointer-events: none;
|
|
279
284
|
}
|
|
280
285
|
}
|
|
281
286
|
|
|
287
|
+
|
|
288
|
+
|
|
282
289
|
</style>
|
|
@@ -63,7 +63,8 @@ const TextFieldTemplate = (args, {argTypes}) => ({
|
|
|
63
63
|
:google-address-auto-complete="googleAddressAutoComplete"
|
|
64
64
|
:google-address-country-options="googleAddressCountryOptions"
|
|
65
65
|
@click="onClick"
|
|
66
|
-
@input="onInput"
|
|
66
|
+
@input="onInput"
|
|
67
|
+
@onPlaceSelected="onPlaceSelected"/>
|
|
67
68
|
</v-layout>`,
|
|
68
69
|
})
|
|
69
70
|
|
|
@@ -62,11 +62,13 @@ const dialogTemplate = (args, {argTypes}) => ({
|
|
|
62
62
|
:showCloseButton="true"
|
|
63
63
|
:size="modalSize"
|
|
64
64
|
:showFooterDivider="false"
|
|
65
|
+
:useOffset="false"
|
|
66
|
+
flavor="input"
|
|
65
67
|
@click-outside="$emit('onClickOutside')"
|
|
66
68
|
@onCloseButtonClicked="$emit('onCloseButtonClicked')">
|
|
67
69
|
<template #content>
|
|
68
70
|
<VcUpsellBlock
|
|
69
|
-
mode="
|
|
71
|
+
:mode="mode"
|
|
70
72
|
:imageUrl="imageUrl"
|
|
71
73
|
:titleText="titleText"
|
|
72
74
|
:subtitleText="subtitleText"
|
|
@@ -126,7 +128,10 @@ export default {
|
|
|
126
128
|
component: VcUpsellBlockCmp,
|
|
127
129
|
argTypes: {
|
|
128
130
|
description: {table: {disable: true}},
|
|
129
|
-
modalSize: {
|
|
131
|
+
modalSize: {
|
|
132
|
+
options: ['sm', 'md', 'lg', 'xl', 'responsive'],
|
|
133
|
+
control: {type: 'radio'}
|
|
134
|
+
},
|
|
130
135
|
showDialog: {table: {disable: true}},
|
|
131
136
|
linkText: {table: {category: 'link'}},
|
|
132
137
|
linkUrl: {table: {category: 'link'}},
|
package/src/components/index.js
CHANGED
|
@@ -65,3 +65,8 @@ export {default as VcSearchPicker} from './VcSearchPicker/VcSearchPicker.vue';
|
|
|
65
65
|
export {default as VcDraggableList} from './VcDraggableList/VcDraggableList.vue';
|
|
66
66
|
export {default as VcTabs} from './VcTabs/VcTabs.vue';
|
|
67
67
|
export {default as VcSideNav} from './VcSideNav/VcSideNav.vue';
|
|
68
|
+
export {default as VcMiniBanner} from './VcMiniBanner/VcMiniBanner.vue';
|
|
69
|
+
export {default as VcGalleryItem} from './VcGalleryItem/VcGalleryItem.vue';
|
|
70
|
+
export {default as VcGalleryList} from './VcGalleryList/VcGalleryList.vue';
|
|
71
|
+
export {default as VcBreadcrumbs} from './VcBreadcrumbs/VcBreadcrumbs.vue';
|
|
72
|
+
export {default as VcPageHeader} from './page/elements/VcPageHeader.vue';
|
|
@@ -272,6 +272,8 @@ MobileSingleSelectPickerWithAvatars.parameters = {
|
|
|
272
272
|
</VcInputModal>
|
|
273
273
|
</template>
|
|
274
274
|
|
|
275
|
+
<script>
|
|
276
|
+
|
|
275
277
|
/**
|
|
276
278
|
TODO: - to get this code running you need to
|
|
277
279
|
1. Implement selected item - display the current selected item
|
|
@@ -305,6 +307,7 @@ MobileSingleSelectPickerWithAvatars.parameters = {
|
|
|
305
307
|
},
|
|
306
308
|
},
|
|
307
309
|
}
|
|
310
|
+
</script>
|
|
308
311
|
|
|
309
312
|
<style lang="scss" scoped>
|
|
310
313
|
// Your css here
|
|
@@ -11,6 +11,7 @@ const Template = (args, {argTypes}) => ({
|
|
|
11
11
|
:showCloseButton="showCloseButton"
|
|
12
12
|
:showFooterDivider="showFooterDivider"
|
|
13
13
|
:showHeaderDivider="showHeaderDivider"
|
|
14
|
+
:flavor="flavor"
|
|
14
15
|
:use-offset="useOffset"
|
|
15
16
|
:closeOnEsc="closeOnEsc"
|
|
16
17
|
:data-qa="dataQa"
|
|
@@ -48,6 +49,7 @@ Playground.args = {
|
|
|
48
49
|
closeOnEsc: true,
|
|
49
50
|
showCloseButton: false,
|
|
50
51
|
useOffset: false,
|
|
52
|
+
flavor: 'input',
|
|
51
53
|
dataQa: 'VcModalContainer',
|
|
52
54
|
}
|
|
53
55
|
|
|
@@ -60,6 +62,10 @@ export default {
|
|
|
60
62
|
options: ['sm', 'md', 'lg', 'xl', 'responsive'],
|
|
61
63
|
control: {type: 'radio'}
|
|
62
64
|
},
|
|
65
|
+
flavor: {
|
|
66
|
+
options: ['input', 'confirm', 'notice', 'prominent'],
|
|
67
|
+
control: {type: 'radio'}
|
|
68
|
+
},
|
|
63
69
|
},
|
|
64
70
|
parameters: {
|
|
65
71
|
design: {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<v-layout column :data-qa="dataQa">
|
|
11
11
|
<header :class="{'showDivider': showHeaderDivider}">
|
|
12
12
|
<slot name="header"/>
|
|
13
|
-
<VcButton class="VcModalCloseButton" v-if="
|
|
13
|
+
<VcButton class="VcModalCloseButton" v-if="showCloseButton" icon fab small
|
|
14
14
|
@click="$emit('onCloseButtonClicked')">
|
|
15
15
|
<template #prepend>
|
|
16
16
|
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
@@ -81,13 +81,6 @@ export default {
|
|
|
81
81
|
default: 'VcModalContainer',
|
|
82
82
|
}
|
|
83
83
|
},
|
|
84
|
-
computed: {
|
|
85
|
-
displayCloseButton() {
|
|
86
|
-
if (this.flavor === 'input' && !this.$vuetify.breakpoint.mdAndUp)
|
|
87
|
-
return false;
|
|
88
|
-
return this.showCloseButton;
|
|
89
|
-
},
|
|
90
|
-
}
|
|
91
84
|
}
|
|
92
85
|
</script>
|
|
93
86
|
|
|
@@ -161,7 +154,7 @@ export default {
|
|
|
161
154
|
|
|
162
155
|
footer {
|
|
163
156
|
padding: var(--size-value3) var(--size-value4) var(--size-value3);
|
|
164
|
-
|
|
157
|
+
text-align: end;
|
|
165
158
|
|
|
166
159
|
&.showDivider {
|
|
167
160
|
border-top: 1px solid rgba(0, 0, 0, 0.12);
|
|
@@ -177,7 +170,7 @@ export default {
|
|
|
177
170
|
header {
|
|
178
171
|
font-weight: var(--font-weight-xl);
|
|
179
172
|
font-size: var(--font-size-medium2);
|
|
180
|
-
padding-bottom:
|
|
173
|
+
padding-bottom: 0;
|
|
181
174
|
padding-top: var(--size-value10);
|
|
182
175
|
}
|
|
183
176
|
|
|
@@ -217,7 +210,7 @@ export default {
|
|
|
217
210
|
}
|
|
218
211
|
|
|
219
212
|
.VcModalContainerContent {
|
|
220
|
-
min-height:
|
|
213
|
+
min-height: 0;
|
|
221
214
|
margin-left: var(--size-value16);
|
|
222
215
|
padding-right: var(--size-value16);
|
|
223
216
|
}
|
|
@@ -235,12 +228,12 @@ export default {
|
|
|
235
228
|
&.responsive {
|
|
236
229
|
height: 100%;
|
|
237
230
|
margin: 0;
|
|
238
|
-
border-bottom-left-radius:
|
|
239
|
-
border-bottom-right-radius:
|
|
231
|
+
border-bottom-left-radius: 0;
|
|
232
|
+
border-bottom-right-radius: 0;
|
|
240
233
|
}
|
|
241
234
|
|
|
242
235
|
.VcModalContainerContent {
|
|
243
|
-
padding:
|
|
236
|
+
padding: 0;
|
|
244
237
|
}
|
|
245
238
|
}
|
|
246
239
|
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import '@testing-library/jest-dom'
|
|
2
|
+
import VcPageHeader from "./VcPageHeader.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
|
+
import {fireEvent} from "@testing-library/dom";
|
|
8
|
+
|
|
9
|
+
init();
|
|
10
|
+
|
|
11
|
+
Vue.use(Vuetify)
|
|
12
|
+
|
|
13
|
+
describe("VcPageHeader.vue", () => {
|
|
14
|
+
|
|
15
|
+
const renderWithVuetify = (component, options, callback, isMobile = false) => {
|
|
16
|
+
const root = document.createElement('div')
|
|
17
|
+
root.setAttribute('data-app', 'true')
|
|
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 with breadcrumbs and subtitle", () => {
|
|
47
|
+
// Queries: https://testing-library.com/docs/queries/about#types-of-queries
|
|
48
|
+
const {container, getByTestId, getByText, emitted} = renderWithVuetify(VcPageHeader, {
|
|
49
|
+
props: {
|
|
50
|
+
title: 'Payments',
|
|
51
|
+
subtitle: 'Payments subtitle',
|
|
52
|
+
breadcrumbs: [
|
|
53
|
+
{
|
|
54
|
+
text: 'item 1',
|
|
55
|
+
disabled: false,
|
|
56
|
+
href: 'item_1',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
text: 'item 2',
|
|
60
|
+
disabled: false,
|
|
61
|
+
href: 'item_2',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
text: 'item 3',
|
|
65
|
+
disabled: false,
|
|
66
|
+
href: 'item_3',
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
// Expect options: https://github.com/testing-library/jest-dom
|
|
73
|
+
expect(container).toHaveAttribute('data-app', 'true');
|
|
74
|
+
|
|
75
|
+
// Make sure the component has the data-qa attribute
|
|
76
|
+
const component = getByTestId('VcPageHeader');
|
|
77
|
+
expect(component).toBeInTheDocument();
|
|
78
|
+
|
|
79
|
+
const breadcrumbs = getByTestId('VcBreadcrumbs');
|
|
80
|
+
expect(breadcrumbs).toBeInTheDocument();
|
|
81
|
+
|
|
82
|
+
expect(getByText('Payments')).toBeInTheDocument();
|
|
83
|
+
expect(getByText('Payments subtitle')).toBeInTheDocument();
|
|
84
|
+
|
|
85
|
+
const backButton = getByTestId('VcPageHeader-backButton');
|
|
86
|
+
expect(backButton).toBeInTheDocument();
|
|
87
|
+
fireEvent.click(backButton);
|
|
88
|
+
expect(emitted().onBackClicked.length).toBe(1);
|
|
89
|
+
|
|
90
|
+
const saveButton = getByTestId('VcPageHeader-saveButton');
|
|
91
|
+
expect(saveButton).toBeInTheDocument();
|
|
92
|
+
fireEvent.click(saveButton);
|
|
93
|
+
expect(emitted().onSaveClicked.length).toBe(1);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("has no breadcrumbs and disabled save button", () => {
|
|
97
|
+
const {queryByTestId, getByTestId} = renderWithVuetify(VcPageHeader, {
|
|
98
|
+
props: {
|
|
99
|
+
title: 'Payments',
|
|
100
|
+
buttonData: {save: {disabled: true}},
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const breadcrumbs = queryByTestId('VcBreadcrumbs');
|
|
105
|
+
expect(breadcrumbs).toBe(null);
|
|
106
|
+
|
|
107
|
+
const saveButton = getByTestId('VcPageHeader-saveButton');
|
|
108
|
+
expect(saveButton).toBeDisabled();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("has no back button", () => {
|
|
112
|
+
const {queryByTestId} = renderWithVuetify(VcPageHeader, {
|
|
113
|
+
props: {
|
|
114
|
+
title: 'Payments',
|
|
115
|
+
showBackButton: false,
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const backButton = queryByTestId('VcPageHeader-backButton');
|
|
120
|
+
expect(backButton).not.toBeInTheDocument();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import VcPageHeaderCmp from './VcPageHeader';
|
|
2
|
+
import VcBaseDocs from '@/stories/VcBaseDocs.mdx';
|
|
3
|
+
|
|
4
|
+
const baseProps = {
|
|
5
|
+
title: 'Payments',
|
|
6
|
+
subtitle: 'This page contains information on all your payments, past, present and future',
|
|
7
|
+
breadcrumbs: [
|
|
8
|
+
{
|
|
9
|
+
text: 'item 1',
|
|
10
|
+
disabled: false,
|
|
11
|
+
href: 'item_1',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
text: 'item 2',
|
|
15
|
+
disabled: false,
|
|
16
|
+
href: 'item_2',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
text: 'item 3',
|
|
20
|
+
disabled: false,
|
|
21
|
+
href: 'item_3',
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
showBackButton: true,
|
|
25
|
+
buttonData: {},
|
|
26
|
+
dataQa: 'VcPageHeader',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const Template = (args, {argTypes}) => ({
|
|
30
|
+
components: {VcPageHeader: VcPageHeaderCmp},
|
|
31
|
+
props: Object.keys(argTypes),
|
|
32
|
+
template: `
|
|
33
|
+
<div>
|
|
34
|
+
<VcPageHeader :title="title"
|
|
35
|
+
:subtitle="subtitle"
|
|
36
|
+
:breadcrumbs="breadcrumbs"
|
|
37
|
+
:show-back-button="showBackButton"
|
|
38
|
+
:button-data="buttonData"
|
|
39
|
+
@onBackClicked="onBackClicked"
|
|
40
|
+
@onSaveClicked="onSaveClicked"/>
|
|
41
|
+
</div>`,
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
export const Playground = Template.bind({});
|
|
45
|
+
|
|
46
|
+
Playground.args = {
|
|
47
|
+
...baseProps,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const NoBreadcrumbs = Template.bind({});
|
|
51
|
+
|
|
52
|
+
NoBreadcrumbs.args = {
|
|
53
|
+
...baseProps,
|
|
54
|
+
breadcrumbs: undefined,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const DisabledSaveButton = Template.bind({});
|
|
58
|
+
|
|
59
|
+
DisabledSaveButton.args = {
|
|
60
|
+
...baseProps,
|
|
61
|
+
buttonData: {save: {disabled: true}},
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export default {
|
|
65
|
+
title: 'page / elements / VcPageHeader', // This will control the story sidebar position
|
|
66
|
+
id: 'VcPageHeader', // This will be the permanent link to this component
|
|
67
|
+
component: VcPageHeaderCmp,
|
|
68
|
+
parameters: {
|
|
69
|
+
design: {
|
|
70
|
+
type: 'figma',
|
|
71
|
+
url: 'https://www.figma.com/file/xIOY6fBoA1wpy1tHv3i5js/vcita---ui-library?node-id=12049%3A261603',
|
|
72
|
+
},
|
|
73
|
+
status: {
|
|
74
|
+
type: 'beta', // 'beta' | 'stable' | 'deprecated' | 'releaseCandidate'
|
|
75
|
+
},
|
|
76
|
+
docs: {
|
|
77
|
+
page: VcBaseDocs,
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<VcLayout align-center class="VcPageHeader">
|
|
3
|
+
<VcLayout column :data-qa="dataQa">
|
|
4
|
+
<VcBreadcrumbs v-if="breadcrumbs && breadcrumbs.length > 0" :items="breadcrumbs"/>
|
|
5
|
+
<span class="VcHeader--title">
|
|
6
|
+
<VcButton v-if="showBackButton" icon small
|
|
7
|
+
:data-qa="`${dataQa}-backButton`"
|
|
8
|
+
@click="$emit('onBackClicked')">
|
|
9
|
+
<template #prepend>
|
|
10
|
+
<VcIcon color="black" size="var(--font-size-small)">$chevron_left</VcIcon>
|
|
11
|
+
</template>
|
|
12
|
+
</VcButton>
|
|
13
|
+
{{ title }}
|
|
14
|
+
</span>
|
|
15
|
+
<span v-if="subtitle && subtitle.length > 0" class="VcHeader--subtitle">
|
|
16
|
+
{{ subtitle }}
|
|
17
|
+
</span>
|
|
18
|
+
</VcLayout>
|
|
19
|
+
<VcLayout justify-end>
|
|
20
|
+
<slot name="buttons">
|
|
21
|
+
<VcButton :icon-size="12"
|
|
22
|
+
:disabled="buttonData.save && buttonData.save.disabled"
|
|
23
|
+
prepend-default-icon prepend-icon="check_button"
|
|
24
|
+
:data-qa="`${dataQa}-saveButton`"
|
|
25
|
+
@click="$emit('onSaveClicked')">
|
|
26
|
+
{{ saveButtonLabel }}
|
|
27
|
+
</VcButton>
|
|
28
|
+
</slot>
|
|
29
|
+
</VcLayout>
|
|
30
|
+
</VcLayout>
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<script>
|
|
34
|
+
import VcBreadcrumbs from "@/components/VcBreadcrumbs/VcBreadcrumbs.vue";
|
|
35
|
+
import VcLayout from "@/components/VcLayout/VcLayout.vue";
|
|
36
|
+
import VcIcon from "@/components/VcIcon/VcIcon.vue";
|
|
37
|
+
import VcButton from "@/components/VcButton/VcButton.vue";
|
|
38
|
+
|
|
39
|
+
export default {
|
|
40
|
+
name: "VcPageHeader",
|
|
41
|
+
components: {VcButton, VcIcon, VcLayout, VcBreadcrumbs},
|
|
42
|
+
props: {
|
|
43
|
+
breadcrumbs: {
|
|
44
|
+
type: Array,
|
|
45
|
+
validator: items => items.every(item => item.text && item.href)
|
|
46
|
+
},
|
|
47
|
+
title: {
|
|
48
|
+
type: String,
|
|
49
|
+
required: true
|
|
50
|
+
},
|
|
51
|
+
subtitle: {
|
|
52
|
+
type: String,
|
|
53
|
+
default: ''
|
|
54
|
+
},
|
|
55
|
+
showBackButton: {
|
|
56
|
+
type: Boolean,
|
|
57
|
+
default: true,
|
|
58
|
+
},
|
|
59
|
+
buttonData: {
|
|
60
|
+
type: Object,
|
|
61
|
+
default: () => ({}),
|
|
62
|
+
},
|
|
63
|
+
dataQa: {
|
|
64
|
+
type: String,
|
|
65
|
+
default: 'VcPageHeader'
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
computed: {
|
|
69
|
+
saveButtonLabel() {
|
|
70
|
+
return this.buttonData.save?.label || this.$dst('ds.page.saveButton.label')
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
<style lang="scss" scoped>
|
|
77
|
+
|
|
78
|
+
.VcPageHeader {
|
|
79
|
+
margin-bottom: var(--size-value10);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.VcHeader--title {
|
|
83
|
+
font-size: var(--font-size-medium0);
|
|
84
|
+
font-weight: var(--font-weight-large2);
|
|
85
|
+
line-height: var(--size-value8);
|
|
86
|
+
color: var(--gray-darken-5);
|
|
87
|
+
margin-top: var(--size-value1);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.VcHeader--subtitle {
|
|
91
|
+
font-size: var(--font-size-x-small);
|
|
92
|
+
font-weight: var(--font-weight-medium);
|
|
93
|
+
line-height: var(--size-value5);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
</style>
|