Add animated glass background, breadcrumbs, and brand mark polish
Cards now sit on an animated signature-gradient background and use a translucent, blurred bp-glass surface so it shines through; extended bp-glass to every stat surface on the Stats page and to its tab switcher. Adds a Breadcrumbs component below the header on all app pages. Also: drop the gradient text fill from the wordmark/heading, animate the BrandMark's heart and curve on the dashboard hero instead of a plain pulse ring, recenter the heart/curve artwork in icon.svg and BrandMark, close the mobile nav menu on link click, remove the redundant "back to recordings" button, and match the "Start session"/"Scan for devices" button sizes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
import { NavBar } from "@/components/layout/NavBar";
|
||||
import { Breadcrumbs } from "@/components/layout/Breadcrumbs";
|
||||
|
||||
export default function AppLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="min-h-dvh">
|
||||
<NavBar />
|
||||
<main className="mx-auto max-w-6xl px-4 py-8">{children}</main>
|
||||
<main className="mx-auto max-w-6xl px-4 py-8">
|
||||
<Breadcrumbs />
|
||||
{children}
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+2
-2
@@ -24,8 +24,8 @@ export default async function DashboardPage() {
|
||||
<div className="flex flex-col gap-8">
|
||||
<Card className="bp-glass overflow-hidden">
|
||||
<CardContent className="flex flex-col items-start gap-4 py-8">
|
||||
<BrandMark size={40} className="bp-pulse rounded-[9px]" />
|
||||
<h1 className="font-heading bp-gradient-text text-3xl font-semibold">Welcome back</h1>
|
||||
<BrandMark size={48} animated className="rounded-[9px]" />
|
||||
<h1 className="font-heading text-3xl font-semibold">Welcome back</h1>
|
||||
<p className="max-w-xl text-sm text-muted-foreground">
|
||||
Scan for nearby devices, take control, and record sessions to replay later - all running
|
||||
directly from your browser over Web Bluetooth.
|
||||
|
||||
@@ -27,7 +27,7 @@ export default async function StatsPage() {
|
||||
</div>
|
||||
|
||||
<Tabs defaultValue="sessions">
|
||||
<TabsList>
|
||||
<TabsList className="bp-glass">
|
||||
<TabsTrigger value="sessions">Sessions</TabsTrigger>
|
||||
<TabsTrigger value="devices">Devices</TabsTrigger>
|
||||
<TabsTrigger value="recordings">Recordings</TabsTrigger>
|
||||
|
||||
+82
-5
@@ -127,13 +127,46 @@
|
||||
@apply border-border outline-ring/50;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
@apply text-foreground;
|
||||
}
|
||||
html {
|
||||
@apply font-sans;
|
||||
}
|
||||
}
|
||||
|
||||
/* Animated signature-sweep background - sits behind everything; cards use
|
||||
.bp-glass (translucent + blurred) so it shines through instead of being
|
||||
fully hidden behind an opaque card surface. */
|
||||
body {
|
||||
background-color: var(--background);
|
||||
background-image:
|
||||
radial-gradient(ellipse 80% 60% at 15% 10%, color-mix(in srgb, #ff6fb0 32%, transparent), transparent 60%),
|
||||
radial-gradient(ellipse 70% 60% at 85% 25%, color-mix(in srgb, #4f7fe0 28%, transparent), transparent 60%),
|
||||
radial-gradient(ellipse 75% 65% at 50% 100%, color-mix(in srgb, #b34bde 30%, transparent), transparent 60%);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 140% 140%;
|
||||
background-attachment: fixed;
|
||||
animation: bp-bg-drift 24s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes bp-bg-drift {
|
||||
0% {
|
||||
background-position: 0% 0%, 100% 0%, 50% 100%;
|
||||
}
|
||||
50% {
|
||||
background-position: 20% 20%, 80% 30%, 60% 80%;
|
||||
}
|
||||
100% {
|
||||
background-position: 0% 0%, 100% 0%, 50% 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
body {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Signature pink -> purple -> blue sweep (matches app/icon.svg), used for
|
||||
the wordmark and one hero moment - not smeared across every surface. */
|
||||
.bp-gradient-text {
|
||||
@@ -147,17 +180,20 @@
|
||||
background: linear-gradient(135deg, #ff6fb0, #b34bde 50%, #4f7fe0);
|
||||
}
|
||||
|
||||
/* Console-module surface: hairline border + a soft inset top highlight,
|
||||
standing in for backdrop-blur glassmorphism. */
|
||||
/* Console-module surface: translucent + blurred so the animated background
|
||||
sweep shines through, with a hairline border and soft inset top highlight. */
|
||||
.bp-glass {
|
||||
background: var(--card);
|
||||
background: color-mix(in srgb, var(--card) 55%, transparent);
|
||||
backdrop-filter: blur(20px) saturate(150%);
|
||||
border: 1px solid var(--border);
|
||||
box-shadow: inset 0 1px 0 color-mix(in srgb, var(--foreground) 8%, transparent);
|
||||
transition:
|
||||
border-color 0.2s ease,
|
||||
box-shadow 0.2s ease;
|
||||
box-shadow 0.2s ease,
|
||||
background-color 0.2s ease;
|
||||
}
|
||||
.bp-glass:hover {
|
||||
background: color-mix(in srgb, var(--card) 62%, transparent);
|
||||
border-color: color-mix(in srgb, var(--primary) 45%, var(--border));
|
||||
box-shadow:
|
||||
inset 0 1px 0 color-mix(in srgb, var(--foreground) 10%, transparent),
|
||||
@@ -201,6 +237,47 @@
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
|
||||
/* BrandMark's animated variant (dashboard hero): the heart glyph beats, the
|
||||
EKG-style curve glows in the primary accent instead of plain white. */
|
||||
@keyframes bp-mark-heartbeat {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 0.22;
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 0.75;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
.bp-mark-heart {
|
||||
transform-box: fill-box;
|
||||
transform-origin: center;
|
||||
animation: bp-mark-heartbeat 1.8s ease-in-out infinite;
|
||||
}
|
||||
@keyframes bp-mark-curve-glow {
|
||||
0%,
|
||||
100% {
|
||||
filter: drop-shadow(0 0 1px color-mix(in srgb, var(--primary) 50%, transparent));
|
||||
}
|
||||
50% {
|
||||
filter:
|
||||
drop-shadow(0 0 5px color-mix(in srgb, var(--primary) 100%, transparent))
|
||||
drop-shadow(0 0 10px color-mix(in srgb, var(--primary) 70%, transparent));
|
||||
}
|
||||
}
|
||||
.bp-mark-curve {
|
||||
stroke: #fff;
|
||||
animation: bp-mark-curve-glow 1.8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.bp-mark-heart,
|
||||
.bp-mark-curve {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bp-pulse-glow {
|
||||
0%,
|
||||
100% {
|
||||
|
||||
+14
-12
@@ -7,16 +7,18 @@
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect x="1" y="1" width="30" height="30" rx="9" fill="url(#bpGrad)" />
|
||||
<path
|
||||
d="M16 22.6c-.3 0-.5-.1-.7-.3C11.7 19 8 15.6 8 12.3 8 9.9 9.9 8 12.3 8c1.3 0 2.6.6 3.4 1.7.1.1.2.1.3 0 .8-1.1 2.1-1.7 3.4-1.7C21.8 8 23.7 9.9 23.7 12.3c0 3.3-3.7 6.7-7.3 10-.2.2-.4.3-.7.3z"
|
||||
fill="rgba(255,255,255,0.22)"
|
||||
/>
|
||||
<polyline
|
||||
points="6,15 10,15 12,9 15,21 18,13 20,15 26,15"
|
||||
fill="none"
|
||||
stroke="#ffffff"
|
||||
stroke-width="1.7"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<g transform="translate(0 0.7)">
|
||||
<path
|
||||
d="M16 22.6c-.3 0-.5-.1-.7-.3C11.7 19 8 15.6 8 12.3 8 9.9 9.9 8 12.3 8c1.3 0 2.6.6 3.4 1.7.1.1.2.1.3 0 .8-1.1 2.1-1.7 3.4-1.7C21.8 8 23.7 9.9 23.7 12.3c0 3.3-3.7 6.7-7.3 10-.2.2-.4.3-.7.3z"
|
||||
fill="rgba(255,255,255,0.22)"
|
||||
/>
|
||||
<polyline
|
||||
points="6,15 10,15 12,9 15,21 18,13 20,15 26,15"
|
||||
fill="none"
|
||||
stroke="#ffffff"
|
||||
stroke-width="1.7"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 884 B After Width: | Height: | Size: 950 B |
+1
-1
@@ -13,7 +13,7 @@ export default function LoginPage() {
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<BrandMark size={32} />
|
||||
<CardTitle className="font-heading bp-gradient-text text-2xl">Sexy</CardTitle>
|
||||
<CardTitle className="font-heading text-2xl">Sexy</CardTitle>
|
||||
</div>
|
||||
<CardDescription>Enter the shared access secret to continue.</CardDescription>
|
||||
</CardHeader>
|
||||
|
||||
Reference in New Issue
Block a user