feat: the text of a picture's or a search's card folds and unfolds smoothly
This commit is contained in:
1 parent
dd1244a169
commit
dde85031aa
1 file changed
+26
-1
@@ -502,13 +502,38 @@
|
||||
c.classList.toggle('short', p.scrollWidth <= p.clientWidth + 1 && !/\n/.test(p.textContent));
|
||||
}));
|
||||
}
|
||||
// animateHeight: change() flips the card between folded and open; the
|
||||
// text's box grows or shrinks to its new height instead of jumping. The
|
||||
// text keeps its wrapped lines while it shrinks.
|
||||
function animateHeight(pre, change) {
|
||||
const h0 = pre.getBoundingClientRect().height;
|
||||
change();
|
||||
const still = document.body.classList.contains('no-motion') || matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
const h1 = pre.getBoundingClientRect().height;
|
||||
if (still || Math.abs(h1 - h0) < 1) return;
|
||||
const st = pre.style;
|
||||
st.boxSizing = 'border-box'; st.overflow = 'hidden'; st.whiteSpace = 'pre-wrap'; st.textOverflow = 'clip';
|
||||
st.height = h0 + 'px';
|
||||
pre.getBoundingClientRect(); // the start is drawn before the end is set
|
||||
st.transition = 'height .24s cubic-bezier(.3,.7,.3,1)';
|
||||
st.height = h1 + 'px';
|
||||
let t = 0;
|
||||
const done = () => {
|
||||
clearTimeout(t); pre.removeEventListener('transitionend', done);
|
||||
st.height = st.transition = st.overflow = st.whiteSpace = st.textOverflow = st.boxSizing = '';
|
||||
};
|
||||
pre.addEventListener('transitionend', done);
|
||||
t = setTimeout(done, 450);
|
||||
}
|
||||
const FOLD_CHEV = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="m9 6 6 6-6 6"/></svg>';
|
||||
list.addEventListener('click', ev => {
|
||||
const t = ev.target.closest('.foldable .ai-fold, .foldable pre');
|
||||
if (!t) return;
|
||||
const card = t.closest('.foldable');
|
||||
if (card.classList.contains('short') && !card.classList.contains('open')) return;
|
||||
const msg = card.closest('.ai-msg'), on = card.classList.toggle('open');
|
||||
const msg = card.closest('.ai-msg'), pre = card.querySelector('pre');
|
||||
let on = false;
|
||||
animateHeight(pre, () => { on = card.classList.toggle('open'); });
|
||||
const i = Number(card.dataset.n);
|
||||
(msg._open = msg._open || new Set())[on ? 'add' : 'delete'](i);
|
||||
const b = card.querySelector('.ai-fold');
|
||||
|
||||
Reference in new issue
Block a user