Enhance layout and components with improved accessibility and performance
- Refactor JavaScript functions to prevent duplicate initializations on navigation - Add skeleton loaders for invoices and services during loading states - Introduce a new progress bar component with customizable properties - Update dropdown and checkbox components for better styling and accessibility - Improve modal and navigation components with enhanced animations and structure
This commit is contained in:
@@ -1,8 +1,21 @@
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
document.querySelectorAll('img:not([loading])')
|
||||
.forEach(img => img.loading = 'lazy');
|
||||
});
|
||||
<script data-navigate-track>
|
||||
// Apply lazy loading to images - runs on initial load and Livewire navigation
|
||||
(function() {
|
||||
const applyLazyLoading = () => {
|
||||
document.querySelectorAll('img:not([loading])')
|
||||
.forEach(img => img.loading = 'lazy');
|
||||
};
|
||||
|
||||
// Run immediately if DOM is ready, otherwise wait
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', applyLazyLoading);
|
||||
} else {
|
||||
applyLazyLoading();
|
||||
}
|
||||
|
||||
// Also run on Livewire navigation
|
||||
document.addEventListener('livewire:navigated', applyLazyLoading);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -28,10 +41,17 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
</style>
|
||||
|
||||
<nav class="w-full px-4 lg:px-8 bg-background-secondary border-b border-neutral flex flex-col lg:flex-row justify-between fixed top-0 z-20 h-auto">
|
||||
<div x-data="{ slideOverOpen: false }"
|
||||
x-init="$watch('slideOverOpen', value => { document.documentElement.style.overflow = value ? 'hidden' : '' })"
|
||||
class="relative z-50 w-full h-auto">
|
||||
<nav x-data="{ scrolled: false, slideOverOpen: false }"
|
||||
x-init="
|
||||
window.addEventListener('scroll', () => { scrolled = window.scrollY > 20 });
|
||||
$watch('slideOverOpen', value => { document.documentElement.style.overflow = value ? 'hidden' : '' });
|
||||
"
|
||||
:class="{
|
||||
'shadow-lg shadow-black/10 border-neutral/80': scrolled,
|
||||
'border-neutral': !scrolled
|
||||
}"
|
||||
class="w-full px-4 lg:px-8 bg-background-secondary/95 backdrop-blur-md border-b flex flex-col lg:flex-row justify-between fixed top-0 z-20 h-auto transition-all duration-300">
|
||||
<div class="relative z-50 w-full h-auto">
|
||||
|
||||
<div class="flex flex-row items-center justify-between w-full h-16">
|
||||
|
||||
@@ -166,9 +186,34 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
<!-- Mobile slide-over menu (<1024px) -->
|
||||
<template x-teleport="body">
|
||||
<div x-show="slideOverOpen" @keydown.window.escape="slideOverOpen=false" x-cloak class="fixed left-0 right-0 top-20 w-full z-[99]" style="height:calc(100dvh - 5rem);" aria-modal="true">
|
||||
<div x-show="slideOverOpen" x-transition ... @click.away="slideOverOpen = false" class="absolute inset-0 bg-background-secondary/80 backdrop-blur-md border-t border-neutral/50 shadow-2xl overflow-y-auto flex flex-col rounded-t-2xl">
|
||||
<div x-show="slideOverOpen" @keydown.window.escape="slideOverOpen=false" x-cloak class="fixed inset-0 z-[99]" aria-modal="true">
|
||||
{{-- Backdrop with blur and fade --}}
|
||||
<div x-show="slideOverOpen"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="transition ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
@click="slideOverOpen = false"
|
||||
class="absolute inset-0 bg-black/40 backdrop-blur-sm"></div>
|
||||
|
||||
{{-- Slide-over panel --}}
|
||||
<div x-show="slideOverOpen"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0 translate-y-full"
|
||||
x-transition:enter-end="opacity-100 translate-y-0"
|
||||
x-transition:leave="transition ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100 translate-y-0"
|
||||
x-transition:leave-end="opacity-0 translate-y-full"
|
||||
@click.stop
|
||||
class="absolute left-0 right-0 top-16 bg-background-secondary/95 backdrop-blur-xl border-t border-neutral/50 shadow-2xl overflow-y-auto flex flex-col rounded-t-3xl"
|
||||
style="height:calc(100dvh - 4rem);">
|
||||
<div class="flex flex-col h-full p-6">
|
||||
{{-- Swipe handle indicator --}}
|
||||
<div class="flex justify-center mb-4">
|
||||
<div class="w-12 h-1.5 bg-neutral/50 rounded-full"></div>
|
||||
</div>
|
||||
<div class="flex-1 min-h-0 overflow-y-auto">
|
||||
<x-navigation.sidebar-links />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user