Enhance UI components with visual polish, including hover animations and improved skeleton loaders for better user experience
This commit is contained in:
@@ -2085,6 +2085,32 @@ img {
|
||||
box-shadow: 0 0 20px hsl(var(--color-primary) / 0.4);
|
||||
}
|
||||
|
||||
/* =============================================================================
|
||||
VISUAL POLISH ENHANCEMENTS
|
||||
============================================================================= */
|
||||
|
||||
/* Card arrow hover animation - slides right on hover */
|
||||
.card-arrow-animate {
|
||||
transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1),
|
||||
color 0.15s ease;
|
||||
}
|
||||
|
||||
.group:hover .card-arrow-animate,
|
||||
a:hover .card-arrow-animate {
|
||||
transform: translateX(4px);
|
||||
color: hsl(var(--color-primary));
|
||||
}
|
||||
|
||||
/* Status card hover enhancement - subtle lift and glow */
|
||||
.status-card-hover {
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.status-card-hover:hover {
|
||||
transform: scale(1.02);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
/* Sidebar active indicator bar */
|
||||
.nav-active-bar {
|
||||
position: relative;
|
||||
@@ -2113,6 +2139,8 @@ img {
|
||||
.ripple::after,
|
||||
.interactive-lift,
|
||||
.form-error-shake,
|
||||
.card-arrow-animate,
|
||||
.status-card-hover,
|
||||
[wire\:navigate],
|
||||
::view-transition-old(page),
|
||||
::view-transition-new(page) {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
})">
|
||||
|
||||
<button
|
||||
class="flex flex-row items-center px-2 py-1 text-sm font-semibold whitespace-nowrap text-base hover:text-primary transition-colors duration-200"
|
||||
class="flex flex-row items-center px-2 py-1 text-sm font-semibold whitespace-nowrap text-base hover:text-primary transition-colors duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded-md"
|
||||
x-on:click="open = !open"
|
||||
:aria-expanded="open">
|
||||
{{ $trigger }}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
</legend>
|
||||
@endif
|
||||
<textarea type="{{ $type ?? 'text' }}" id="{{ $id ?? $name }}" name="{{ $name }}"
|
||||
class="block w-full text-sm text-primary-100 bg-primary-800 border-2 border-neutral rounded-md outline-none focus:outline-none focus:border-secondary transition-all duration-300 ease-in-out disabled:bg-primary-700 disabled:cursor-not-allowed {{ $class ?? '' }} @if ($type !== 'color') px-2.5 py-2.5 @endif"
|
||||
class="block w-full text-sm text-base bg-background-secondary/50 border border-neutral rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary transition-all duration-300 ease-in-out disabled:bg-background-secondary/50 disabled:cursor-not-allowed resize-y min-h-[100px] {{ $class ?? '' }} @if ($type !== 'color') px-2.5 py-2.5 @endif"
|
||||
placeholder="{{ $placeholder ?? ($label ?? '') }}" @if ($dirty && isset($attributes['wire:model']))
|
||||
wire:dirty.class="!border-yellow-600" @endif {{ $attributes->except(['placeholder', 'label', 'id', 'name', 'type', 'class', 'divClass', 'required', 'hideRequiredIndicator', 'dirty']) }}
|
||||
@required($required)>{{ $slot }}</textarea>
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
<nav role="navigation" aria-label="Pagination Navigation" class="flex gap-2 items-center">
|
||||
<span>
|
||||
@if ($paginator->onFirstPage())
|
||||
<span class="bg-background-secondary text-base/50 px-4 py-2 rounded-lg cursor-not-allowed border border-neutral transition-colors duration-200">Previous</span>
|
||||
<span class="bg-background-secondary text-base/50 px-4 py-2 rounded-lg cursor-not-allowed border border-neutral/30 opacity-50 transition-colors duration-200">Previous</span>
|
||||
@else
|
||||
<button wire:click="previousPage" wire:loading.attr="disabled" rel="prev" class="bg-background-secondary text-base px-4 py-2 rounded-lg border border-neutral hover:bg-background/80 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-primary/50">Previous</button>
|
||||
<button wire:click="previousPage" wire:loading.attr="disabled" rel="prev" class="bg-background-secondary text-base px-4 py-2 rounded-lg border border-neutral hover:bg-background/80 hover:border-primary/50 transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-primary/50">Previous</button>
|
||||
@endif
|
||||
</span>
|
||||
|
||||
@@ -19,16 +19,16 @@
|
||||
abs($paginator->currentPage() - $page) <= 1)
|
||||
<span>
|
||||
<button wire:click="gotoPage({{ $page }})" wire:loading.attr="disabled"
|
||||
class="{{ $page === $paginator->currentPage() ? 'bg-primary text-white border-primary' : 'bg-background-secondary text-base border-neutral hover:bg-background/80' }} px-4 py-2 rounded-lg cursor-pointer border transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-primary/50">{{ $page }}</button>
|
||||
class="{{ $page === $paginator->currentPage() ? 'bg-primary text-white border-primary shadow-sm' : 'bg-background-secondary text-base border-neutral hover:bg-background/80 hover:border-primary/50' }} px-4 py-2 rounded-lg cursor-pointer border transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-primary/50">{{ $page }}</button>
|
||||
</span>
|
||||
@elseif($page == 3 || $page == $paginator->lastPage() - 3)
|
||||
<span class="bg-background-secondary text-base/50 px-4 py-2 rounded-lg border border-neutral">
|
||||
<span class="bg-background-secondary text-base/50 px-4 py-2 rounded-lg border border-neutral/30">
|
||||
<span>...</span>
|
||||
</span>
|
||||
@endif
|
||||
@endforeach
|
||||
@else
|
||||
<span class="bg-background-secondary text-base/50 px-4 py-2 rounded-lg border border-neutral">
|
||||
<span class="bg-background-secondary text-base/50 px-4 py-2 rounded-lg border border-neutral/30">
|
||||
<span>...</span>
|
||||
</span>
|
||||
@endif
|
||||
@@ -37,10 +37,10 @@
|
||||
|
||||
<span>
|
||||
@if ($paginator->onLastPage())
|
||||
<span class="bg-background-secondary text-base/50 px-4 py-2 rounded-lg cursor-not-allowed border border-neutral transition-colors duration-200">Next</span>
|
||||
<span class="bg-background-secondary text-base/50 px-4 py-2 rounded-lg cursor-not-allowed border border-neutral/30 opacity-50 transition-colors duration-200">Next</span>
|
||||
@else
|
||||
<button wire:click="nextPage" wire:loading.attr="disabled" rel="next"
|
||||
class="bg-background-secondary text-base px-4 py-2 rounded-lg border border-neutral hover:bg-background/80 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-primary/50">Next</button>
|
||||
class="bg-background-secondary text-base px-4 py-2 rounded-lg border border-neutral hover:bg-background/80 hover:border-primary/50 transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-primary/50">Next</button>
|
||||
@endif
|
||||
</span>
|
||||
</nav>
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
{{-- Skeleton loader for invoice card --}}
|
||||
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 border border-neutral/50 p-6 rounded-xl shadow-lg
|
||||
flex flex-col md:flex-row items-start md:items-center justify-between gap-4 animate-pulse">
|
||||
flex flex-col md:flex-row items-start md:items-center justify-between gap-4">
|
||||
|
||||
<div class="flex items-start md:items-center gap-4 flex-grow">
|
||||
{{-- Icon skeleton --}}
|
||||
<div class="p-3 rounded-full flex-shrink-0 bg-blue-500/20 w-12 h-12"></div>
|
||||
<div class="p-3 rounded-full flex-shrink-0 bg-blue-500/20 w-12 h-12 skeleton-shimmer"></div>
|
||||
|
||||
<div class="flex flex-col flex-grow">
|
||||
{{-- Title skeleton --}}
|
||||
<div class="h-6 bg-neutral/20 rounded-lg w-40 mb-2"></div>
|
||||
<div class="h-6 bg-neutral/20 rounded-lg w-40 mb-2 skeleton-shimmer"></div>
|
||||
{{-- Amount and date skeleton --}}
|
||||
<div class="h-4 bg-neutral/20 rounded w-56 mb-1"></div>
|
||||
<div class="h-4 bg-neutral/20 rounded w-56 mb-1 skeleton-shimmer"></div>
|
||||
{{-- Due date skeleton --}}
|
||||
<div class="h-3 bg-neutral/20 rounded w-36"></div>
|
||||
<div class="h-3 bg-neutral/20 rounded w-36 skeleton-shimmer"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-3 flex-shrink-0 mt-3 md:mt-0">
|
||||
{{-- Status badge skeleton --}}
|
||||
<div class="h-7 bg-neutral/20 rounded-full w-20"></div>
|
||||
<div class="h-7 bg-neutral/20 rounded-full w-20 skeleton-shimmer"></div>
|
||||
{{-- Arrow skeleton --}}
|
||||
<div class="h-6 w-6 bg-neutral/20 rounded"></div>
|
||||
<div class="h-6 w-6 bg-neutral/20 rounded skeleton-shimmer"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
{{-- Skeleton loader for service card --}}
|
||||
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 border border-neutral/50 p-6 rounded-xl shadow-lg
|
||||
flex flex-col md:flex-row items-start md:items-center justify-between gap-4 animate-pulse">
|
||||
flex flex-col md:flex-row items-start md:items-center justify-between gap-4">
|
||||
|
||||
<div class="flex items-start md:items-center gap-4 flex-grow">
|
||||
{{-- Icon skeleton --}}
|
||||
<div class="p-3 rounded-full flex-shrink-0 bg-neutral/20 w-12 h-12"></div>
|
||||
<div class="p-3 rounded-full flex-shrink-0 bg-neutral/20 w-12 h-12 skeleton-shimmer"></div>
|
||||
|
||||
<div class="flex flex-col flex-grow">
|
||||
{{-- Title skeleton --}}
|
||||
<div class="h-6 bg-neutral/20 rounded-lg w-48 mb-2"></div>
|
||||
<div class="h-6 bg-neutral/20 rounded-lg w-48 mb-2 skeleton-shimmer"></div>
|
||||
{{-- Description skeleton --}}
|
||||
<div class="h-4 bg-neutral/20 rounded w-64 mb-1"></div>
|
||||
<div class="h-4 bg-neutral/20 rounded w-64 mb-1 skeleton-shimmer"></div>
|
||||
{{-- Date skeleton --}}
|
||||
<div class="h-3 bg-neutral/20 rounded w-32"></div>
|
||||
<div class="h-3 bg-neutral/20 rounded w-32 skeleton-shimmer"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-3 flex-shrink-0 mt-3 md:mt-0">
|
||||
{{-- Status badge skeleton --}}
|
||||
<div class="h-7 bg-neutral/20 rounded-full w-20"></div>
|
||||
<div class="h-7 bg-neutral/20 rounded-full w-20 skeleton-shimmer"></div>
|
||||
{{-- Arrow skeleton --}}
|
||||
<div class="h-6 w-6 bg-neutral/20 rounded"></div>
|
||||
<div class="h-6 w-6 bg-neutral/20 rounded skeleton-shimmer"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
</h1>
|
||||
|
||||
<div class="grid grid-cols-3 md:grid-cols-3 gap-4 mb-12 bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 border border-neutral/50 p-2 rounded-xl">
|
||||
<div class="bg-success/10 border border-success/50 rounded-xl p-4 text-center">
|
||||
<div class="bg-success/10 border border-success/50 rounded-xl p-4 text-center status-card-hover">
|
||||
<div class="flex items-center justify-center mb-2">
|
||||
<x-ri-checkbox-circle-fill class="size-6 text-success mr-2" />
|
||||
<span class="text-2xl font-bold text-success">{{ $invoices->where('status', 'paid')->count() }}</span>
|
||||
@@ -13,7 +13,7 @@
|
||||
<p class="text-sm font-medium text-success">{{ __('Paid') }}</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-warning/10 border border-warning/50 rounded-xl p-4 text-center">
|
||||
<div class="bg-warning/10 border border-warning/50 rounded-xl p-4 text-center status-card-hover">
|
||||
<div class="flex items-center justify-center mb-2">
|
||||
<x-ri-error-warning-fill class="size-6 text-warning mr-2" />
|
||||
<span class="text-2xl font-bold text-warning">{{ $invoices->where('status', 'pending')->count() }}</span>
|
||||
@@ -21,7 +21,7 @@
|
||||
<p class="text-sm font-medium text-warning">{{ __('Pending') }}</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-inactive/10 border border-inactive/50 rounded-xl p-4 text-center">
|
||||
<div class="bg-inactive/10 border border-inactive/50 rounded-xl p-4 text-center status-card-hover">
|
||||
<div class="flex items-center justify-center mb-2">
|
||||
<x-ri-close-circle-fill class="size-6 text-inactive mr-2" />
|
||||
<span class="text-2xl font-bold text-inactive">{{ $invoices->where('status', 'cancelled')->count() }}</span>
|
||||
@@ -80,13 +80,13 @@
|
||||
{{ __('Pending') }}
|
||||
@endif
|
||||
</div>
|
||||
<x-ri-arrow-right-s-line class="size-6 text-color-muted group-hover:text-primary transition-colors duration-200" />
|
||||
<x-ri-arrow-right-s-line class="size-6 text-color-muted card-arrow-animate" />
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
@empty
|
||||
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 rounded-xl shadow-lg p-8 lg:p-12 border border-neutral/50 text-center group">
|
||||
<div class="bg-blue-500/10 rounded-full p-6 w-fit mx-auto mb-6 transition-transform duration-300 group-hover:scale-110">
|
||||
<div class="bg-blue-500/10 rounded-full p-6 w-fit mx-auto mb-6 transition-transform duration-300 group-hover:scale-110 empty-state-float">
|
||||
<x-ri-file-list-3-line class="size-12 text-blue-500" />
|
||||
</div>
|
||||
<h3 class="text-2xl font-bold text-color-base mb-3">No invoices yet</h3>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
{{-- Status Overview --}}
|
||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-12 bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 border border-neutral/50 p-2 rounded-xl">
|
||||
<div class="bg-success/10 border border-success/50 rounded-xl p-4 text-center">
|
||||
<div class="bg-success/10 border border-success/50 rounded-xl p-4 text-center status-card-hover">
|
||||
<div class="flex items-center justify-center mb-2">
|
||||
<x-ri-checkbox-circle-fill class="size-6 text-success mr-2" />
|
||||
<span class="text-2xl font-bold text-success">{{ $services->where('status', 'active')->count() }}</span>
|
||||
@@ -14,7 +14,7 @@
|
||||
<p class="text-sm font-medium text-success">{{ __('Active') }}</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-warning/10 border border-warning/50 rounded-xl p-4 text-center">
|
||||
<div class="bg-warning/10 border border-warning/50 rounded-xl p-4 text-center status-card-hover">
|
||||
<div class="flex items-center justify-center mb-2">
|
||||
<x-ri-error-warning-fill class="size-6 text-warning mr-2" />
|
||||
<span class="text-2xl font-bold text-warning">{{ $services->where('status', 'pending')->count() }}</span>
|
||||
@@ -22,7 +22,7 @@
|
||||
<p class="text-sm font-medium text-warning">{{ __('Pending') }}</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-error/10 border border-error/50 rounded-xl p-4 text-center">
|
||||
<div class="bg-error/10 border border-error/50 rounded-xl p-4 text-center status-card-hover">
|
||||
<div class="flex items-center justify-center mb-2">
|
||||
<x-ri-forbid-fill class="size-6 text-red-500 mr-2" />
|
||||
<span class="text-2xl font-bold text-red-500">{{ $services->where('status', 'suspended')->count() }}</span>
|
||||
@@ -30,7 +30,7 @@
|
||||
<p class="text-sm font-medium text-red-500">{{ __('Suspended') }}</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-inactive/10 border border-inactive/50 rounded-xl p-4 text-center">
|
||||
<div class="bg-inactive/10 border border-inactive/50 rounded-xl p-4 text-center status-card-hover">
|
||||
<div class="flex items-center justify-center mb-2">
|
||||
<x-ri-close-circle-fill class="size-6 text-inactive mr-2" />
|
||||
<span class="text-2xl font-bold text-inactive">{{ $services->where('status', 'cancelled')->count() }}</span>
|
||||
@@ -121,13 +121,13 @@
|
||||
{{ __('Pending') }}
|
||||
@endif
|
||||
</div>
|
||||
<x-ri-arrow-right-s-line class="size-6 text-color-muted group-hover:text-primary transition-colors duration-200" />
|
||||
<x-ri-arrow-right-s-line class="size-6 text-color-muted card-arrow-animate" />
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
@empty
|
||||
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 rounded-xl shadow-lg p-8 lg:p-12 border border-neutral/50 text-center group">
|
||||
<div class="bg-primary/10 rounded-full p-6 w-fit mx-auto mb-6 transition-transform duration-300 group-hover:scale-110">
|
||||
<div class="bg-primary/10 rounded-full p-6 w-fit mx-auto mb-6 transition-transform duration-300 group-hover:scale-110 empty-state-float">
|
||||
<x-ri-server-line class="size-12 text-primary" />
|
||||
</div>
|
||||
<h3 class="text-2xl font-bold text-color-base mb-3">No services yet</h3>
|
||||
|
||||
@@ -57,13 +57,13 @@
|
||||
{{ ucfirst($ticket->status) }}
|
||||
@endif
|
||||
</div>
|
||||
<x-ri-arrow-right-s-line class="size-6 text-color-muted group-hover:text-primary transition-colors duration-200" />
|
||||
<x-ri-arrow-right-s-line class="size-6 text-color-muted card-arrow-animate" />
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
@empty
|
||||
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 rounded-xl shadow-lg p-8 lg:p-12 border border-neutral/50 text-center">
|
||||
<div class="bg-secondary/10 rounded-full p-6 w-fit mx-auto mb-6">
|
||||
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 rounded-xl shadow-lg p-8 lg:p-12 border border-neutral/50 text-center group">
|
||||
<div class="bg-secondary/10 rounded-full p-6 w-fit mx-auto mb-6 empty-state-float">
|
||||
<x-ri-customer-service-2-line class="size-12 text-secondary" />
|
||||
</div>
|
||||
<h3 class="text-2xl font-bold text-color-base mb-3">No tickets yet</h3>
|
||||
|
||||
Reference in New Issue
Block a user