Skip to content

Commit 69a2e13

Browse files
Merge pull request #5881 from kiva/MP-1394_my_kiva_carousel_variation
feat: new my kiva carousel variation
2 parents 84bb9d2 + 6f0b881 commit 69a2e13

File tree

2 files changed

+166
-0
lines changed

2 files changed

+166
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import JourneyCardCarousel from '#src/components/Contentful/JourneyCardCarousel.vue';
2+
3+
export default {
4+
title: 'MyKiva/JourneyCardCarousel',
5+
component: JourneyCardCarousel,
6+
};
7+
8+
const slideData = {
9+
title: 'Women’s equality',
10+
subtitle: 'Continue challenge',
11+
badgeUrl: '//images.ctfassets.net/j0p9a6ql0rn7/3dAEh0zYSkqK5Up5q8Flv8/70d21f8db5f93b20be1581ef333dc60e/Women_10.svg',
12+
backgroundImg: 'https://images.ctfassets.net/j0p9a6ql0rn7/7mY5ZujL9UfbluRkVkHgkX/5ec83a74e7c1dc387f3fa35af34f5243/mg-hppromo-1-wxga-retina.jpg',
13+
primaryCtaText: 'Lend to a woman',
14+
primaryCtaUrl: '/lend-by-category',
15+
secondaryCtaText: 'Learn more',
16+
secondaryCtaUrl: '/about',
17+
};
18+
19+
const content = {
20+
slides: [
21+
{ ...slideData },
22+
{ ...slideData, secondaryCtaText: '', },
23+
{ ...slideData },
24+
{ ...slideData },
25+
{ ...slideData },
26+
],
27+
};
28+
29+
const story = (args = {}) => {
30+
const template = (_args, { argTypes }) => ({
31+
props: Object.keys(argTypes),
32+
components: { JourneyCardCarousel },
33+
setup() { return { args }; },
34+
template: `
35+
<div style="max-width: 1200px;">
36+
<journey-card-carousel v-bind="args" />
37+
</div>
38+
`,
39+
});
40+
template.args = args;
41+
return template;
42+
};
43+
44+
export const Default = story({ content });
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
<template>
2+
<div>
3+
<KvCarousel
4+
:embla-options="{
5+
loop: false,
6+
align: slidesAligmment,
7+
slidesToScroll,
8+
}"
9+
:multiple-slides-visible="true"
10+
class="journey-card-carousel tw-w-full md:tw-overflow-visible"
11+
>
12+
<template
13+
v-for="(slide, index) in carouselSlides"
14+
#[`slide${index}`]
15+
:key="index"
16+
>
17+
<div
18+
class="tw-w-full tw-relative tw-rounded tw-bg-cover tw-bg-center journey-card"
19+
:style="{ backgroundImage: `url(${backgroundImg(slide)})` }"
20+
>
21+
<div class="tw-absolute tw-w-full tw-bottom-1.5 tw-px-1.5">
22+
<div class="tw-flex tw-items-center tw-gap-1 tw-w-full tw-mb-1.5">
23+
<img
24+
class="tw-h-6"
25+
:src="badgeUrl(slide)"
26+
>
27+
<div class="tw-text-primary-inverse">
28+
<h2 class="tw-text-h3">
29+
{{ title(slide) }}
30+
</h2>
31+
<p
32+
v-if="subTitle(slide)"
33+
class="tw-text-small"
34+
>
35+
{{ subTitle(slide) }}
36+
</p>
37+
</div>
38+
</div>
39+
<div class="tw-flex tw-flex-col md:tw-flex-row tw-gap-1.5 md:tw-gap-2.5">
40+
<button
41+
v-if="secondaryCtaText(slide) && secondaryCtaUrl(slide)"
42+
:to="secondaryCtaUrl(slide)"
43+
variant="tertiary"
44+
class="tw-inline-flex tw-justify-center tw-items-center tw-rounded tw-py-1 tw-px-3
45+
tw-border tw-border-white tw-font-medium tw-text-center tw-text-white"
46+
>
47+
{{ secondaryCtaText(slide) }}
48+
</button>
49+
<KvButton
50+
:to="primaryCtaUrl(slide)"
51+
variant="secondary"
52+
>
53+
{{ primaryCtaText(slide) }}
54+
</KvButton>
55+
</div>
56+
</div>
57+
</div>
58+
</template>
59+
</KvCarousel>
60+
</div>
61+
</template>
62+
63+
<script setup>
64+
import { computed } from 'vue';
65+
import useIsMobile from '#src/composables/useIsMobile';
66+
import { MOBILE_BREAKPOINT } from '#src/composables/useBadgeModal';
67+
import { KvCarousel, KvButton } from '@kiva/kv-components';
68+
69+
const props = defineProps({
70+
content: {
71+
type: Object,
72+
default: () => ({}),
73+
},
74+
});
75+
76+
const { isMobile } = useIsMobile(MOBILE_BREAKPOINT);
77+
78+
const carouselSlides = computed(() => props.content?.slides || []); // TODO: replace with Contentful data
79+
80+
const slidesAligmment = computed(() => {
81+
return isMobile.value ? 'start' : 'center';
82+
});
83+
84+
const slidesToScroll = computed(() => {
85+
return isMobile.value ? 1 : 2;
86+
});
87+
88+
const title = slide => slide?.title || '';
89+
const subTitle = slide => slide?.subtitle || '';
90+
const badgeUrl = slide => slide?.badgeUrl || '';
91+
const backgroundImg = slide => slide?.backgroundImg || '';
92+
const primaryCtaText = slide => slide?.primaryCtaText || '';
93+
const primaryCtaUrl = slide => slide?.primaryCtaUrl || '';
94+
const secondaryCtaText = slide => slide?.secondaryCtaText || '';
95+
const secondaryCtaUrl = slide => slide?.secondaryCtaUrl || '';
96+
</script>
97+
98+
<style lang="postcss" scoped>
99+
.journey-card {
100+
width: 322px;
101+
height: 402px;
102+
103+
@screen md {
104+
width: 520px;
105+
height: 390px;
106+
}
107+
}
108+
109+
.journey-card-carousel:deep(.kv-carousel__controls) {
110+
@apply tw-hidden md:tw-flex tw-gap-x-4 tw-py-1.5 tw-w-full tw-overflow-visible;
111+
}
112+
113+
.journey-card-carousel:deep(.kv-carousel__controls > button) {
114+
@apply tw-w-5 tw-h-5 tw-border-0;
115+
116+
box-shadow: 0 4px 12px 0 rgb(0 0 0 / 8%);
117+
}
118+
119+
.journey-card-carousel:deep(.kv-carousel__controls > div) {
120+
@apply tw-hidden;
121+
}
122+
</style>

0 commit comments

Comments
 (0)