Improve animation

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
Charles de Dreuille
2026-02-03 16:22:23 +00:00
committed by Patrik Oldsberg
parent 4c3dfa1c1e
commit 2aec9470cc
3 changed files with 23 additions and 21 deletions
@@ -74,7 +74,7 @@
box-shadow: 0 4px 12px -2px rgba(0 0 0 / 0.4);
/* Animation */
transition: transform 6s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 6s ease;
transition: transform 3s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 3s ease;
/* View Transitions - name is set dynamically via inline style, class groups them */
view-transition-class: toast;
@@ -244,19 +244,12 @@
}
}
/* Apply animations to view transition pseudo-elements */
/* Debug: using wildcard to test if view transitions work at all */
::view-transition-old(*) {
animation: bui-toast-exit 6s ease-out forwards;
/* Apply exit animation only to the closing toast */
::view-transition-old(toast-exit) {
animation: bui-toast-exit 3s ease-out forwards;
}
::view-transition-new(*) {
animation: none;
}
/* Don't animate the root snapshot */
::view-transition-old(root),
::view-transition-new(root) {
::view-transition-new(toast-exit) {
animation: none;
}
@@ -266,8 +259,7 @@
transition: none;
}
::view-transition-old(*),
::view-transition-new(*) {
::view-transition-old(toast-exit) {
animation: none !important;
}
}
+1 -1
View File
@@ -143,10 +143,10 @@ export const Toast = forwardRef(
style={
{
'--toast-index': index,
viewTransitionName: `toast-${toast.key}`,
} as React.CSSProperties
}
{...dataAttributes}
data-toast-key={toast.key}
data-status={finalStatus}
data-starting-style={isStarting ? '' : undefined}
{...restProps}
+16 -6
View File
@@ -45,21 +45,27 @@ import type { ToastContent } from './types';
*
* @public
*/
// Track if we should use view transition (only for removals)
let useViewTransition = false;
// Track which toast element is being closed for view transition
let closingToastElement: HTMLElement | null = null;
export const toastQueue = new RAToastQueue<ToastContent>({
maxVisibleToasts: 5,
// Wrap state updates in a CSS view transition for smooth animations
wrapUpdate(fn) {
if (useViewTransition && 'startViewTransition' in document) {
useViewTransition = false; // Reset flag
if (closingToastElement && 'startViewTransition' in document) {
// Set view-transition-name on the element BEFORE capturing old state
closingToastElement.style.viewTransitionName = 'toast-exit';
const element = closingToastElement;
closingToastElement = null;
(
document as Document & {
startViewTransition: (cb: () => void) => void;
}
).startViewTransition(() => {
flushSync(fn);
// Clean up (element may be removed, but just in case)
element.style.viewTransitionName = '';
});
} else {
fn();
@@ -67,9 +73,13 @@ export const toastQueue = new RAToastQueue<ToastContent>({
},
});
// Override close to enable view transition
// Override close to capture the toast element before transition
const originalClose = toastQueue.close.bind(toastQueue);
toastQueue.close = (key: string) => {
useViewTransition = true;
// Find the toast element by our custom data attribute
const toastElement = document.querySelector(
`[data-toast-key="${key}"]`,
) as HTMLElement | null;
closingToastElement = toastElement;
originalClose(key);
};