Improve animation
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
committed by
Patrik Oldsberg
parent
4c3dfa1c1e
commit
2aec9470cc
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user