mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-27 21:33:41 +02:00
* feat(views): refine navigation progress bar with brand color and glow (MUL-2269) The previous 1px bg-primary bar read as near-black on light theme and snapped on/off in a single frame, which felt abrupt despite being a small visual element. Switch to a 2px brand-colored sweep with right-edge glow, slower 1.4s cubic-bezier easing, and a 200ms fade-out so completion doesn't pop. - Container: h-px → h-0.5 (2px); always mounted with opacity-driven fade - Bar: bg-primary → bg-brand + two-layer box-shadow glow via color-mix - Keyframe: 1.1s ease-in-out → 1.4s cubic-bezier(0.4, 0, 0.2, 1) Zero new design tokens (reuses existing --brand) and zero tailwind config changes. Desktop unaffected — same component, same prefetch=no-op path. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai> * fix(views): unmount nav progress sweep when hidden (MUL-2269) Hiding the bar with opacity-0 left the inner element's `infinite` keyframe animation running on every dashboard page, defeating the perceived-perf goal. Mount the sweep only while navigating, plus the 200ms fade tail (unmount on opacity transitionend), so nothing animates while hidden. Co-authored-by: multica-agent <github@multica.ai> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai>
46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
import { useIsNavigating } from "../navigation";
|
|
|
|
// 2px top-of-content progress bar shown while a transition-wrapped
|
|
// push/replace is mid-flight. Indeterminate by design — we don't know
|
|
// when the next route will commit, just that it's coming.
|
|
//
|
|
// The container stays mounted so it can fade out over 200ms instead of
|
|
// vanishing in one frame. The inner sweep is mounted only while navigating
|
|
// (plus the fade-out tail); leaving its `infinite` keyframe animation
|
|
// running while hidden would burn paints on every dashboard view.
|
|
export function NavigationProgress() {
|
|
const isNavigating = useIsNavigating();
|
|
const [renderSweep, setRenderSweep] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (isNavigating) setRenderSweep(true);
|
|
}, [isNavigating]);
|
|
|
|
return (
|
|
<div
|
|
aria-hidden
|
|
data-visible={isNavigating ? "true" : "false"}
|
|
onTransitionEnd={(event) => {
|
|
if (event.propertyName === "opacity" && !isNavigating) {
|
|
setRenderSweep(false);
|
|
}
|
|
}}
|
|
className="pointer-events-none absolute inset-x-0 top-0 z-50 h-0.5 overflow-hidden opacity-0 transition-opacity duration-200 data-[visible=true]:opacity-100"
|
|
>
|
|
{renderSweep && (
|
|
<div
|
|
className="h-full w-1/3 animate-nav-progress-sweep bg-brand"
|
|
style={{
|
|
boxShadow:
|
|
"0 0 8px color-mix(in oklab, var(--brand) 60%, transparent), 0 0 2px color-mix(in oklab, var(--brand) 80%, transparent)",
|
|
}}
|
|
/>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|