🐞 fix: Animate team-grid bio with JS measuring natural height
This commit is contained in:
Vendored
+2017
-3175
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@
|
||||
|
||||
&:hover {
|
||||
.team-grid__read-bio::after {
|
||||
content: url("data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20transform%3D%22rotate(0%200%200)%22%3E%3Cpath%20d%3D%22M6.28033%2010.5947C5.98744%2010.3018%205.51256%2010.3018%205.21967%2010.5947C4.92678%2010.8876%204.92678%2011.3624%205.21967%2011.6553L11.4697%2017.9053C11.7626%2018.1982%2012.2374%2018.1982%2012.5303%2017.9053L18.7803%2011.6553C19.0732%2011.3624%2019.0732%2010.8876%2018.7803%2010.5947C18.4874%2010.3018%2018.0126%2010.3018%2017.7197%2010.5947L12%2016.3143L6.28033%2010.5947Z%22%20fill%3D%22%23006196%22%2F%3E%3Cpath%20opacity%3D%221%22%20d%3D%22M6.28033%206.09467C5.98744%205.80178%205.51256%205.80178%205.21967%206.09467C4.92678%206.38756%204.92678%206.86244%205.21967%207.15533L11.4697%2013.4053C11.7626%2013.6982%2012.2374%2013.6982%2012.5303%2013.4053L18.7803%207.15533C19.0732%206.86244%2019.0732%206.38756%2018.7803%206.09467C18.4874%205.80178%2018.0126%205.80178%2017.7197%206.09467L12%2011.8143L6.28033%206.09467Z%22%20fill%3D%22%23006196%22%2F%3E%3C%2Fsvg%3E");
|
||||
content: url("data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20transform%3D%22rotate(0%200%200)%22%3E%3Cpath%20d%3D%22M6.28033%2010.5947C5.98744%2010.3018%205.51256%2010.3018%205.21967%2010.5947C4.92678%2010.8876%204.92678%2011.3624%205.21967%2011.6553L11.4697%2017.9053C11.7626%2018.1982%2012.2374%2018.1982%2012.5303%2017.9053L18.7803%2011.6553C19.0732%2011.3624%2019.0732%2010.8876%2018.7803%2010.5947C18.4874%2010.3018%2018.0126%2010.3018%2017.7197%2010.5947L12%2016.3143L6.28033%2010.5947Z%22%20fill%3D%22%23006196%22%2F%3E%3Cpath%20opacity%3D%221%22%20d%3D%22M6.28033%206.09467C5.98744%205.80178%205.51256%205.80178%205.21967%206.09467C4.92678%206.38756%204.92678%206.86244%205.21967%207.15533L11.4697%2013.4053C11.7626%2013.6982%2012.2374%2018.1982%2012.5303%2013.4053L18.7803%207.15533C19.0732%206.86244%2019.0732%206.38756%2018.7803%206.09467C18.4874%205.80178%2018.0126%205.80178%2017.7197%206.09467L12%2011.8143L6.28033%206.09467Z%22%20fill%3D%22%23006196%22%2F%3E%3C%2Fsvg%3E");
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
}
|
||||
@@ -42,28 +42,25 @@
|
||||
|
||||
.team-grid__read-bio {
|
||||
@apply flex gap-2 justify-center items-center text-cwc-blue-01 text-16px font-bold leading-snug mb-1;
|
||||
transition: transform 300ms ease;
|
||||
|
||||
&::after {
|
||||
content: url("data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20transform%3D%22rotate(0%200%200)%22%3E%3Cpath%20d%3D%22M6.28033%2010.5947C5.98744%2010.3018%205.51256%2010.3018%205.21967%2010.5947C4.92678%2010.8876%204.92678%2011.3624%205.21967%2011.6553L11.4697%2017.9053C11.7626%2018.1982%2012.2374%2018.1982%2012.5303%2017.9053L18.7803%2011.6553C19.0732%2011.3624%2019.0732%2010.8876%2018.7803%2010.5947C18.4874%2010.3018%2018.0126%2010.3018%2017.7197%2010.5947L12%2016.3143L6.28033%2010.5947Z%22%20fill%3D%22%23006196%22%2F%3E%3Cpath%20opacity%3D%220.5%22%20d%3D%22M6.28033%206.09467C5.98744%205.80178%205.51256%205.80178%205.21967%206.09467C4.92678%206.38756%204.92678%206.86244%205.21967%207.15533L11.4697%2013.4053C11.7626%2013.6982%2012.2374%2013.6982%2012.5303%2013.4053L18.7803%207.15533C19.0732%206.86244%2019.0732%206.38756%2018.7803%206.09467C18.4874%205.80178%2018.0126%205.80178%2017.7197%206.09467L12%2011.8143L6.28033%206.09467Z%22%20fill%3D%22%23006196%22%2F%3E%3C%2Fsvg%3E");
|
||||
content: url("data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20transform%3D%22rotate(0%200%200)%22%3E%3Cpath%20d%3D%22M6.28033%2010.5947C5.98744%2010.3018%205.51256%2010.3018%205.21967%2010.5947C4.92678%2010.8876%204.92678%2011.3624%205.21967%2011.6553L11.4697%2017.9053C11.7626%2018.1982%2012.2374%2018.1982%2012.5303%2017.9053L18.7803%2011.6553C19.0732%2011.3624%2019.0732%2010.8876%2018.7803%2010.5947C18.4874%2010.3018%2018.0126%2010.3018%2017.7197%2010.5947L12%2016.3143L6.28033%2010.5947Z%22%20fill%3D%22%23006196%22%2F%3E%3Cpath%20opacity%3D%220.5%22%20d%3D%22M6.28033%206.09467C5.98744%205.80178%205.51256%205.80178%205.21967%206.09467C4.92678%206.38756%204.92678%206.86244%205.21967%207.15533L11.4697%2013.4053C11.7626%2013.6982%2012.2374%2018.1982%2012.5303%2013.4053L18.7803%207.15533C19.0732%206.86244%2019.0732%206.38756%2018.7803%206.09467C18.4874%205.80178%2018.0126%205.80178%2017.7197%206.09467L12%2011.8143L6.28033%206.09467Z%22%20fill%3D%22%23006196%22%2F%3E%3C%2Fsvg%3E");
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
transition: transform 300ms ease;
|
||||
}
|
||||
}
|
||||
|
||||
.team-grid__details[open] .team-grid__read-bio::after {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.team-grid__bio-wrap {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
transition: max-height 300ms ease;
|
||||
}
|
||||
|
||||
.team-grid__details[open] {
|
||||
.team-grid__bio-wrap { max-height: 1000px; }
|
||||
|
||||
.team-grid__read-bio::after {
|
||||
content: url("data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20transform%3D%22rotate(0%200%200)%22%3E%3Cpath%20d%3D%22M6.28033%2010.5947C5.98744%2010.3018%205.51256%2010.3018%205.21967%2010.5947C4.92678%2010.8876%204.92678%2011.3624%205.21967%2011.6553L11.4697%2017.9053C11.7626%2018.1982%2012.2374%2018.1982%2012.5303%2017.9053L18.7803%2011.6553C19.0732%2011.3624%2019.0732%2010.8876%2018.7803%2010.5947C18.4874%2010.3018%2018.0126%2010.3018%2017.7197%2010.5947L12%2016.3143L6.28033%2010.5947Z%22%20fill%3D%22%23006196%22%2F%3E%3Cpath%20opacity%3D%221%22%20d%3D%22M6.28033%206.09467C5.98744%205.80178%205.51256%205.80178%205.21967%206.09467C4.92678%206.38756%204.92678%206.86244%205.21967%207.15533L11.4697%2013.4053C11.7626%2013.6982%2012.2374%2013.6982%2012.5303%2013.4053L18.7803%207.15533C19.0732%206.86244%2019.0732%206.38756%2018.7803%206.09467C18.4874%205.80178%2018.0126%205.80178%2017.7197%206.09467L12%2011.8143L6.28033%206.09467Z%22%20fill%3D%22%23006196%22%2F%3E%3C%2Fsvg%3E");
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
.team-grid__bio { @apply text-16px font-light leading-snug pt-2 text-center text-balance; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Team Grid block — bio expand/collapse animation.
|
||||
*
|
||||
* Native <details>/<summary> handles the toggle, but CSS transitions on
|
||||
* max-height need a concrete target value to animate to. This module
|
||||
* measures each bio's natural height on open and animates max-height
|
||||
* from current → measured (open) or current → 0 (close) so the
|
||||
* transition fires in both directions.
|
||||
*
|
||||
* The module is enqueued per-block by the team-grid PHP template. It
|
||||
* auto-initializes on import: queries the DOM for any existing
|
||||
* .team-grid__details elements and attaches a toggle handler to each.
|
||||
*/
|
||||
|
||||
const DETAILS_SELECTOR = '.team-grid__details';
|
||||
const BIO_WRAP_SELECTOR = '.team-grid__bio-wrap';
|
||||
|
||||
const setMaxHeight = (el, value) => {
|
||||
el.style.maxHeight = typeof value === 'number' ? `${value}px` : value;
|
||||
};
|
||||
|
||||
const measureBioHeight = (bioWrap) => {
|
||||
// Temporarily allow the inner content to render at its natural size so
|
||||
// scrollHeight reports the real height rather than the clipped height.
|
||||
const previousMax = bioWrap.style.maxHeight;
|
||||
const previousOverflow = bioWrap.style.overflow;
|
||||
|
||||
setMaxHeight(bioWrap, 'none');
|
||||
bioWrap.style.overflow = 'visible';
|
||||
|
||||
const height = bioWrap.scrollHeight;
|
||||
|
||||
bioWrap.style.overflow = previousOverflow;
|
||||
setMaxHeight(bioWrap, previousMax || '');
|
||||
|
||||
return height;
|
||||
};
|
||||
|
||||
const animateOpen = (bioWrap) => {
|
||||
const target = measureBioHeight(bioWrap);
|
||||
|
||||
setMaxHeight(bioWrap, '0px');
|
||||
|
||||
// Force a reflow so the browser registers the starting value before
|
||||
// we change it to the target — otherwise the transition is skipped.
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
bioWrap.offsetHeight;
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
setMaxHeight(bioWrap, `${target}px`);
|
||||
});
|
||||
|
||||
// After the transition completes, set max-height back to 'none' so
|
||||
// dynamic content (e.g. images loading late) can grow the bio
|
||||
// without being clipped.
|
||||
const onEnd = (event) => {
|
||||
if (event.propertyName !== 'max-height' || event.target !== bioWrap) {
|
||||
return;
|
||||
}
|
||||
bioWrap.removeEventListener('transitionend', onEnd);
|
||||
setMaxHeight(bioWrap, 'none');
|
||||
};
|
||||
bioWrap.addEventListener('transitionend', onEnd);
|
||||
};
|
||||
|
||||
const animateClose = (bioWrap) => {
|
||||
// Capture the current rendered height so the browser has a concrete
|
||||
// starting value for the transition. Without this, going from
|
||||
// 'none' to '0px' snaps instead of animating.
|
||||
const current = bioWrap.getBoundingClientRect().height;
|
||||
|
||||
setMaxHeight(bioWrap, `${current}px`);
|
||||
|
||||
// Force a reflow so the browser registers the starting value.
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
bioWrap.offsetHeight;
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
setMaxHeight(bioWrap, '0px');
|
||||
});
|
||||
};
|
||||
|
||||
const attach = (details) => {
|
||||
if (details.dataset.teamGridBound === 'true') {
|
||||
return;
|
||||
}
|
||||
details.dataset.teamGridBound = 'true';
|
||||
|
||||
const bioWrap = details.querySelector(BIO_WRAP_SELECTOR);
|
||||
|
||||
if (!bioWrap) {
|
||||
return;
|
||||
}
|
||||
|
||||
details.addEventListener('toggle', () => {
|
||||
if (details.open) {
|
||||
animateOpen(bioWrap);
|
||||
} else {
|
||||
animateClose(bioWrap);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const init = () => {
|
||||
document.querySelectorAll(DETAILS_SELECTOR).forEach(attach);
|
||||
};
|
||||
|
||||
init();
|
||||
@@ -17,6 +17,17 @@ if ( empty( $members ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Enqueue the per-block JS only when this block actually renders.
|
||||
$js_path = '/views/blocks/team-grid/team-grid.js';
|
||||
if ( file_exists( get_stylesheet_directory() . $js_path ) ) {
|
||||
wp_enqueue_script_module(
|
||||
'cwc-team-grid',
|
||||
get_stylesheet_directory_uri() . $js_path,
|
||||
array(),
|
||||
(string) filemtime( get_stylesheet_directory() . $js_path )
|
||||
);
|
||||
}
|
||||
|
||||
$modeSingle = '';
|
||||
|
||||
$blockID = wp_unique_id( 'single-' );
|
||||
|
||||
Reference in New Issue
Block a user