@citizenplane/pimp 18.13.5 → 18.14.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/CpBottomSheet.vue.d.ts +11 -6
- package/dist/components/CpBottomSheet.vue.d.ts.map +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/composables/useBottomSheetDrag.d.ts +33 -0
- package/dist/composables/useBottomSheetDrag.d.ts.map +1 -0
- package/dist/pimp.es.js +6322 -6807
- package/dist/pimp.umd.js +38 -40
- package/dist/style.css +1 -1
- package/package.json +2 -2
- package/src/assets/css/easings.css +23 -0
- package/src/components/CpBottomSheet.vue +283 -92
- package/src/components/CpSeatMapEmergencyExitDialog.vue +2 -2
- package/src/components/index.ts +0 -1
- package/src/composables/useBottomSheetDrag.ts +221 -0
- package/src/stories/CpBottomSheet.stories.ts +186 -2
- package/src/stories/Easings.stories.ts +0 -4
- package/vite.config.js +1 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { useResizeObserver, useWindowSize } from '@vueuse/core'
|
|
2
|
+
import type { FullGestureState } from '@vueuse/gesture'
|
|
3
|
+
import { rubberbandIfOutOfBounds } from '@vueuse/gesture'
|
|
4
|
+
import type { ShallowRef } from 'vue'
|
|
5
|
+
import { computed, ref, watch } from 'vue'
|
|
6
|
+
|
|
7
|
+
type SnapPoint = number | `${number}%`
|
|
8
|
+
|
|
9
|
+
type ElementRef = Readonly<ShallowRef<HTMLElement | null>>
|
|
10
|
+
|
|
11
|
+
interface Options {
|
|
12
|
+
canSwipeClose: boolean
|
|
13
|
+
expandOnContentDrag: boolean
|
|
14
|
+
halfAndExpand: boolean
|
|
15
|
+
preventClose: boolean
|
|
16
|
+
snapPoints: SnapPoint[]
|
|
17
|
+
swipeCloseThreshold: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface Context {
|
|
21
|
+
contentRef: ElementRef
|
|
22
|
+
footerRef: ElementRef
|
|
23
|
+
headerRef: ElementRef
|
|
24
|
+
onDismiss: () => void
|
|
25
|
+
scrollRef: ElementRef
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const RUBBERBAND_TENSION = 0.25
|
|
29
|
+
const FLICK_CLOSE_TOLERANCE = 10
|
|
30
|
+
|
|
31
|
+
export const useBottomSheetDrag = (options: Options, context: Context) => {
|
|
32
|
+
const { contentRef, footerRef, headerRef, onDismiss, scrollRef } = context
|
|
33
|
+
|
|
34
|
+
const { height: windowHeight } = useWindowSize()
|
|
35
|
+
|
|
36
|
+
const height = ref<number | null>(null)
|
|
37
|
+
const translateY = ref(0)
|
|
38
|
+
const isDragging = ref(false)
|
|
39
|
+
const naturalHeight = ref(0)
|
|
40
|
+
const currentSnapPointIndex = ref(0)
|
|
41
|
+
|
|
42
|
+
let dragStartHeight = 0
|
|
43
|
+
let contentDragOffset = 0
|
|
44
|
+
let isContentDragActive = false
|
|
45
|
+
|
|
46
|
+
const measureNaturalHeight = () => {
|
|
47
|
+
const parts = [headerRef, contentRef, footerRef]
|
|
48
|
+
const total = parts.reduce((sum, part) => sum + (part.value?.getBoundingClientRect().height ?? 0), 0)
|
|
49
|
+
|
|
50
|
+
naturalHeight.value = Math.ceil(total)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const resolvedSnapPoints = computed<SnapPoint[]>(() => {
|
|
54
|
+
if (options.snapPoints.length) return options.snapPoints
|
|
55
|
+
if (options.halfAndExpand) return ['50%', '100%']
|
|
56
|
+
|
|
57
|
+
return [naturalHeight.value]
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const snapPointHeights = computed(() =>
|
|
61
|
+
resolvedSnapPoints.value.map((snapPoint) =>
|
|
62
|
+
typeof snapPoint === 'number'
|
|
63
|
+
? Math.min(snapPoint, windowHeight.value)
|
|
64
|
+
: (windowHeight.value * Number.parseFloat(snapPoint)) / 100,
|
|
65
|
+
),
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
const minSnapPointHeight = computed(() => Math.min(...snapPointHeights.value))
|
|
69
|
+
const maxSnapPointHeight = computed(() => Math.max(...snapPointHeights.value))
|
|
70
|
+
|
|
71
|
+
const closestSnapPointIndex = computed(() => {
|
|
72
|
+
const distances = snapPointHeights.value.map((snapPointHeight) => Math.abs(snapPointHeight - (height.value ?? 0)))
|
|
73
|
+
|
|
74
|
+
return distances.indexOf(Math.min(...distances))
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
const swipeCloseDistance = computed(() => {
|
|
78
|
+
const sheetHeight = height.value ?? minSnapPointHeight.value
|
|
79
|
+
const threshold = Number.parseFloat(options.swipeCloseThreshold)
|
|
80
|
+
|
|
81
|
+
if (Number.isNaN(threshold)) return sheetHeight / 2
|
|
82
|
+
if (options.swipeCloseThreshold.includes('%')) return (sheetHeight * threshold) / 100
|
|
83
|
+
|
|
84
|
+
return threshold
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
const snapTo = (snapPointIndex: number) => {
|
|
88
|
+
const snapPointHeight = snapPointHeights.value[snapPointIndex]
|
|
89
|
+
if (snapPointHeight === undefined) return
|
|
90
|
+
|
|
91
|
+
currentSnapPointIndex.value = snapPointIndex
|
|
92
|
+
height.value = snapPointHeight
|
|
93
|
+
translateY.value = 0
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const snapToSmallest = () => snapTo(snapPointHeights.value.indexOf(minSnapPointHeight.value))
|
|
97
|
+
|
|
98
|
+
const reset = () => {
|
|
99
|
+
height.value = null
|
|
100
|
+
translateY.value = 0
|
|
101
|
+
isDragging.value = false
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const startDrag = () => {
|
|
105
|
+
isDragging.value = true
|
|
106
|
+
dragStartHeight = height.value ?? minSnapPointHeight.value
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const applyDragOffset = (offsetY: number) => {
|
|
110
|
+
const targetHeight = dragStartHeight - offsetY
|
|
111
|
+
const minHeight = minSnapPointHeight.value
|
|
112
|
+
|
|
113
|
+
if (targetHeight >= minHeight) {
|
|
114
|
+
height.value = rubberbandIfOutOfBounds(targetHeight, 0, maxSnapPointHeight.value, RUBBERBAND_TENSION)
|
|
115
|
+
translateY.value = 0
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const overshoot = minHeight - targetHeight
|
|
120
|
+
|
|
121
|
+
height.value = minHeight
|
|
122
|
+
translateY.value = options.canSwipeClose
|
|
123
|
+
? overshoot
|
|
124
|
+
: rubberbandIfOutOfBounds(overshoot, -minHeight, 0, RUBBERBAND_TENSION)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const shouldCloseAfterDrag = (swipeY: number) => {
|
|
128
|
+
if (!options.canSwipeClose || options.preventClose) return false
|
|
129
|
+
|
|
130
|
+
const isFlickedDown = swipeY > 0 && (height.value ?? 0) <= minSnapPointHeight.value + FLICK_CLOSE_TOLERANCE
|
|
131
|
+
|
|
132
|
+
return isFlickedDown || translateY.value > swipeCloseDistance.value
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const snapPointIndexInSwipeDirection = (swipeY: number) => {
|
|
136
|
+
const currentHeight = height.value ?? 0
|
|
137
|
+
const isSwipingDown = swipeY > 0
|
|
138
|
+
const reachable = snapPointHeights.value.filter((snapPointHeight) =>
|
|
139
|
+
isSwipingDown ? snapPointHeight < currentHeight - 1 : snapPointHeight > currentHeight + 1,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
if (!reachable.length) return closestSnapPointIndex.value
|
|
143
|
+
|
|
144
|
+
return snapPointHeights.value.indexOf(isSwipingDown ? Math.max(...reachable) : Math.min(...reachable))
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const endDrag = (swipeY: number) => {
|
|
148
|
+
isDragging.value = false
|
|
149
|
+
|
|
150
|
+
if (shouldCloseAfterDrag(swipeY)) {
|
|
151
|
+
onDismiss()
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const isSwipe = swipeY !== 0 && snapPointHeights.value.length > 1
|
|
156
|
+
|
|
157
|
+
snapTo(isSwipe ? snapPointIndexInSwipeDirection(swipeY) : closestSnapPointIndex.value)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const onHandleDrag = ({ first, last, movement, swipe }: FullGestureState<'drag'>) => {
|
|
161
|
+
if (first) startDrag()
|
|
162
|
+
else if (last) endDrag(swipe[1])
|
|
163
|
+
else applyDragOffset(movement[1])
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const canStartContentDrag = (movementY: number) => {
|
|
167
|
+
if (!options.expandOnContentDrag) return false
|
|
168
|
+
if ((scrollRef.value?.scrollTop ?? 0) > 0) return false
|
|
169
|
+
if (movementY > 0) return true
|
|
170
|
+
|
|
171
|
+
return snapPointHeights.value.length > 1 && (height.value ?? 0) < maxSnapPointHeight.value
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const onContentDrag = ({ first, last, movement, swipe }: FullGestureState<'drag'>) => {
|
|
175
|
+
if (first) {
|
|
176
|
+
isContentDragActive = false
|
|
177
|
+
return
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (last) {
|
|
181
|
+
if (isContentDragActive) endDrag(swipe[1])
|
|
182
|
+
isContentDragActive = false
|
|
183
|
+
return
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (!isContentDragActive) {
|
|
187
|
+
if (!canStartContentDrag(movement[1])) return
|
|
188
|
+
|
|
189
|
+
isContentDragActive = true
|
|
190
|
+
contentDragOffset = movement[1]
|
|
191
|
+
startDrag()
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
applyDragOffset(movement[1] - contentDragOffset)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const onScrollTouchMove = (event: TouchEvent) => {
|
|
198
|
+
if (!isContentDragActive || !event.cancelable) return
|
|
199
|
+
event.preventDefault()
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
useResizeObserver([headerRef, contentRef, footerRef], measureNaturalHeight)
|
|
203
|
+
|
|
204
|
+
watch(snapPointHeights, () => {
|
|
205
|
+
if (height.value === null || isDragging.value) return
|
|
206
|
+
snapTo(currentSnapPointIndex.value)
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
height,
|
|
211
|
+
isDragging,
|
|
212
|
+
measureNaturalHeight,
|
|
213
|
+
onContentDrag,
|
|
214
|
+
onHandleDrag,
|
|
215
|
+
onScrollTouchMove,
|
|
216
|
+
reset,
|
|
217
|
+
snapToSmallest,
|
|
218
|
+
translateY,
|
|
219
|
+
windowHeight,
|
|
220
|
+
}
|
|
221
|
+
}
|
|
@@ -15,7 +15,8 @@ const meta = {
|
|
|
15
15
|
argTypes: {
|
|
16
16
|
animationDuration: {
|
|
17
17
|
control: 'number',
|
|
18
|
-
description:
|
|
18
|
+
description:
|
|
19
|
+
'Duration of the spring used to present the sheet, in milliseconds. Leaving reuses a third of it on a dry curve.',
|
|
19
20
|
},
|
|
20
21
|
canBackdropClose: {
|
|
21
22
|
control: 'boolean',
|
|
@@ -25,14 +26,27 @@ const meta = {
|
|
|
25
26
|
control: 'boolean',
|
|
26
27
|
description: 'Enable swipe-to-close gesture',
|
|
27
28
|
},
|
|
29
|
+
expandOnContentDrag: {
|
|
30
|
+
control: 'boolean',
|
|
31
|
+
description: 'Let a drag started on the body move the sheet instead of scrolling it',
|
|
32
|
+
},
|
|
28
33
|
preventClose: {
|
|
29
34
|
control: 'boolean',
|
|
30
35
|
description: 'Prevent the sheet from emitting close when dismissed',
|
|
31
36
|
},
|
|
37
|
+
snapPoints: {
|
|
38
|
+
control: 'object',
|
|
39
|
+
description: 'Heights the sheet snaps to, in pixels or in percentage of the viewport height',
|
|
40
|
+
},
|
|
32
41
|
swipeCloseThreshold: {
|
|
33
42
|
control: 'text',
|
|
34
43
|
description: 'Translation threshold after which the sheet closes (px or %)',
|
|
35
44
|
},
|
|
45
|
+
teleportTo: {
|
|
46
|
+
control: 'text',
|
|
47
|
+
description:
|
|
48
|
+
'Selector the sheet teleports to. Defaults to Nuxt SSR-safe `#teleports` container, falling back to `body` when the host does not provide it.',
|
|
49
|
+
},
|
|
36
50
|
onClose: { action: 'close' },
|
|
37
51
|
onOpen: { action: 'open' },
|
|
38
52
|
},
|
|
@@ -47,7 +61,7 @@ type Story = StoryObj<typeof meta>
|
|
|
47
61
|
*/
|
|
48
62
|
export const Default: Story = {
|
|
49
63
|
args: {
|
|
50
|
-
animationDuration:
|
|
64
|
+
animationDuration: 600,
|
|
51
65
|
canBackdropClose: true,
|
|
52
66
|
canSwipeClose: true,
|
|
53
67
|
swipeCloseThreshold: '20%',
|
|
@@ -128,6 +142,176 @@ export const NoBackdropClose: Story = {
|
|
|
128
142
|
}),
|
|
129
143
|
}
|
|
130
144
|
|
|
145
|
+
/**
|
|
146
|
+
* With `expandOnContentDrag`, a drag started on the body of the sheet moves the sheet
|
|
147
|
+
* itself instead of scrolling it. The sheet opens on its smallest snap point (50%):
|
|
148
|
+
* drag the list upwards to expand it to full height, then drag it back down — once the
|
|
149
|
+
* list is scrolled to the top — to collapse it and eventually close it. Anywhere else in
|
|
150
|
+
* the scroll, the body scrolls as usual.
|
|
151
|
+
*
|
|
152
|
+
* Turn the `expandOnContentDrag` control off to compare: the body then only ever scrolls,
|
|
153
|
+
* and the sheet can only be resized from its header or its footer.
|
|
154
|
+
*/
|
|
155
|
+
export const ExpandOnContentDrag: Story = {
|
|
156
|
+
args: {
|
|
157
|
+
expandOnContentDrag: true,
|
|
158
|
+
snapPoints: ['50%', '100%'],
|
|
159
|
+
},
|
|
160
|
+
render: (args) => ({
|
|
161
|
+
setup() {
|
|
162
|
+
const isVisible = ref(false)
|
|
163
|
+
const destinations = [
|
|
164
|
+
'Paris',
|
|
165
|
+
'London',
|
|
166
|
+
'Berlin',
|
|
167
|
+
'Madrid',
|
|
168
|
+
'Rome',
|
|
169
|
+
'Lisbon',
|
|
170
|
+
'Amsterdam',
|
|
171
|
+
'Vienna',
|
|
172
|
+
'Prague',
|
|
173
|
+
'Copenhagen',
|
|
174
|
+
'Stockholm',
|
|
175
|
+
'Oslo',
|
|
176
|
+
'Helsinki',
|
|
177
|
+
'Dublin',
|
|
178
|
+
'Brussels',
|
|
179
|
+
'Zurich',
|
|
180
|
+
'Warsaw',
|
|
181
|
+
'Budapest',
|
|
182
|
+
'Athens',
|
|
183
|
+
'Porto',
|
|
184
|
+
'Paris',
|
|
185
|
+
'London',
|
|
186
|
+
'Berlin',
|
|
187
|
+
'Madrid',
|
|
188
|
+
'Rome',
|
|
189
|
+
'Lisbon',
|
|
190
|
+
'Amsterdam',
|
|
191
|
+
'Vienna',
|
|
192
|
+
'Prague',
|
|
193
|
+
'Copenhagen',
|
|
194
|
+
'Stockholm',
|
|
195
|
+
'Oslo',
|
|
196
|
+
'Helsinki',
|
|
197
|
+
'Dublin',
|
|
198
|
+
'Brussels',
|
|
199
|
+
'Zurich',
|
|
200
|
+
'Warsaw',
|
|
201
|
+
'Budapest',
|
|
202
|
+
'Athens',
|
|
203
|
+
'Porto',
|
|
204
|
+
'Paris',
|
|
205
|
+
'London',
|
|
206
|
+
'Berlin',
|
|
207
|
+
'Madrid',
|
|
208
|
+
'Rome',
|
|
209
|
+
'Lisbon',
|
|
210
|
+
'Amsterdam',
|
|
211
|
+
'Vienna',
|
|
212
|
+
'Prague',
|
|
213
|
+
'Copenhagen',
|
|
214
|
+
'Stockholm',
|
|
215
|
+
'Oslo',
|
|
216
|
+
'Helsinki',
|
|
217
|
+
'Dublin',
|
|
218
|
+
'Brussels',
|
|
219
|
+
'Zurich',
|
|
220
|
+
'Warsaw',
|
|
221
|
+
'Budapest',
|
|
222
|
+
'Athens',
|
|
223
|
+
'Porto',
|
|
224
|
+
]
|
|
225
|
+
return { args, isVisible, destinations }
|
|
226
|
+
},
|
|
227
|
+
template: `
|
|
228
|
+
<CpButton @click="isVisible = true">Open Bottom Sheet</CpButton>
|
|
229
|
+
<CpBottomSheet
|
|
230
|
+
v-bind="args"
|
|
231
|
+
v-model="isVisible"
|
|
232
|
+
@close="isVisible = false"
|
|
233
|
+
>
|
|
234
|
+
<template #header><strong>Drag the list to resize the sheet</strong></template>
|
|
235
|
+
<p v-for="destination in destinations" :key="destination">{{ destination }}</p>
|
|
236
|
+
<template #footer>
|
|
237
|
+
<CpButton @click="isVisible = false">Close</CpButton>
|
|
238
|
+
</template>
|
|
239
|
+
</CpBottomSheet>
|
|
240
|
+
`,
|
|
241
|
+
}),
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Sheets can be nested by declaring one inside the slots of another. Every sheet teleports
|
|
246
|
+
* to the same container, so the child is inserted after its parent and stacks on top of it
|
|
247
|
+
* with its own backdrop — no `z-index` juggling required.
|
|
248
|
+
*
|
|
249
|
+
* Each level keeps its own props, height and gestures: dismiss the child by tapping its
|
|
250
|
+
* backdrop, swiping it down or using its actions, and the parent is revealed untouched.
|
|
251
|
+
* Closing the parent unmounts the whole chain.
|
|
252
|
+
*
|
|
253
|
+
* The nested levels declare no snap points, so each one measures its own header, body and
|
|
254
|
+
* footer and shows them in full. Only the parent is given a height, wide enough to stay
|
|
255
|
+
* visible above its children.
|
|
256
|
+
*/
|
|
257
|
+
export const Nested: Story = {
|
|
258
|
+
args: {
|
|
259
|
+
canBackdropClose: true,
|
|
260
|
+
canSwipeClose: true,
|
|
261
|
+
snapPoints: ['70%'],
|
|
262
|
+
},
|
|
263
|
+
render: (args) => ({
|
|
264
|
+
setup() {
|
|
265
|
+
const isVisible = ref(false)
|
|
266
|
+
const isPassengerVisible = ref(false)
|
|
267
|
+
const isSeatVisible = ref(false)
|
|
268
|
+
const passengers = ['Ada Lovelace', 'Grace Hopper', 'Alan Turing']
|
|
269
|
+
const selectedPassenger = ref(passengers[0])
|
|
270
|
+
return { args, isVisible, isPassengerVisible, isSeatVisible, passengers, selectedPassenger }
|
|
271
|
+
},
|
|
272
|
+
template: `
|
|
273
|
+
<CpButton @click="isVisible = true">Open Bottom Sheet</CpButton>
|
|
274
|
+
<CpBottomSheet
|
|
275
|
+
v-bind="args"
|
|
276
|
+
v-model="isVisible"
|
|
277
|
+
@close="isVisible = false"
|
|
278
|
+
>
|
|
279
|
+
<template #header><strong>Level 1 — Booking</strong></template>
|
|
280
|
+
<p>This is the parent sheet. Open the next level to stack a second sheet on top of it.</p>
|
|
281
|
+
<p>Traveller: <strong>{{ selectedPassenger }}</strong></p>
|
|
282
|
+
|
|
283
|
+
<CpBottomSheet v-model="isPassengerVisible" @close="isPassengerVisible = false">
|
|
284
|
+
<template #header><strong>Level 2 — Passengers</strong></template>
|
|
285
|
+
<p>Pick a traveller, or go one level deeper.</p>
|
|
286
|
+
<CpMenuItem
|
|
287
|
+
v-for="passenger in passengers"
|
|
288
|
+
:key="passenger"
|
|
289
|
+
:is-selected="passenger === selectedPassenger"
|
|
290
|
+
:label="passenger"
|
|
291
|
+
@click="selectedPassenger = passenger"
|
|
292
|
+
/>
|
|
293
|
+
|
|
294
|
+
<CpBottomSheet v-model="isSeatVisible" @close="isSeatVisible = false">
|
|
295
|
+
<template #header><strong>Level 3 — Seat</strong></template>
|
|
296
|
+
<p>Third level. Dismiss it to fall back on level 2, still open underneath.</p>
|
|
297
|
+
<template #footer>
|
|
298
|
+
<CpButton @click="isSeatVisible = false">Confirm seat</CpButton>
|
|
299
|
+
</template>
|
|
300
|
+
</CpBottomSheet>
|
|
301
|
+
|
|
302
|
+
<template #footer>
|
|
303
|
+
<CpButton @click="isSeatVisible = true">Choose a seat</CpButton>
|
|
304
|
+
</template>
|
|
305
|
+
</CpBottomSheet>
|
|
306
|
+
|
|
307
|
+
<template #footer>
|
|
308
|
+
<CpButton @click="isPassengerVisible = true">Select passenger</CpButton>
|
|
309
|
+
</template>
|
|
310
|
+
</CpBottomSheet>
|
|
311
|
+
`,
|
|
312
|
+
}),
|
|
313
|
+
}
|
|
314
|
+
|
|
131
315
|
/**
|
|
132
316
|
* Disable swipe-to-close — the sheet can only be dismissed
|
|
133
317
|
* by tapping the backdrop or using a close action.
|
|
@@ -16,10 +16,6 @@ export default meta
|
|
|
16
16
|
|
|
17
17
|
type Story = StoryObj
|
|
18
18
|
|
|
19
|
-
/**
|
|
20
|
-
* Cubic-bezier curves used for the design-system transitions. Hover (or
|
|
21
|
-
* focus) any track to play the animation and compare curves side by side.
|
|
22
|
-
*/
|
|
23
19
|
export const Curves: Story = {
|
|
24
20
|
render: () => ({
|
|
25
21
|
setup() {
|