tide-design-system 2.4.3 → 2.4.5
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/css/storybook.css +1 -0
- package/dist/css/variables.css +2 -2
- package/dist/style.css +1 -1
- package/dist/tide-design-system.cjs +2 -2
- package/dist/tide-design-system.esm.d.ts +30 -7
- package/dist/tide-design-system.esm.js +1855 -1744
- package/index.ts +2 -0
- package/package.json +1 -1
- package/src/assets/css/storybook.css +1 -0
- package/src/assets/css/variables.css +2 -2
- package/src/components/TideAlert.vue +46 -3
- package/src/components/TideCarousel.vue +131 -28
- package/src/stories/TideAlert.stories.ts +37 -1
- package/src/stories/TideCarousel.stories.ts +21 -23
- package/src/types/Icon.ts +3 -0
package/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ import TideChipFilter from '@/components/TideChipFilter.vue';
|
|
|
15
15
|
import TideChipInput from '@/components/TideChipInput.vue';
|
|
16
16
|
import TideColumns from '@/components/TideColumns.vue';
|
|
17
17
|
import TideDivider from '@/components/TideDivider.vue';
|
|
18
|
+
import TideForm from '@/components/TideForm.vue';
|
|
18
19
|
import TideIcon from '@/components/TideIcon.vue';
|
|
19
20
|
import TideImage from '@/components/TideImage.vue';
|
|
20
21
|
import TideImageBackground from '@/components/TideImageBackground.vue';
|
|
@@ -159,6 +160,7 @@ export {
|
|
|
159
160
|
TideChipInput,
|
|
160
161
|
TideColumns,
|
|
161
162
|
TideDivider,
|
|
163
|
+
TideForm,
|
|
162
164
|
TideIcon,
|
|
163
165
|
TideImage,
|
|
164
166
|
TideImageBackground,
|
package/package.json
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap');
|
|
3
3
|
|
|
4
4
|
.sb-border-black {border: 1px solid #000000;}
|
|
5
|
+
.sb-border-blue {border: 1px solid #0000FF;}
|
|
5
6
|
.sb-border-blue-light {border: 1px solid #CCDEF3;}
|
|
6
7
|
.sb-border-white {border: 1px solid #FFFFFF;}
|
|
7
8
|
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
|
|
58
58
|
/* Global tonal palette */
|
|
59
59
|
--tide-gray-100: #FFFFFF;
|
|
60
|
-
--tide-gray-200: #
|
|
61
|
-
--tide-gray-300: #
|
|
60
|
+
--tide-gray-200: #F2F2F2;
|
|
61
|
+
--tide-gray-300: #E4E4E5;
|
|
62
62
|
--tide-gray-400: #C9CACB;
|
|
63
63
|
--tide-gray-500: #AEAFB2;
|
|
64
64
|
--tide-gray-600: #939598;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import { computed } from 'vue';
|
|
2
|
+
import { Comment, computed, useSlots } from 'vue';
|
|
3
3
|
|
|
4
4
|
import TideButtonIcon from '@/components/TideButtonIcon.vue';
|
|
5
5
|
import TideIcon from '@/components/TideIcon.vue';
|
|
6
|
+
import TideLink from '@/components/TideLink.vue';
|
|
6
7
|
import { ALERT } from '@/types/Alert';
|
|
8
|
+
import { ELEMENT } from '@/types/Element';
|
|
7
9
|
import { ICON } from '@/types/Icon';
|
|
8
10
|
import { PRIORITY } from '@/types/Priority';
|
|
9
11
|
import { SIZE } from '@/types/Size';
|
|
@@ -13,6 +15,7 @@
|
|
|
13
15
|
|
|
14
16
|
type Props = {
|
|
15
17
|
heading?: string;
|
|
18
|
+
ctaLabel?: string;
|
|
16
19
|
isDismissible?: boolean;
|
|
17
20
|
isToast?: boolean;
|
|
18
21
|
type?: Alert;
|
|
@@ -20,9 +23,11 @@
|
|
|
20
23
|
|
|
21
24
|
type Emits = {
|
|
22
25
|
(event: 'close'): void;
|
|
26
|
+
(event: 'ctaClick'): void;
|
|
23
27
|
};
|
|
24
28
|
|
|
25
29
|
const props = withDefaults(defineProps<Props>(), {
|
|
30
|
+
ctaLabel: undefined,
|
|
26
31
|
heading: undefined,
|
|
27
32
|
isDismissible: true,
|
|
28
33
|
isToast: false,
|
|
@@ -30,6 +35,15 @@
|
|
|
30
35
|
});
|
|
31
36
|
|
|
32
37
|
const emit = defineEmits<Emits>();
|
|
38
|
+
const slots = useSlots();
|
|
39
|
+
const hasBody = computed(() => {
|
|
40
|
+
const nodes = slots.default?.();
|
|
41
|
+
if (!nodes) return false;
|
|
42
|
+
|
|
43
|
+
return nodes.some(
|
|
44
|
+
(node) => node.type !== Comment && (typeof node.children !== 'string' || node.children.trim().length > 0)
|
|
45
|
+
);
|
|
46
|
+
});
|
|
33
47
|
|
|
34
48
|
const iconType = computed(() => {
|
|
35
49
|
if (props.type === ALERT.ERROR) return ICON.PRIORITY_HIGH;
|
|
@@ -78,8 +92,24 @@
|
|
|
78
92
|
/>
|
|
79
93
|
</div>
|
|
80
94
|
|
|
81
|
-
<div
|
|
82
|
-
|
|
95
|
+
<div
|
|
96
|
+
:class="[
|
|
97
|
+
'tide-alert-heading',
|
|
98
|
+
CSS.DISPLAY.FLEX,
|
|
99
|
+
CSS.AXIS2.CENTER,
|
|
100
|
+
CSS.FLEX.DIRECTION.ROW,
|
|
101
|
+
!hasBody ? [CSS.AXIS1.BETWEEN, CSS.MARGIN.RIGHT.HALF] : '',
|
|
102
|
+
]"
|
|
103
|
+
>
|
|
104
|
+
<span :class="CSS.FONT.ROLE.LABEL_2_SEMIBOLD">{{ props.heading }}</span>
|
|
105
|
+
|
|
106
|
+
<TideLink
|
|
107
|
+
:class="[CSS.FONT.ROLE.LINK_2]"
|
|
108
|
+
:element="ELEMENT.BUTTON"
|
|
109
|
+
:label="props.ctaLabel"
|
|
110
|
+
@click="emit('ctaClick')"
|
|
111
|
+
v-if="props.ctaLabel && !hasBody"
|
|
112
|
+
/>
|
|
83
113
|
</div>
|
|
84
114
|
|
|
85
115
|
<TideButtonIcon
|
|
@@ -93,6 +123,19 @@
|
|
|
93
123
|
|
|
94
124
|
<div :class="['tide-alert-body', CSS.FONT.ROLE.BODY_2, !props.isToast && CSS.FONT.COLOR.SURFACE.DEFAULT]">
|
|
95
125
|
<slot />
|
|
126
|
+
|
|
127
|
+
<div
|
|
128
|
+
:class="[CSS.MARGIN.TOP.HALF]"
|
|
129
|
+
v-if="props.ctaLabel && hasBody"
|
|
130
|
+
>
|
|
131
|
+
<TideLink
|
|
132
|
+
:class="[CSS.FONT.ROLE.LINK_2]"
|
|
133
|
+
:element="ELEMENT.BUTTON"
|
|
134
|
+
:label="props.ctaLabel"
|
|
135
|
+
@click="emit('ctaClick')"
|
|
136
|
+
v-if="props.ctaLabel"
|
|
137
|
+
/>
|
|
138
|
+
</div>
|
|
96
139
|
</div>
|
|
97
140
|
</div>
|
|
98
141
|
</template>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import { onMounted, onUnmounted, ref } from 'vue';
|
|
2
|
+
import { computed, onMounted, onUnmounted, ref } from 'vue';
|
|
3
3
|
|
|
4
4
|
import TideButtonIcon from '@/components/TideButtonIcon.vue';
|
|
5
5
|
import { ICON } from '@/types/Icon';
|
|
@@ -7,23 +7,25 @@
|
|
|
7
7
|
import { CSS } from '@/types/Styles';
|
|
8
8
|
|
|
9
9
|
type Props = {
|
|
10
|
-
|
|
10
|
+
hasDots?: boolean;
|
|
11
11
|
isFloating?: boolean;
|
|
12
12
|
isHeadline1?: boolean;
|
|
13
13
|
isHideawayButtons?: boolean;
|
|
14
14
|
isScrollByPage?: boolean;
|
|
15
15
|
isTouchscreen?: boolean;
|
|
16
|
+
maxDots?: number;
|
|
16
17
|
subtitle?: string;
|
|
17
18
|
title?: string;
|
|
18
19
|
};
|
|
19
20
|
|
|
20
21
|
const props = withDefaults(defineProps<Props>(), {
|
|
21
|
-
|
|
22
|
+
hasDots: undefined,
|
|
22
23
|
isFloating: false,
|
|
23
24
|
isHeadline1: false,
|
|
24
25
|
isHideawayButtons: true,
|
|
25
26
|
isScrollByPage: true,
|
|
26
27
|
isTouchscreen: undefined,
|
|
28
|
+
maxDots: 5,
|
|
27
29
|
subtitle: undefined,
|
|
28
30
|
title: undefined,
|
|
29
31
|
});
|
|
@@ -35,18 +37,52 @@
|
|
|
35
37
|
const emit = defineEmits<Emits>();
|
|
36
38
|
|
|
37
39
|
const containerRef = ref<HTMLDivElement | null>(null);
|
|
40
|
+
const contentWidth = ref<number>(0);
|
|
41
|
+
const currentPageIndex = ref<number>(0);
|
|
42
|
+
const dotsRef = ref<HTMLDivElement | null>(null);
|
|
43
|
+
const frameWidth = ref<number>(0);
|
|
38
44
|
const isFirstSlide = ref<boolean>(true);
|
|
39
45
|
const isLastSlide = ref<boolean>(false);
|
|
40
46
|
const showButtons = ref<boolean>(true);
|
|
41
47
|
const slideObserver = ref<IntersectionObserver | null>(null);
|
|
48
|
+
const slides = ref<HTMLElement[]>([]);
|
|
42
49
|
const slidesInView = ref<number[]>([]);
|
|
43
50
|
const slotObserver = ref<MutationObserver | null>(null);
|
|
44
51
|
|
|
45
|
-
const
|
|
52
|
+
const currentPage = computed(() => currentPageIndex.value + 1);
|
|
53
|
+
const dotContainerWidth = computed(() => dotCountVisible.value * dotWidth + (dotCountVisible.value - 1) * dotGap);
|
|
54
|
+
const dotCountVisible = computed(() => (props.maxDots > totalPages.value ? totalPages.value : props.maxDots));
|
|
55
|
+
const lastPageIndex = computed(() => totalPages.value - 1);
|
|
56
|
+
const totalPages = computed(() => {
|
|
57
|
+
if (!slides.value.length) return 0;
|
|
58
|
+
if (!props.isScrollByPage) return slides.value.length;
|
|
59
|
+
|
|
60
|
+
const gapWidth = cardGap * (slides.value.length - 1);
|
|
61
|
+
const contentNoGap = contentWidth.value - gapWidth;
|
|
62
|
+
const quotient = Math.round(contentNoGap / frameWidth.value);
|
|
63
|
+
const remainder = contentNoGap % frameWidth.value;
|
|
64
|
+
|
|
65
|
+
return remainder ? quotient + 1 : quotient;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const cardGap: number = 16;
|
|
69
|
+
const dotGap: number = 8;
|
|
70
|
+
const dotWidth: number = 8;
|
|
71
|
+
|
|
72
|
+
const getDotClass = (dotIndex: number) => {
|
|
73
|
+
let className = '';
|
|
74
|
+
|
|
75
|
+
if (dotIndex === currentPageIndex.value) className = 'tide-carousel-dot-active';
|
|
76
|
+
if (Math.abs(currentPageIndex.value - dotIndex) === 1) className = 'tide-carousel-dot-neighbor';
|
|
77
|
+
|
|
78
|
+
return className;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const measureDom = () => {
|
|
82
|
+
if (!containerRef.value) return;
|
|
46
83
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
updateContainerBleed();
|
|
84
|
+
contentWidth.value = containerRef.value.scrollWidth;
|
|
85
|
+
frameWidth.value = containerRef.value.clientWidth;
|
|
50
86
|
};
|
|
51
87
|
|
|
52
88
|
const observeSlides = () => {
|
|
@@ -99,10 +135,17 @@
|
|
|
99
135
|
const scrollToOffset = (target: number) => {
|
|
100
136
|
if (containerRef.value === null) return;
|
|
101
137
|
|
|
138
|
+
const lastOffset: number = slides.value[slides.value.length - 1].offsetLeft;
|
|
139
|
+
const placement = (target / lastOffset) * lastPageIndex.value;
|
|
140
|
+
const isScrollingLeft = placement <= currentPageIndex.value;
|
|
141
|
+
|
|
142
|
+
currentPageIndex.value = isScrollingLeft ? currentPageIndex.value - 1 : currentPageIndex.value + 1;
|
|
143
|
+
|
|
102
144
|
containerRef.value.scrollTo({
|
|
103
145
|
behavior: 'smooth',
|
|
104
146
|
left: target,
|
|
105
147
|
});
|
|
148
|
+
updateDots(isScrollingLeft);
|
|
106
149
|
};
|
|
107
150
|
|
|
108
151
|
const showNextPage = () => {
|
|
@@ -137,19 +180,19 @@
|
|
|
137
180
|
scrollToOffset(slides.value[previousSlide].offsetLeft);
|
|
138
181
|
};
|
|
139
182
|
|
|
140
|
-
const
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
183
|
+
const updateDots = (isScrollingLeft: boolean) => {
|
|
184
|
+
if (!dotsRef.value || dotCountVisible.value >= totalPages.value) return;
|
|
185
|
+
|
|
186
|
+
const isOddDotCount = dotCountVisible.value % 2 !== 0;
|
|
187
|
+
const centerDot =
|
|
188
|
+
isOddDotCount || isScrollingLeft
|
|
189
|
+
? Math.floor(dotCountVisible.value / 2) + 1
|
|
190
|
+
: Math.floor(dotCountVisible.value / 2);
|
|
191
|
+
|
|
192
|
+
dotsRef.value.scrollTo({
|
|
193
|
+
behavior: 'smooth',
|
|
194
|
+
left: currentPage.value < centerDot ? 0 : (currentPage.value - centerDot) * (dotWidth + dotGap),
|
|
195
|
+
});
|
|
153
196
|
};
|
|
154
197
|
|
|
155
198
|
onMounted(() => {
|
|
@@ -157,14 +200,19 @@
|
|
|
157
200
|
|
|
158
201
|
slides.value = Array.from(containerRef.value.children) as HTMLElement[];
|
|
159
202
|
|
|
203
|
+
measureDom();
|
|
160
204
|
observeSlides();
|
|
161
205
|
observeSlot();
|
|
162
|
-
|
|
206
|
+
|
|
207
|
+
if (window) {
|
|
208
|
+
window.addEventListener('resize', measureDom);
|
|
209
|
+
}
|
|
163
210
|
});
|
|
164
211
|
|
|
165
212
|
onUnmounted(() => {
|
|
166
213
|
slideObserver.value?.disconnect();
|
|
167
214
|
slotObserver.value?.disconnect();
|
|
215
|
+
window.removeEventListener('resize', measureDom);
|
|
168
216
|
});
|
|
169
217
|
</script>
|
|
170
218
|
|
|
@@ -225,11 +273,10 @@
|
|
|
225
273
|
|
|
226
274
|
<slot name="misc" />
|
|
227
275
|
|
|
228
|
-
<div :class="[CSS.POSITION.RELATIVE]">
|
|
276
|
+
<div :class="[CSS.POSITION.RELATIVE, CSS.DISPLAY.FLEX, CSS.AXIS1.CENTER]">
|
|
229
277
|
<ul
|
|
230
278
|
:class="[
|
|
231
279
|
'tide-carousel-container',
|
|
232
|
-
props.bleed && 'bleed',
|
|
233
280
|
CSS.DISPLAY.FLEX,
|
|
234
281
|
CSS.GAP.ONE,
|
|
235
282
|
CSS.LIST_BULLETS.OFF,
|
|
@@ -238,11 +285,54 @@
|
|
|
238
285
|
CSS.SNAP.ON,
|
|
239
286
|
]"
|
|
240
287
|
ref="containerRef"
|
|
241
|
-
@scroll="handleScroll"
|
|
242
288
|
>
|
|
243
289
|
<slot />
|
|
244
290
|
</ul>
|
|
245
291
|
|
|
292
|
+
<div
|
|
293
|
+
:class="[
|
|
294
|
+
'tide-carousel-dots-container',
|
|
295
|
+
CSS.POSITION.ABSOLUTE,
|
|
296
|
+
CSS.POSITIONING.BOTTOM,
|
|
297
|
+
CSS.DISPLAY.FLEX,
|
|
298
|
+
CSS.AXIS1.CENTER,
|
|
299
|
+
CSS.MARGIN.BOTTOM.HALF,
|
|
300
|
+
CSS.WIDTH.FULL,
|
|
301
|
+
]"
|
|
302
|
+
:style="{
|
|
303
|
+
width: `${dotContainerWidth}px`,
|
|
304
|
+
}"
|
|
305
|
+
v-if="isScrollByPage && hasDots && totalPages > 1"
|
|
306
|
+
>
|
|
307
|
+
<div
|
|
308
|
+
:class="[
|
|
309
|
+
'tide-carousel-dots',
|
|
310
|
+
CSS.DISPLAY.FLEX,
|
|
311
|
+
CSS.AXIS1.START,
|
|
312
|
+
CSS.AXIS2.CENTER,
|
|
313
|
+
CSS.GAP.HALF,
|
|
314
|
+
CSS.OVERFLOW.X.SCROLL,
|
|
315
|
+
CSS.POINTER_EVENTS.OFF,
|
|
316
|
+
CSS.SCROLLBAR.OFF,
|
|
317
|
+
]"
|
|
318
|
+
ref="dotsRef"
|
|
319
|
+
>
|
|
320
|
+
<div
|
|
321
|
+
:class="[
|
|
322
|
+
'tide-carousel-dot',
|
|
323
|
+
CSS.FLEX.SHRINK.OFF,
|
|
324
|
+
CSS.HEIGHT.ZERO,
|
|
325
|
+
CSS.WIDTH.ZERO,
|
|
326
|
+
CSS.BORDER.RADIUS.FULL,
|
|
327
|
+
CSS.BG.SURFACE.DEFAULT,
|
|
328
|
+
getDotClass(index),
|
|
329
|
+
]"
|
|
330
|
+
:key="index"
|
|
331
|
+
v-for="(_, index) in totalPages"
|
|
332
|
+
/>
|
|
333
|
+
</div>
|
|
334
|
+
</div>
|
|
335
|
+
|
|
246
336
|
<div
|
|
247
337
|
:class="[
|
|
248
338
|
'tide-carousel-button-overlay',
|
|
@@ -279,10 +369,6 @@
|
|
|
279
369
|
</template>
|
|
280
370
|
|
|
281
371
|
<style scoped>
|
|
282
|
-
.tide-carousel-container.bleed {
|
|
283
|
-
transition: margin var(--tide-animate), padding var(--tide-animate);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
372
|
.tide-carousel-button-overlay.hideaway {
|
|
287
373
|
opacity: 0;
|
|
288
374
|
}
|
|
@@ -290,4 +376,21 @@
|
|
|
290
376
|
.tide-carousel:hover .tide-carousel-button-overlay.hideaway {
|
|
291
377
|
opacity: 1;
|
|
292
378
|
}
|
|
379
|
+
|
|
380
|
+
.tide-carousel-dot {
|
|
381
|
+
width: 8px;
|
|
382
|
+
height: 8px;
|
|
383
|
+
opacity: 0.75;
|
|
384
|
+
transform: scale(0.5);
|
|
385
|
+
transition: opacity var(--tide-animate), transform var(--tide-animate);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.tide-carousel-dot-neighbor {
|
|
389
|
+
transform: scale(0.75);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
.tide-carousel-dot-active {
|
|
393
|
+
transform: scale(1);
|
|
394
|
+
opacity: 1;
|
|
395
|
+
}
|
|
293
396
|
</style>
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
|
|
15
15
|
type Args = InstanceType<typeof TideAlert>['$props'] & {
|
|
16
16
|
handleClose: string;
|
|
17
|
+
handleCtaClick: string;
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
const render = (args: Args) => ({
|
|
@@ -33,16 +34,38 @@ const render = (args: Args) => ({
|
|
|
33
34
|
alert('Please specify a valid handler in the "close" control.');
|
|
34
35
|
}
|
|
35
36
|
},
|
|
37
|
+
handleCtaClick: () => {
|
|
38
|
+
action('TideAlert "Action" CTA clicked')({});
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const callback = eval(args.handleCtaClick);
|
|
42
|
+
|
|
43
|
+
if (callback) {
|
|
44
|
+
callback();
|
|
45
|
+
}
|
|
46
|
+
} catch {
|
|
47
|
+
alert('Please specify a valid handler in the "ctaClick" control.');
|
|
48
|
+
}
|
|
49
|
+
},
|
|
36
50
|
},
|
|
37
51
|
setup: () => ({ args }),
|
|
38
|
-
template: `<TideAlert @close="handleClose" v-bind="args">{{ args.default }}</TideAlert>`,
|
|
52
|
+
template: `<TideAlert @close="handleClose" @click="handleCtaClick" v-bind="args">{{ args.default }}</TideAlert>`,
|
|
39
53
|
});
|
|
40
54
|
|
|
41
55
|
const ALERT = prependNoneAsUndefined(STANDARD_ALERT.ALERT);
|
|
42
56
|
|
|
43
57
|
export default {
|
|
44
58
|
argTypes: {
|
|
59
|
+
click: disabledArgType,
|
|
45
60
|
close: disabledArgType,
|
|
61
|
+
ctaLabel: {
|
|
62
|
+
control: 'text',
|
|
63
|
+
description: 'Call To Action that renders as a TideLink; clicking emits a separate `click` event',
|
|
64
|
+
table: {
|
|
65
|
+
defaultValue: { summary: 'None' },
|
|
66
|
+
type: { summary: 'string' },
|
|
67
|
+
},
|
|
68
|
+
},
|
|
46
69
|
dataTrack,
|
|
47
70
|
default: {
|
|
48
71
|
control: 'text',
|
|
@@ -63,6 +86,17 @@ export default {
|
|
|
63
86
|
type: { summary: '() => void' },
|
|
64
87
|
},
|
|
65
88
|
},
|
|
89
|
+
handleCtaClick: {
|
|
90
|
+
control: 'text',
|
|
91
|
+
description: 'JS code or function to execute on CTA click event',
|
|
92
|
+
isEmit: true,
|
|
93
|
+
name: 'click',
|
|
94
|
+
table: {
|
|
95
|
+
category: 'Events',
|
|
96
|
+
defaultValue: { summary: 'None' },
|
|
97
|
+
type: { summary: '() => void' },
|
|
98
|
+
},
|
|
99
|
+
},
|
|
66
100
|
heading: {
|
|
67
101
|
control: 'text',
|
|
68
102
|
description: 'Heading text',
|
|
@@ -88,9 +122,11 @@ export default {
|
|
|
88
122
|
},
|
|
89
123
|
},
|
|
90
124
|
args: {
|
|
125
|
+
ctaLabel: '',
|
|
91
126
|
dataTrack: '',
|
|
92
127
|
default: '',
|
|
93
128
|
handleClose: 'doSomething',
|
|
129
|
+
handleCtaClick: 'doSomething',
|
|
94
130
|
heading: 'Heading',
|
|
95
131
|
isDismissible: undefined,
|
|
96
132
|
isToast: undefined,
|
|
@@ -7,7 +7,6 @@ import { argTypeBooleanUnrequired, disabledArgType, doSomething, lineBreak, tab
|
|
|
7
7
|
import type { StoryContext } from '@storybook/vue3';
|
|
8
8
|
|
|
9
9
|
type Args = InstanceType<typeof TideCarousel>['$props'] & {
|
|
10
|
-
bleed: number | string;
|
|
11
10
|
handleSlidesAddedToView: string;
|
|
12
11
|
};
|
|
13
12
|
|
|
@@ -15,13 +14,13 @@ const formatSnippet = (code: string, context: StoryContext) => {
|
|
|
15
14
|
const { args } = context;
|
|
16
15
|
|
|
17
16
|
const argsWithValues: string[] = [];
|
|
18
|
-
const hasBleed = args.bleed !== '';
|
|
19
17
|
|
|
20
|
-
if (
|
|
18
|
+
if (args.hasDots !== undefined) argsWithValues.push(`has-dots="${args.hasDots}"`);
|
|
21
19
|
if (args.isFloating !== undefined) argsWithValues.push(`:is-floating="${args.isFloating}"`);
|
|
22
20
|
if (args.isHideawayButtons !== undefined) argsWithValues.push(`:is-hideaway-buttons="${args.isHideawayButtons}"`);
|
|
23
21
|
if (args.isScrollByPage !== undefined) argsWithValues.push(`:is-scroll-by-page="false"`);
|
|
24
22
|
if (args.isTouchscreen !== undefined) argsWithValues.push(`:is-touchscreen="${args.isTouchscreen}"`);
|
|
23
|
+
if (args.maxDots !== '') argsWithValues.push(`max-dots="${args.maxDots}"`);
|
|
25
24
|
if (args.subtitle !== '') argsWithValues.push(`subtitle="${args.subtitle}"`);
|
|
26
25
|
if (args.title !== '') argsWithValues.push(`title="${args.title}"`);
|
|
27
26
|
if (args.handleSlidesAddedToView) argsWithValues.push(`@slides-added-to-view="${args.handleSlidesAddedToView}"`);
|
|
@@ -32,7 +31,7 @@ const formatSnippet = (code: string, context: StoryContext) => {
|
|
|
32
31
|
// prettier-ignore
|
|
33
32
|
`<TideCarousel ${argsWithValues.join(' ')}>` + lineBreak +
|
|
34
33
|
slotContentMisc + tab +
|
|
35
|
-
`<li class="tide-shrink-none
|
|
34
|
+
`<li class="tide-shrink-none" v-for="(_child, index) in new Array(12)">` + lineBreak + tab + tab +
|
|
36
35
|
args.default + lineBreak + tab +
|
|
37
36
|
`</li>` + lineBreak +
|
|
38
37
|
`</TideCarousel>`
|
|
@@ -72,37 +71,20 @@ const render = (args: Args) => ({
|
|
|
72
71
|
template:
|
|
73
72
|
`<TideCarousel
|
|
74
73
|
@slides-added-to-view="handleSlidesAddedToView"
|
|
75
|
-
class="tide-margin-x-1"
|
|
76
74
|
v-bind="args"
|
|
77
75
|
>
|
|
78
76
|
<template #misc>{{ args.misc }}</template>
|
|
79
77
|
<li
|
|
80
|
-
|
|
81
|
-
class="tide-shrink-none tide-border-1 tide-border tide-padding-1"
|
|
78
|
+
class="tide-shrink-none tide-border-1 sb-border-blue tide-padding-1 sb-bg-blue-light"
|
|
82
79
|
v-for="(_child, index) in new Array(12)"
|
|
83
80
|
>
|
|
84
81
|
{{ args.default.replace('#', index) }}
|
|
85
82
|
</li>
|
|
86
83
|
</TideCarousel>`,
|
|
87
|
-
updated() {
|
|
88
|
-
if (typeof args.bleed === 'string' && args.bleed === '') {
|
|
89
|
-
args.bleed = 0;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return { args };
|
|
93
|
-
},
|
|
94
84
|
});
|
|
95
85
|
|
|
96
86
|
export default {
|
|
97
87
|
argTypes: {
|
|
98
|
-
bleed: {
|
|
99
|
-
control: 'text',
|
|
100
|
-
description: 'Sets an allowance for visible overflow at component boundaries.',
|
|
101
|
-
table: {
|
|
102
|
-
defaultValue: { summary: 'None' },
|
|
103
|
-
type: { summary: 'number' },
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
88
|
default: {
|
|
107
89
|
control: 'text',
|
|
108
90
|
description: 'Dynamic card content',
|
|
@@ -122,6 +104,13 @@ export default {
|
|
|
122
104
|
type: { summary: '(slides: number[]) => void' },
|
|
123
105
|
},
|
|
124
106
|
},
|
|
107
|
+
hasDots: {
|
|
108
|
+
...argTypeBooleanUnrequired,
|
|
109
|
+
description: 'Determines whether to display the indicator dots overlay',
|
|
110
|
+
table: {
|
|
111
|
+
defaultValue: { summary: 'False' },
|
|
112
|
+
},
|
|
113
|
+
},
|
|
125
114
|
isFloating: {
|
|
126
115
|
...argTypeBooleanUnrequired,
|
|
127
116
|
description: 'Determines whether to display on-page or floating carousel',
|
|
@@ -158,6 +147,14 @@ export default {
|
|
|
158
147
|
defaultValue: { summary: 'None' },
|
|
159
148
|
},
|
|
160
149
|
},
|
|
150
|
+
maxDots: {
|
|
151
|
+
control: 'text',
|
|
152
|
+
description: 'Determines the max number of indicator dots to display at a given time',
|
|
153
|
+
table: {
|
|
154
|
+
defaultValue: { summary: 'None' },
|
|
155
|
+
type: { summary: 'number' },
|
|
156
|
+
},
|
|
157
|
+
},
|
|
161
158
|
misc: {
|
|
162
159
|
control: 'text',
|
|
163
160
|
description: 'Content to display between the title/buttons and carousel content',
|
|
@@ -186,13 +183,14 @@ export default {
|
|
|
186
183
|
},
|
|
187
184
|
},
|
|
188
185
|
args: {
|
|
189
|
-
bleed: '',
|
|
190
186
|
default: 'Card #',
|
|
191
187
|
handleSlidesAddedToView: 'doSomething',
|
|
188
|
+
hasDots: undefined,
|
|
192
189
|
isFloating: undefined,
|
|
193
190
|
isHideawayButtons: undefined,
|
|
194
191
|
isScrollByPage: undefined,
|
|
195
192
|
isTouchscreen: undefined,
|
|
193
|
+
maxDots: '',
|
|
196
194
|
misc: '',
|
|
197
195
|
subtitle: '',
|
|
198
196
|
title: 'Demo',
|
package/src/types/Icon.ts
CHANGED
|
@@ -11,6 +11,7 @@ export const ICON = {
|
|
|
11
11
|
ARROW_CYCLE: 'arrow-cycle',
|
|
12
12
|
ARROW_FORWARD: 'arrow-forward',
|
|
13
13
|
ARROW_RIGHT: 'arrow-right',
|
|
14
|
+
ARROW_UP: 'arrow-up',
|
|
14
15
|
ASSIGNMENT: 'assignment',
|
|
15
16
|
ATTACH_MONEY: 'attach-money',
|
|
16
17
|
AUTO_RENEW: 'auto-renew',
|
|
@@ -110,6 +111,8 @@ export const ICON = {
|
|
|
110
111
|
SMS: 'sms',
|
|
111
112
|
SNOWFLAKE: 'snowflake',
|
|
112
113
|
STAR: 'star',
|
|
114
|
+
STAR_FILLED: 'star-filled',
|
|
115
|
+
STAR_HALF: 'star-half',
|
|
113
116
|
SUMMARIZE: 'summarize',
|
|
114
117
|
SWAP_HORIZ: 'swap-horiz',
|
|
115
118
|
SWAP_VERT: 'swap-vert',
|