Files
michaelschiemer/resources/js/modules/admin/view-transitions.js
2025-11-24 21:28:25 +01:00

138 lines
3.3 KiB
JavaScript

/**
* View Transitions Helper - Admin Interface
*
* Helper-Funktionen für View Transitions API.
* Baseline 2023: View Transitions API ist Baseline Newly available.
*/
/**
* Check if View Transitions are supported
*/
export function supportsViewTransitions() {
return 'startViewTransition' in document;
}
/**
* Start View Transition for Admin Navigation
*/
export function transitionNavigation(callback) {
if (!supportsViewTransitions()) {
callback();
return;
}
document.startViewTransition(() => {
callback();
});
}
/**
* Start View Transition for Admin Content Updates
*/
export function transitionContentUpdate(callback) {
if (!supportsViewTransitions()) {
callback();
return;
}
const transition = document.startViewTransition(() => {
callback();
});
return transition;
}
/**
* Start View Transition for Popover
*/
export function transitionPopover(popoverElement, callback) {
if (!supportsViewTransitions()) {
callback();
return;
}
// Set view-transition-name for this specific popover
const originalName = popoverElement.style.viewTransitionName;
popoverElement.style.viewTransitionName = `admin-popover-${popoverElement.id}`;
const transition = document.startViewTransition(() => {
callback();
});
transition.finished.finally(() => {
// Restore original name
if (originalName) {
popoverElement.style.viewTransitionName = originalName;
} else {
popoverElement.style.viewTransitionName = '';
}
});
return transition;
}
/**
* Initialize View Transitions for Admin Navigation Links
*/
export function initAdminNavigationTransitions() {
if (!supportsViewTransitions()) {
return;
}
// Handle navigation links
document.querySelectorAll('.admin-nav a[href]').forEach(link => {
link.addEventListener('click', (e) => {
const href = link.getAttribute('href');
// Only handle internal links
if (href && !href.startsWith('http') && !href.startsWith('#')) {
e.preventDefault();
transitionNavigation(() => {
window.location.href = href;
});
}
});
});
}
/**
* Initialize View Transitions for Popover Toggles
*/
export function initPopoverTransitions() {
if (!supportsViewTransitions()) {
return;
}
document.querySelectorAll('[popovertarget]').forEach(trigger => {
const popoverId = trigger.getAttribute('popovertarget');
const popover = document.getElementById(popoverId);
if (popover) {
popover.addEventListener('toggle', (e) => {
const isOpen = popover.matches(':popover-open');
transitionPopover(popover, () => {
// Transition is handled by browser
});
});
}
});
}
/**
* Initialize all View Transitions
*/
export function initViewTransitions() {
initAdminNavigationTransitions();
initPopoverTransitions();
}
// Auto-initialize if DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initViewTransitions);
} else {
initViewTransitions();
}