CollapseSet: Improve animation

Co-authored-by: Scott Nonnenberg <scott@signal.org>
Co-authored-by: Jamie Kyle <jamie@signal.org>
This commit is contained in:
automated-signal
2026-03-31 15:00:57 -05:00
committed by GitHub
parent 92a907b2e4
commit d2bede015a
2 changed files with 47 additions and 52 deletions

View File

@@ -5780,43 +5780,51 @@ button.module-calling-participants-list__contact {
}
.CollapseSet__height-container {
max-height: 0px;
overflow: hidden;
transition: max-height 200ms
linear(
0,
0.024 1.7%,
0.097 3.7%,
0.55 12%,
0.75 16.6%,
0.887 21.4%,
0.935 24%,
0.97 26.8%,
1.002 31.5%,
1.013 37.5%,
1.001 62.7%,
1
);
visibility: hidden;
pointer-events: none;
user-select: none;
height: 0px;
display: none;
/* stylelint-disable-next-line property-no-unknown */
interpolate-size: allow-keywords;
transition-property: display, height;
transition-behavior: allow-discrete;
transition-duration: 200ms;
transition-timing-function: linear(
0,
0.024 1.7%,
0.097 3.7%,
0.55 12%,
0.75 16.6%,
0.887 21.4%,
0.935 24%,
0.97 26.8%,
1.002 31.5%,
1.013 37.5%,
1.001 62.7%,
1
);
}
.CollapseSet__height-container--expanded {
visibility: visible;
pointer-events: auto;
user-select: auto;
display: block;
height: auto;
@starting-style {
height: 0;
}
}
.CollapseSet__transparency-container {
opacity: 0;
transition: opacity 120ms linear 200ms;
transition: opacity 25ms linear;
}
.CollapseSet__transparency-container--expanded {
opacity: 0;
transition: opacity 25ms;
transition-duration: 120ms;
transition-delay: 200ms;
opacity: 1;
@starting-style {
opacity: 0;
}
}
// Module: Last Seen Indicator

View File

@@ -61,6 +61,7 @@ export function CollapseSetViewer(props: Props): React.JSX.Element {
Record<string, CollapsedMessage>
>({});
const previousTargetedMessage = useRef<TargetedMessageType>(undefined);
const [isAnimating, setIsAnimating] = useState<boolean>(false);
useEffect(() => {
if (!targetedMessage) {
@@ -140,8 +141,6 @@ export function CollapseSetViewer(props: Props): React.JSX.Element {
!shouldShowButton ? 0 : oldestOriginallyUnseenIndex
);
const transparencyRef = React.useRef<HTMLDivElement>(null);
return (
<div>
{shouldShowButton ? (
@@ -152,6 +151,7 @@ export function CollapseSetViewer(props: Props): React.JSX.Element {
dayCount={collapsedDayCount}
isExpanded={isExpanded}
onClick={() => {
setIsAnimating(true);
setIsExpanded(value => !value);
}}
onDelete={() => {
@@ -168,34 +168,21 @@ export function CollapseSetViewer(props: Props): React.JSX.Element {
'CollapseSet__height-container',
isExpanded ? 'CollapseSet__height-container--expanded' : undefined
)}
style={{
maxHeight: isExpanded
? `${transparencyRef.current?.clientHeight ?? 5000}px`
: undefined,
onTransitionEnd={event => {
if (event.propertyName === 'height') {
setIsAnimating(false);
}
}}
>
<div
ref={transparencyRef}
onTransitionEnd={() => {
const expandedClass =
'CollapseSet__transparency-container--expanded';
const ref = transparencyRef.current;
if (!ref) {
return;
}
if (ref.classList.contains(expandedClass)) {
ref.classList.remove(expandedClass);
} else {
ref.classList.add(expandedClass);
}
}}
className={classNames('CollapseSet__transparency-container')}
style={{
opacity: isExpanded ? '1' : undefined,
}}
className={classNames(
'CollapseSet__transparency-container',
isExpanded
? 'CollapseSet__transparency-container--expanded'
: undefined
)}
>
{shouldShowButton ? (
{shouldShowButton && (isExpanded || isAnimating) ? (
<>
{collapsedMessages.map((child, index) => {
const previousMessage = messages[index - 1];