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:
2026-02-01 12:31:43 -05:00
parent 10c978eae9
commit f7766b6d67
14 changed files with 470 additions and 172 deletions

View File

@@ -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>