@citizenplane/pimp 18.19.0 → 18.19.2
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/components/CpAncillaryCategory.vue.d.ts +3 -3
- package/dist/components/CpAncillaryCategory.vue.d.ts.map +1 -1
- package/dist/pimp.es.js +44 -49
- package/dist/pimp.umd.js +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/CpAncillaryCategory.vue +74 -73
- package/src/stories/CpAncillaryCategory.stories.ts +51 -12
package/package.json
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="cpAncillaryCategory">
|
|
3
|
-
<
|
|
4
|
-
|
|
3
|
+
<component
|
|
4
|
+
:is="headerTag"
|
|
5
|
+
v-bind="headerAttrs"
|
|
6
|
+
class="cpAncillaryCategory__header"
|
|
7
|
+
@click="handleHeaderClick"
|
|
8
|
+
>
|
|
9
|
+
<div class="cpAncillaryCategory__lead">
|
|
5
10
|
<div class="cpAncillaryCategory__visual">
|
|
6
11
|
<img
|
|
7
12
|
v-if="visual"
|
|
@@ -12,34 +17,32 @@
|
|
|
12
17
|
/>
|
|
13
18
|
<cp-icon v-else class="cpAncillaryCategory__fallbackIcon" size="40" type="shopping-bag" />
|
|
14
19
|
</div>
|
|
15
|
-
<div class="
|
|
16
|
-
<
|
|
17
|
-
|
|
20
|
+
<div class="cpAncillaryCategory__content">
|
|
21
|
+
<div class="cpAncillaryCategory__texts">
|
|
22
|
+
<span :id="titleId" class="cpAncillaryCategory__title">{{ title }}</span>
|
|
23
|
+
<span class="cpAncillaryCategory__description">{{ description }}</span>
|
|
24
|
+
</div>
|
|
25
|
+
<div v-if="isSwitch" class="cpAncillaryCategory__trailing">
|
|
26
|
+
<span v-if="hasFromPrice" class="cpAncillaryCategory__price">{{ formattedPrice }}</span>
|
|
27
|
+
<cp-switch v-model="checked" color="accent" />
|
|
28
|
+
</div>
|
|
29
|
+
<div v-else-if="isActuallyExpandable" class="cpAncillaryCategory__trailing">
|
|
30
|
+
<span v-if="hasFromPrice" class="cpAncillaryCategory__fromPriceClip">
|
|
31
|
+
<span :aria-hidden="isOpen" class="cpAncillaryCategory__fromPrice" :class="fromPriceDynamicClass">
|
|
32
|
+
<span class="cpAncillaryCategory__fromPriceLabel">{{ fromPriceLabel }}</span>
|
|
33
|
+
<span class="cpAncillaryCategory__fromPriceAmount">{{ formattedPrice }}</span>
|
|
34
|
+
</span>
|
|
35
|
+
</span>
|
|
36
|
+
<cp-icon
|
|
37
|
+
class="cpAncillaryCategory__chevron"
|
|
38
|
+
:class="chevronDynamicClass"
|
|
39
|
+
size="24"
|
|
40
|
+
type="chevron-down"
|
|
41
|
+
/>
|
|
42
|
+
</div>
|
|
18
43
|
</div>
|
|
19
|
-
</button>
|
|
20
|
-
<div v-if="isSwitch" class="cpAncillaryCategory__trailing">
|
|
21
|
-
<span v-if="hasFromPrice" class="cpAncillaryCategory__price">{{ formattedPrice }}</span>
|
|
22
|
-
<cp-switch v-model="checked" color="accent" />
|
|
23
44
|
</div>
|
|
24
|
-
|
|
25
|
-
<span v-if="hasFromPrice" class="cpAncillaryCategory__fromPriceClip">
|
|
26
|
-
<span :aria-hidden="isOpen" class="cpAncillaryCategory__fromPrice" :class="fromPriceDynamicClass">
|
|
27
|
-
<span class="cpAncillaryCategory__fromPriceLabel">{{ fromPriceLabel }}</span>
|
|
28
|
-
<span class="cpAncillaryCategory__fromPriceAmount">{{ formattedPrice }}</span>
|
|
29
|
-
</span>
|
|
30
|
-
</span>
|
|
31
|
-
<button
|
|
32
|
-
:aria-controls="bodyId"
|
|
33
|
-
:aria-expanded="isOpen"
|
|
34
|
-
:aria-labelledby="titleId"
|
|
35
|
-
class="cpAncillaryCategory__toggle"
|
|
36
|
-
type="button"
|
|
37
|
-
@click="handleToggle"
|
|
38
|
-
>
|
|
39
|
-
<cp-icon class="cpAncillaryCategory__chevron" :class="chevronDynamicClass" size="24" type="chevron-down" />
|
|
40
|
-
</button>
|
|
41
|
-
</div>
|
|
42
|
-
</div>
|
|
45
|
+
</component>
|
|
43
46
|
<cp-transition-expand v-if="isActuallyExpandable">
|
|
44
47
|
<div v-if="isOpen">
|
|
45
48
|
<div :id="bodyId" class="cpAncillaryCategory__body">
|
|
@@ -98,6 +101,12 @@ const toggleId = useId()
|
|
|
98
101
|
const titleId = computed(() => `${toggleId}-title`)
|
|
99
102
|
const bodyId = computed(() => `${toggleId}-body`)
|
|
100
103
|
|
|
104
|
+
const headerTag = computed(() => (isActuallyExpandable.value ? 'button' : 'div'))
|
|
105
|
+
|
|
106
|
+
const headerAttrs = computed(() =>
|
|
107
|
+
isActuallyExpandable.value ? { type: 'button', 'aria-expanded': isOpen.value, 'aria-controls': bodyId.value } : {},
|
|
108
|
+
)
|
|
109
|
+
|
|
101
110
|
const categoryVisuals: Partial<Record<CpAncillaryCategoryTypes, string>> = {
|
|
102
111
|
[CpAncillaryCategoryTypes.BAGGAGES]: BaggagesVisual,
|
|
103
112
|
[CpAncillaryCategoryTypes.CARBON_OFFSET]: CarbonOffsetVisual,
|
|
@@ -126,8 +135,8 @@ const fromPriceDynamicClass = computed(() => ({ 'cpAncillaryCategory__fromPrice-
|
|
|
126
135
|
|
|
127
136
|
const chevronDynamicClass = computed(() => ({ 'cpAncillaryCategory__chevron--isRotated': isOpen.value }))
|
|
128
137
|
|
|
129
|
-
const
|
|
130
|
-
isOpen.value = !isOpen.value
|
|
138
|
+
const handleHeaderClick = () => {
|
|
139
|
+
if (isActuallyExpandable.value) isOpen.value = !isOpen.value
|
|
131
140
|
}
|
|
132
141
|
</script>
|
|
133
142
|
|
|
@@ -141,15 +150,38 @@ const handleToggle = () => {
|
|
|
141
150
|
border-radius: var(--cp-radius-xl);
|
|
142
151
|
background: var(--cp-background-primary);
|
|
143
152
|
box-shadow: var(--cp-shadows-xs);
|
|
153
|
+
container-type: inline-size;
|
|
144
154
|
gap: var(--cp-spacing-sm);
|
|
145
155
|
|
|
146
156
|
&__header {
|
|
157
|
+
@extend %u-focus-outline;
|
|
158
|
+
|
|
147
159
|
display: flex;
|
|
148
160
|
width: 100%;
|
|
149
|
-
align-items: center;
|
|
150
161
|
padding: var(--cp-spacing-lg);
|
|
151
162
|
border-radius: var(--cp-radius-lg);
|
|
163
|
+
text-align: left;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
&__lead {
|
|
167
|
+
display: flex;
|
|
168
|
+
width: 100%;
|
|
169
|
+
min-width: 0;
|
|
170
|
+
align-items: center;
|
|
171
|
+
gap: var(--cp-spacing-xl);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
&__content {
|
|
175
|
+
display: flex;
|
|
176
|
+
min-width: 0;
|
|
177
|
+
flex: auto;
|
|
178
|
+
align-items: center;
|
|
152
179
|
gap: var(--cp-spacing-lg);
|
|
180
|
+
|
|
181
|
+
@container (width < 30rem) {
|
|
182
|
+
flex-direction: column;
|
|
183
|
+
align-items: stretch;
|
|
184
|
+
}
|
|
153
185
|
}
|
|
154
186
|
|
|
155
187
|
&__trailing {
|
|
@@ -160,6 +192,11 @@ const handleToggle = () => {
|
|
|
160
192
|
padding: 0 var(--cp-spacing-xl);
|
|
161
193
|
border-radius: var(--cp-radius-lg);
|
|
162
194
|
gap: var(--cp-spacing-lg);
|
|
195
|
+
|
|
196
|
+
@container (width < 30rem) {
|
|
197
|
+
justify-content: flex-start;
|
|
198
|
+
padding: 0;
|
|
199
|
+
}
|
|
163
200
|
}
|
|
164
201
|
|
|
165
202
|
&__price {
|
|
@@ -177,7 +214,7 @@ const handleToggle = () => {
|
|
|
177
214
|
&__fromPrice {
|
|
178
215
|
display: flex;
|
|
179
216
|
align-items: center;
|
|
180
|
-
gap: var(--cp-spacing-
|
|
217
|
+
gap: var(--cp-spacing-sm);
|
|
181
218
|
opacity: 1;
|
|
182
219
|
transform: translate3d(0, 0, 0);
|
|
183
220
|
transition:
|
|
@@ -206,46 +243,6 @@ const handleToggle = () => {
|
|
|
206
243
|
line-height: var(--cp-text-lg-line-height);
|
|
207
244
|
}
|
|
208
245
|
|
|
209
|
-
&__toggle {
|
|
210
|
-
display: flex;
|
|
211
|
-
flex: none;
|
|
212
|
-
align-items: center;
|
|
213
|
-
justify-content: center;
|
|
214
|
-
padding: var(--cp-spacing-xs);
|
|
215
|
-
border: 0;
|
|
216
|
-
border-radius: 50%;
|
|
217
|
-
appearance: none;
|
|
218
|
-
background: transparent;
|
|
219
|
-
color: inherit;
|
|
220
|
-
cursor: pointer;
|
|
221
|
-
transition: background-color 200ms ease;
|
|
222
|
-
|
|
223
|
-
@media (hover: hover) {
|
|
224
|
-
&:hover {
|
|
225
|
-
background: var(--cp-background-secondary-hover);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
&:focus-visible {
|
|
230
|
-
border-radius: 50%;
|
|
231
|
-
background: var(--cp-background-secondary-hover);
|
|
232
|
-
|
|
233
|
-
@extend %u-focus-outline;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
&__lead {
|
|
238
|
-
@extend %u-focus-outline;
|
|
239
|
-
|
|
240
|
-
display: flex;
|
|
241
|
-
width: 100%;
|
|
242
|
-
min-width: 0;
|
|
243
|
-
flex: auto;
|
|
244
|
-
align-items: center;
|
|
245
|
-
gap: var(--cp-spacing-xl);
|
|
246
|
-
text-align: left;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
246
|
&__visual {
|
|
250
247
|
display: flex;
|
|
251
248
|
width: fn.px-to-rem(96);
|
|
@@ -273,6 +270,7 @@ const handleToggle = () => {
|
|
|
273
270
|
&__texts {
|
|
274
271
|
display: flex;
|
|
275
272
|
min-width: 0;
|
|
273
|
+
flex: auto;
|
|
276
274
|
flex-direction: column;
|
|
277
275
|
}
|
|
278
276
|
|
|
@@ -297,6 +295,10 @@ const handleToggle = () => {
|
|
|
297
295
|
&--isRotated {
|
|
298
296
|
rotate: 180deg;
|
|
299
297
|
}
|
|
298
|
+
|
|
299
|
+
@container (width < 30rem) {
|
|
300
|
+
display: none;
|
|
301
|
+
}
|
|
300
302
|
}
|
|
301
303
|
|
|
302
304
|
&__body {
|
|
@@ -305,7 +307,6 @@ const handleToggle = () => {
|
|
|
305
307
|
padding: var(--cp-spacing-lg);
|
|
306
308
|
border-radius: var(--cp-radius-lg);
|
|
307
309
|
background: var(--cp-background-primary);
|
|
308
|
-
gap: var(--cp-spacing-lg);
|
|
309
310
|
}
|
|
310
311
|
}
|
|
311
312
|
</style>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
|
2
|
-
import {
|
|
2
|
+
import { ref } from 'vue'
|
|
3
3
|
|
|
4
4
|
import CpAncillaryCategory from '@/components/CpAncillaryCategory.vue'
|
|
5
5
|
import CpAncillaryItem from '@/components/CpAncillaryItem.vue'
|
|
@@ -14,17 +14,6 @@ const galleryRowStyle = 'display: flex; flex-direction: column; gap: 10px; width
|
|
|
14
14
|
const meta = {
|
|
15
15
|
title: 'Business/CpAncillaryCategory',
|
|
16
16
|
component: CpAncillaryCategory,
|
|
17
|
-
decorators: [
|
|
18
|
-
(story) => ({
|
|
19
|
-
components: { story },
|
|
20
|
-
setup() {
|
|
21
|
-
onMounted(() => {
|
|
22
|
-
document.getElementById('storybook-root')?.style.setProperty('width', '100%')
|
|
23
|
-
})
|
|
24
|
-
},
|
|
25
|
-
template: '<story />',
|
|
26
|
-
}),
|
|
27
|
-
],
|
|
28
17
|
argTypes: {
|
|
29
18
|
currency: {
|
|
30
19
|
control: 'text',
|
|
@@ -232,6 +221,56 @@ export const Switch: Story = {
|
|
|
232
221
|
}),
|
|
233
222
|
}
|
|
234
223
|
|
|
224
|
+
/**
|
|
225
|
+
* Same expandable and switch cards at a 358px container width: the
|
|
226
|
+
* container query on the root stacks the from-price under the texts
|
|
227
|
+
* instead of beside them.
|
|
228
|
+
*/
|
|
229
|
+
export const Mobile: Story = {
|
|
230
|
+
args: {
|
|
231
|
+
...Default.args,
|
|
232
|
+
},
|
|
233
|
+
parameters: { controls: { disable: true } },
|
|
234
|
+
render: () => ({
|
|
235
|
+
components: { CpAncillaryCategory },
|
|
236
|
+
setup() {
|
|
237
|
+
const switchChecked = ref(false)
|
|
238
|
+
return { galleryListStyle, galleryRowStyle, docLabelStyle, switchChecked }
|
|
239
|
+
},
|
|
240
|
+
template: `
|
|
241
|
+
<div :style="galleryListStyle">
|
|
242
|
+
<div :style="galleryRowStyle">
|
|
243
|
+
<span :style="docLabelStyle">Expandable</span>
|
|
244
|
+
<div style="width: 358px;">
|
|
245
|
+
<CpAncillaryCategory
|
|
246
|
+
title="Sport Equipments"
|
|
247
|
+
description="Travel with special or oversized items you need to bring along."
|
|
248
|
+
type="sportEquipments"
|
|
249
|
+
is-expandable
|
|
250
|
+
is-default-closed
|
|
251
|
+
:from-price="5990"
|
|
252
|
+
currency="EUR"
|
|
253
|
+
/>
|
|
254
|
+
</div>
|
|
255
|
+
</div>
|
|
256
|
+
<div :style="galleryRowStyle">
|
|
257
|
+
<span :style="docLabelStyle">Switch</span>
|
|
258
|
+
<div style="width: 358px;">
|
|
259
|
+
<CpAncillaryCategory
|
|
260
|
+
v-model:checked="switchChecked"
|
|
261
|
+
title="Carbon offset"
|
|
262
|
+
description="Compensate the CO2 emissions of your flight"
|
|
263
|
+
type="carbonOffset"
|
|
264
|
+
:from-price="490"
|
|
265
|
+
currency="EUR"
|
|
266
|
+
/>
|
|
267
|
+
</div>
|
|
268
|
+
</div>
|
|
269
|
+
</div>
|
|
270
|
+
`,
|
|
271
|
+
}),
|
|
272
|
+
}
|
|
273
|
+
|
|
235
274
|
/* -------------------------------------------------------------------------- */
|
|
236
275
|
/* Gallery */
|
|
237
276
|
/* -------------------------------------------------------------------------- */
|