Skip to content

Commit

Permalink
1.3.4 (#30)
Browse files Browse the repository at this point in the history
* trigger a new transition if children height changed while expanding

* suppress some demo prop warning

* Fix #31 - Update default transition value since Chromium 128

* Tests - Update to match Chrome v128 default transition computation

* Pkg - Bump v1.3.4

* Core - Improve comment
  • Loading branch information
smastrom authored Aug 5, 2024
1 parent 5f3d783 commit 51502dc
Show file tree
Hide file tree
Showing 8 changed files with 35 additions and 34 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ dist
/cypress/screenshots/
.vscode/*
!.vscode/extensions.json
.idea
*.tgz
2 changes: 1 addition & 1 deletion packages/vue-collapsed/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vue-collapsed",
"version": "1.3.3",
"version": "1.3.4",
"private": false,
"description": "Dynamic CSS height transition from any to auto and vice versa for Vue 3. Accordion ready.",
"keywords": [
Expand Down
34 changes: 25 additions & 9 deletions packages/vue-collapsed/src/Collapse.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,7 @@ import {
} from 'vue'
import { SAFE_STYLES, VISUALLY_HIDDEN, AUTO_DUR_VAR, FALLBACK_DURATION } from './constants'
import {
getTransitionProp,
getComputedHeight,
getHeightProp,
getAutoDuration,
isReducedOrDisabled,
} from './utils'
import { getTransitionProp, getComputedHeight, getAutoDuration, isReducedOrDisabled } from './utils'
export type TransitionState = 'expanding' | 'expanded' | 'collapsing' | 'collapsed'
Expand Down Expand Up @@ -104,6 +98,15 @@ const setAutoDuration = (newDuration: number) => (autoDuration.value = newDurati
const autoDurationVar = computed(() => ({ [AUTO_DUR_VAR]: `${autoDuration.value}ms` }))
/**
* In some edge cases, Collapse may have children elements that also expand
* their height while expanding.
*
* When this occurs, the 'scrollHeight' obtained on transition start will be lower than
* the same 'scrollHeight' obtained on transition end.
*/
let transitionStartScrollHeight = NaN
function onExpanded() {
replaceStyles(SAFE_STYLES)
setState('expanded')
Expand Down Expand Up @@ -139,6 +142,8 @@ onMounted(() => {
watch(isExpanded, (isExpanding) => {
if (!collapseRef.value) return
transitionStartScrollHeight = NaN
if (isExpanding) {
if (isReducedOrDisabled(collapseRef)) return onExpanded()
Expand Down Expand Up @@ -168,9 +173,11 @@ watch(isExpanded, (isExpanding) => {
/** Set height to scrollHeight and trigger the transition. */
transitionStartScrollHeight = collapseRef.value!.scrollHeight
addStyles({
...getHeightProp(collapseRef),
...getTransitionProp(collapseRef),
height: `${transitionStartScrollHeight}px`,
willChange: 'height',
})
})
Expand All @@ -189,7 +196,7 @@ watch(isExpanded, (isExpanding) => {
addStyles({
...autoDurationVar.value,
...getHeightProp(collapseRef),
height: `${collapseRef.value!.scrollHeight}px`,
})
/** Same as for expand, abort transition and force collapse */
Expand Down Expand Up @@ -230,6 +237,15 @@ function onTransitionEnd(e: TransitionEvent) {
if (isExpanded.value) {
if (Math.abs(collapseRef.value.scrollHeight - getComputedHeight(collapseRef)) < 1) {
onExpanded()
} else if (transitionStartScrollHeight < collapseRef.value.scrollHeight) {
/**
* A child element expanded its height while Collapse
* is transitioning, update the height and trigger
* the transition again.
*/
addStyles({
height: `${collapseRef.value.scrollHeight}px`,
})
}
} else {
if (Math.abs(baseHeight.value - getComputedHeight(collapseRef)) < 1) {
Expand Down
17 changes: 3 additions & 14 deletions packages/vue-collapsed/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,21 @@ import type { Ref } from 'vue'

type RefEl = Ref<HTMLElement | null>

const isFirefox = () => typeof navigator !== 'undefined' && navigator.userAgent.includes('Firefox')

export function getComputedHeight(el: RefEl) {
if (!el.value) return 0
return parseFloat(getComputedStyle(el.value).height)
}

export function getHeightProp(el: RefEl) {
return {
height: `${el.value?.scrollHeight || 0}px`,
}
}

export function getTransitionProp(el: RefEl) {
if (!el.value) return {}

const { transition } = getComputedStyle(el.value)

// If transition is not defined via CSS, return the default one referencing the auto duration
if (
transition === 'all 0s ease 0s' ||
(isFirefox() &&
transition ===
'all') /* Since Firefox v124, Gecko returns transition 'all' instead of 'all 0s ease 0s' */
)
if (transition === 'all 0s ease 0s' || transition === 'all') {
/* Since Firefox v124 and Chromium v128, their rendering engines compute 'all' instead of 'all 0s ease 0s' as default transition */
return { transition: DEFAULT_TRANSITION }
}

return { transition }
}
Expand Down
9 changes: 2 additions & 7 deletions packages/vue-collapsed/tests/Collapse.cy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import App from './App.vue'

import { getRandomIntInclusive, isFirefox } from '../cypress/support/component'

describe('Collapse', () => {
Expand Down Expand Up @@ -275,13 +276,7 @@ describe('Collapse', () => {

const transition = 'height 0.3s cubic-bezier(0.33, 1, 0.68, 1)'

cy.get('#Collapse').should(
'have.css',
'transition',
isFirefox
? transition // Firefox >= 124 doesn't include '0s' by default anymore
: `${transition} 0s`
)
cy.get('#Collapse').should('have.css', 'transition', transition)

cy.get('#Collapse').and('have.attr', 'style').and('include', '--vc-auto-duration: 300ms')
})
Expand Down
2 changes: 1 addition & 1 deletion playground/components/AdvancedControl.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Collapse } from 'vue-collapsed'
// Used for demo purposes only...
const props = withDefaults(
defineProps<{
initialState: boolean
initialState?: boolean
}>(),
{ initialState: true }
)
Expand Down
2 changes: 1 addition & 1 deletion playground/components/DisplayHide.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Collapse } from 'vue-collapsed'
const props = withDefaults(
defineProps<{
initialState: boolean
initialState?: boolean
}>(),
{ initialState: true }
)
Expand Down
2 changes: 1 addition & 1 deletion playground/components/MountUnmount.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Collapse } from 'vue-collapsed'
const props = withDefaults(
defineProps<{
initialState: boolean
initialState?: boolean
}>(),
{ initialState: true }
)
Expand Down

0 comments on commit 51502dc

Please sign in to comment.