Skip to content

Commit

Permalink
1.2.6 (#15)
Browse files Browse the repository at this point in the history
* streamline auto duration handling and raf watcher calls

* update readme

* bump deps, release 1.2.6

update readme shields
  • Loading branch information
smastrom committed Aug 4, 2023
1 parent 9820505 commit a7cf517
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 86 deletions.
44 changes: 14 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
![npm](https://img.shields.io/npm/v/vue-collapsed?color=46c119) ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/smastrom/vue-collapsed/tests.yml?branch=main&label=tests) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/vue-collapsed?color=success)
![dependency-count](https://img.shields.io/badge/dependency%20count-0-success)
![npm](https://img.shields.io/npm/v/vue-collapsed?color=46c119) ![dependencies](https://img.shields.io/badge/dependencies-0-success) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/vue-collapsed?color=success) ![downloads](https://img.shields.io/npm/dm/vue-collapsed) ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/smastrom/vue-collapsed/tests.yml?branch=main&label=tests)

# Vue Collapsed

Expand Down Expand Up @@ -126,6 +125,18 @@ To transition other properties use the attribute `data-collapse`:
}
```

Or to use different easings/durations for expand and collapse:

```css
.v-collapse[data-collapse='expanding'] {
transition: height 600ms ease-in-out;
}

.v-collapse[data-collapse='collapsing'] {
transition: height 300ms ease-out;
}
```

Above values can also be accessed using `v-slot`:

```vue
Expand Down Expand Up @@ -188,33 +199,6 @@ function handleAccordion(selectedIndex) {
</template>
```

## Example - Callbacks

```vue
<script setup>
// ...
const sectionsRef = ref([])
function scrollIntoView(index) {
sectionsRef.value[index].scrollIntoView({ behavior: 'smooth' })
}
</script>
<template>
<div v-for="(question, index) in questions" :key="question.title" ref="sectionsRef">
<button @click="handleAccordion(index)">
{{ question.title }}
</button>
<Collapse :when="questions[index].isExpanded" @expanded="() => scrollIntoView(index)">
<p>
{{ question.answer }}
</p>
</Collapse>
</div>
</template>
```

## Accessibility

`vue-collapsed` automatically detects if users prefer reduced motion and will disable transitions accordingly while keeping the same API behavior (emitting events and post-transition styles).
Expand Down Expand Up @@ -255,7 +239,7 @@ function handleCollapse() {
</template>
```

## Manually disable transitions
## Manually disabling transitions

```vue
<template>
Expand Down
1 change: 0 additions & 1 deletion demo/NestedCollapse.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ const nested = reactive({
first: true, // Initial value
second: false,
third: false,
fourth: false,
})
const innerText = `
Expand Down
13 changes: 10 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vue-collapsed",
"version": "1.2.5",
"version": "1.2.6",
"private": false,
"description": "Dynamic CSS height transition from any to auto and vice versa for Vue 3. Accordion ready.",
"keywords": [
Expand Down Expand Up @@ -28,6 +28,13 @@
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"files": [
"dist/*"
],
Expand All @@ -51,15 +58,15 @@
"@rollup/plugin-terser": "^0.4.3",
"@types/node": "^18.17.1",
"@vitejs/plugin-vue": "^4.2.3",
"cypress": "^12.17.2",
"cypress": "^12.17.3",
"cypress-wait-frames": "^0.9.4",
"husky": "^8.0.3",
"lint-staged": "^13.2.3",
"playwright-webkit": "^1.36.2",
"prettier": "^2.8.8",
"rimraf": "^4.4.1",
"typescript": "^4.9.5",
"vite": "^4.4.7",
"vite": "^4.4.8",
"vite-plugin-dts": "^1.7.3",
"vue": "^3.3.4",
"vue-tsc": "^1.8.8"
Expand Down
89 changes: 38 additions & 51 deletions src/Collapse.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ import {
type CSSProperties as CSS,
} from 'vue'
import { SAFE_STYLES as safeStyles, AUTO_DUR_VAR } from './constants'
import { SAFE_STYLES as safeStyles, VISUALLY_HIDDEN, AUTO_DUR_VAR } from './constants'
import { getTransition, getHeight, getAutoDuration, isReducedOrDisaled } from './utils'
type TransitionState = 'expanding' | 'expanded' | 'collapsing' | 'collapsed'
export type TransitionState = 'expanding' | 'expanded' | 'collapsing' | 'collapsed'
const props = withDefaults(
defineProps<{
Expand Down Expand Up @@ -61,19 +61,11 @@ const collapsedStyles = computed(() => ({
const collapseRef = ref<HTMLElement | null>(null)
const state = ref<TransitionState>(isExpanded.value ? 'expanded' : 'collapsed')
const style = shallowRef<CSS>(isExpanded.value ? safeStyles : collapsedStyles.value)
const style = shallowRef<CSS>({})
const autoDuration = ref(0)
const autoDuration = ref(300)
const autoDurationVar = computed(() => ({ [AUTO_DUR_VAR]: `${autoDuration.value}ms` }))
function setAutoDuration() {
if (!collapseRef.value) return
if (isExpanded.value || baseHeight.value > 0) {
autoDuration.value = getAutoDuration(collapseRef.value.scrollHeight - baseHeight.value)
}
}
function onExpanded() {
style.value = safeStyles
state.value = 'expanded'
Expand All @@ -88,7 +80,13 @@ function onCollapsed() {
// Lifecycle / Watchers
onMounted(setAutoDuration)
onMounted(() => {
if (!collapseRef.value) return
if (!isExpanded.value && baseHeight.value === 0) style.value = VISUALLY_HIDDEN
autoDuration.value = getAutoDuration(collapseRef.value.scrollHeight - baseHeight.value)
style.value = isExpanded.value ? safeStyles : collapsedStyles.value
})
watch(isExpanded, (isExpanding) => {
if (isExpanding) {
Expand All @@ -104,28 +102,23 @@ watch(isExpanded, (isExpanding) => {
* We set the height to baseHeight as it is the 'current' height
* we are transitioning from.
*/
state.value = 'expanding'
emit('expand')
style.value = {
...safeStyles,
...baseHeightStyles.value,
...autoDurationVar.value,
willChange: 'height',
}
requestAnimationFrame(() => {
/** Get auto duration in once scrollHeight is available. */
setAutoDuration()
style.value = { ...style.value, ...autoDurationVar.value }
requestAnimationFrame(() => {
/** Set height to scrollHeight and trigger the transition. */
style.value = {
...style.value,
...getHeight(collapseRef.value),
...getTransition(collapseRef.value),
}
state.value = 'expanding'
emit('expand')
})
/** Set height to scrollHeight and trigger the transition. */
style.value = {
...style.value,
...getHeight(collapseRef.value),
...getTransition(collapseRef.value),
}
})
} else {
if (isReducedOrDisaled(collapseRef.value)) return onCollapsed()
Expand All @@ -136,31 +129,24 @@ watch(isExpanded, (isExpanding) => {
*
* Since the element is visible we get the 'current'
* expanded height (scrollHeight) and set it as height.
*
* We could use only one raf call, but we must use the
* same number of raf calls of the previous condition (2) to make
* sure accordion transitions (collapse/expand at the same time)
* are perfectly in sync.
*/
state.value = 'collapsing'
emit('collapse')
style.value = {
...style.value,
...autoDurationVar.value,
...getHeight(collapseRef.value),
willChange: 'height',
}
requestAnimationFrame(() => {
/** Set height to baseHeight and trigger the transition. */
style.value = {
...style.value,
...autoDurationVar.value,
...getHeight(collapseRef.value),
willChange: 'height',
...baseHeightStyles.value,
...getTransition(collapseRef.value),
}
requestAnimationFrame(() => {
/** Set height to baseHeight and trigger the transition. */
style.value = {
...style.value,
...baseHeightStyles.value,
...getTransition(collapseRef.value),
}
state.value = 'collapsing'
emit('collapse')
})
})
}
})
Expand All @@ -175,13 +161,14 @@ watch(baseHeight, (newBaseHeight) => {
*
* Below styles are going to be replaced on next expand.
*/
transitionDuration: '0s',
height: `${newBaseHeight}px`,
...(newBaseHeight === 0
? { display: 'none' }
: { transition: 'none', height: `${newBaseHeight}px` }),
}
}
})
// Callbacks
// Event handlers
function onTransitionEnd(event: TransitionEvent) {
if (event.target === collapseRef.value && event.propertyName === 'height') {
Expand Down
14 changes: 13 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,16 @@ export const AUTO_DUR_VAR = '--vc-auto-duration'

export const DEFAULT_TRANSITION = `height var(${AUTO_DUR_VAR}) cubic-bezier(0.33, 1, 0.68, 1)`

export const SAFE_STYLES = { padding: 0, border: 0, margin: 0 } as const
export const SAFE_STYLES = { padding: 0 } as const

export const VISUALLY_HIDDEN = {
position: 'absolute',
width: '1px',
height: '1px',
padding: '0',
margin: '-1px',
overflow: 'hidden',
clip: 'rect(0, 0, 0, 0)',
whiteSpace: 'nowrap',
border: '0',
} as const

0 comments on commit a7cf517

Please sign in to comment.