feat: Enhance UI components and add command palette

- Updated dropdown component styles and transitions for improved UX.
- Refined checkbox, input, radio, select, and textarea components with consistent error messaging and styling.
- Introduced a new card component for better layout options.
- Added a stat card component for displaying metrics with trends.
- Implemented a command palette for global search and navigation, accessible via Cmd/Ctrl+K.
- Enhanced modal and navigation components with new styles and transitions.
- Improved layout styles for better responsiveness and visual appeal.
This commit is contained in:
2026-04-22 10:40:33 -04:00
parent a910d41e6e
commit 8baf7d6c7d
19 changed files with 859 additions and 82 deletions

View File

@@ -312,6 +312,155 @@ html {
.neon-border::before {
animation: none !important;
}
.border-gradient-live::before {
animation: none !important;
}
}
/* =============================================================================
HOVER LIFT — universal micro-interaction for list rows, cards, tiles.
============================================================================= */
@utility hover-lift {
transition: transform 220ms var(--ease-out-soft, ease), box-shadow 220ms var(--ease-out-soft, ease);
}
.hover-lift:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-floating);
}
/* =============================================================================
BORDER-GRADIENT-LIVE — slower animated conic rail for active status badges.
============================================================================= */
@utility border-gradient-live {
position: relative;
isolation: isolate;
}
.border-gradient-live::before {
content: '';
position: absolute;
inset: -2px;
border-radius: inherit;
padding: 2px;
background: conic-gradient(from var(--neon-angle),
hsl(var(--color-success) / 0.85),
hsl(var(--color-primary) / 0.6),
hsl(var(--color-secondary) / 0.85),
hsl(var(--color-success) / 0.85));
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
animation: neon-spin 12s linear infinite;
pointer-events: none;
z-index: -1;
}
/* =============================================================================
PULSE RING — double-ripple for live status dots (e.g. "Available").
============================================================================= */
@utility pulse-ring {
position: relative;
}
.pulse-ring::before,
.pulse-ring::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
background: currentColor;
opacity: 0;
animation: pulse-ring-expand 2s cubic-bezier(0, 0, 0.2, 1) infinite;
pointer-events: none;
}
.pulse-ring::after {
animation-delay: 1s;
}
@keyframes pulse-ring-expand {
0% { transform: scale(1); opacity: 0.6; }
80% { transform: scale(2.4); opacity: 0; }
100% { transform: scale(2.4); opacity: 0; }
}
/* =============================================================================
RIPPLE — radial ripple on :active for solid buttons (primary/danger).
Uses ::after so it doesn't conflict with existing ::before usage.
============================================================================= */
.btn-ripple {
position: relative;
overflow: hidden;
isolation: isolate;
}
.btn-ripple::after {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(circle at center, rgba(255,255,255,0.35) 0%, rgba(255,255,255,0) 60%);
opacity: 0;
transform: scale(0.4);
pointer-events: none;
transition: transform 0.45s var(--ease-out-soft, ease), opacity 0.45s var(--ease-out-soft, ease);
}
.btn-ripple:active::after {
opacity: 1;
transform: scale(1);
transition-duration: 0s;
}
/* =============================================================================
SCROLL-REVEAL STAGGER — extends .reveal-on-scroll with a per-index delay.
Parent sets --reveal-idx (0,1,2,…); delay = idx * 60ms.
============================================================================= */
[data-reveal-stagger] > .reveal-on-scroll,
.reveal-on-scroll[data-reveal-idx] {
transition-delay: calc(var(--reveal-idx, 0) * 60ms);
}
/* =============================================================================
FOCUS-VISIBLE UNIFICATION — consistent primary ring on keyboard focus,
globally. Individual form controls already customize their own rings.
============================================================================= */
@layer base {
:where(a, button, [role="button"], summary, [tabindex]):focus-visible {
outline: 2px solid hsl(var(--color-primary) / 0.6);
outline-offset: 2px;
border-radius: inherit;
}
}
/* =============================================================================
TILT SPOTLIGHT — when a card has [data-tilt], the Alpine directive sets
--tilt-x/--tilt-y (0..1). This renders a soft radial spotlight following the
cursor. The directive also applies perspective rotations via inline style.
============================================================================= */
[data-tilt] {
transition: transform 120ms var(--ease-out-soft, ease);
transform-style: preserve-3d;
}
[data-tilt]::before {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
background: radial-gradient(
280px circle at calc(var(--tilt-x, 0.5) * 100%) calc(var(--tilt-y, 0.5) * 100%),
hsl(var(--color-primary) / 0.14),
transparent 65%
);
opacity: 0;
transition: opacity 220ms var(--ease-out-soft, ease);
pointer-events: none;
z-index: 0;
}
[data-tilt]:hover::before {
opacity: 1;
}
[data-tilt] > * {
position: relative;
z-index: 1;
}
@media (prefers-reduced-motion: reduce) {
[data-tilt] { transform: none !important; }
[data-tilt]::before { display: none !important; }
}
/* Line clamp utilities - removed excessive containment */