Redesign sidebar with frosted glass effect
Based on Figma design, updated sidebar to feature: - Frosted glass background with backdrop blur - Dark gradient app icon (from-[#303035] to-[#26262c]) - Filled icons when active, stroked when inactive - Smaller, more compact nav items (32x32px) - Updated sidebar CSS variables for translucent colors - Added glass utility classes for backdrop blur effects - User avatar at bottom with gradient background 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -99,14 +99,16 @@
|
||||
--chart-4: oklch(0.7 0.16 85);
|
||||
--chart-5: oklch(0.65 0.18 35);
|
||||
|
||||
--sidebar: oklch(0.98 0.001 280);
|
||||
/* Sidebar - frosted glass style */
|
||||
--sidebar: oklch(0.93 0 0 / 0.8);
|
||||
--sidebar-foreground: oklch(0.145 0.005 285);
|
||||
--sidebar-primary: oklch(0.205 0.006 285);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.94 0.002 280);
|
||||
--sidebar-accent-foreground: oklch(0.205 0.006 285);
|
||||
--sidebar-border: oklch(0.91 0.003 280);
|
||||
--sidebar-accent: oklch(0 0 0 / 0.1);
|
||||
--sidebar-accent-foreground: oklch(0.145 0.005 285);
|
||||
--sidebar-border: oklch(0 0 0 / 0.05);
|
||||
--sidebar-ring: oklch(0.65 0.015 280);
|
||||
--sidebar-muted: oklch(0 0 0 / 0.3);
|
||||
}
|
||||
|
||||
.dark {
|
||||
@@ -146,14 +148,16 @@
|
||||
--chart-4: oklch(0.6 0.2 310);
|
||||
--chart-5: oklch(0.65 0.22 25);
|
||||
|
||||
--sidebar: oklch(0.14 0.005 280);
|
||||
/* Sidebar - frosted glass style (dark) */
|
||||
--sidebar: oklch(0.18 0.005 280 / 0.9);
|
||||
--sidebar-foreground: oklch(0.96 0 0);
|
||||
--sidebar-primary: oklch(0.6 0.22 250);
|
||||
--sidebar-primary-foreground: oklch(0.96 0 0);
|
||||
--sidebar-accent: oklch(0.22 0.005 280);
|
||||
--sidebar-accent: oklch(1 0 0 / 0.1);
|
||||
--sidebar-accent-foreground: oklch(0.96 0 0);
|
||||
--sidebar-border: oklch(0.26 0.005 280);
|
||||
--sidebar-border: oklch(1 0 0 / 0.05);
|
||||
--sidebar-ring: oklch(0.5 0.01 280);
|
||||
--sidebar-muted: oklch(1 0 0 / 0.3);
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
@@ -198,6 +202,7 @@
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
--color-sidebar-muted: var(--sidebar-muted);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
@@ -236,7 +241,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Utility classes for consistent shadows */
|
||||
/* Utility classes for consistent shadows and effects */
|
||||
@layer utilities {
|
||||
.shadow-card {
|
||||
box-shadow:
|
||||
@@ -255,4 +260,13 @@
|
||||
0 4px 6px -1px oklch(0 0 0 / 0.05),
|
||||
0 2px 4px -2px oklch(0 0 0 / 0.05);
|
||||
}
|
||||
|
||||
/* Frosted glass effect */
|
||||
.glass {
|
||||
@apply backdrop-blur-xl backdrop-saturate-150;
|
||||
}
|
||||
|
||||
.glass-subtle {
|
||||
@apply backdrop-blur-md backdrop-saturate-125;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { page } from "$app/stores";
|
||||
import { Separator } from "$lib/components/ui/separator";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
interface Props {
|
||||
@@ -38,19 +37,19 @@ const bottomItems = [
|
||||
|
||||
<aside
|
||||
class={cn(
|
||||
"flex h-screen w-[72px] flex-col items-center bg-sidebar py-5",
|
||||
"border-r border-sidebar-border",
|
||||
"flex h-screen w-[80px] flex-col items-center bg-sidebar glass",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<!-- Logo -->
|
||||
<!-- App Icon -->
|
||||
<div class="flex h-[94px] items-center justify-center">
|
||||
<a
|
||||
href="/"
|
||||
aria-label="Home"
|
||||
class="group flex h-10 w-10 items-center justify-center rounded-lg bg-foreground transition-all duration-200 hover:scale-[1.02]"
|
||||
class="group flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-b from-[#303035] to-[#26262c] shadow-sm transition-transform duration-200 hover:scale-105"
|
||||
>
|
||||
<svg
|
||||
class="h-5 w-5 text-background transition-transform duration-200 group-hover:scale-105"
|
||||
class="h-4 w-4 text-white transition-transform duration-200 group-hover:scale-110"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
@@ -59,35 +58,61 @@ const bottomItems = [
|
||||
<path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<Separator class="my-5 w-8" />
|
||||
</div>
|
||||
|
||||
<!-- Main Navigation -->
|
||||
<nav class="flex flex-1 flex-col items-center gap-1">
|
||||
<nav class="flex flex-1 flex-col items-center gap-3">
|
||||
{#each navItems as item}
|
||||
{@const isActive = $page.url.pathname === item.href || (item.href !== "/" && $page.url.pathname.startsWith(item.href))}
|
||||
{@const isActive =
|
||||
$page.url.pathname === item.href ||
|
||||
(item.href !== "/" && $page.url.pathname.startsWith(item.href))}
|
||||
<a
|
||||
href={item.href}
|
||||
class={cn(
|
||||
"group relative flex h-10 w-10 items-center justify-center rounded-lg transition-all duration-150",
|
||||
"group relative flex h-8 w-8 items-center justify-center rounded-lg transition-all duration-150",
|
||||
isActive
|
||||
? "bg-sidebar-accent text-foreground"
|
||||
: "text-muted-foreground hover:bg-sidebar-accent/60 hover:text-foreground",
|
||||
? "bg-sidebar-accent text-sidebar-foreground"
|
||||
: "text-sidebar-muted hover:bg-sidebar-accent/50 hover:text-sidebar-foreground",
|
||||
)}
|
||||
aria-label={item.label}
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
>
|
||||
{#if item.icon === "home"}
|
||||
<svg class="h-[18px] w-[18px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75">
|
||||
{#if isActive}
|
||||
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path
|
||||
d="M12.97 2.59a1.5 1.5 0 00-1.94 0l-7.5 6.363A1.5 1.5 0 003 10.097V19.5A1.5 1.5 0 004.5 21h4.75a.75.75 0 00.75-.75V14h4v6.25c0 .414.336.75.75.75h4.75a1.5 1.5 0 001.5-1.5v-9.403a1.5 1.5 0 00-.53-1.144l-7.5-6.363z"
|
||||
/>
|
||||
</svg>
|
||||
{:else}
|
||||
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75">
|
||||
<path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2V9z" stroke-linecap="round" stroke-linejoin="round" />
|
||||
<path d="M9 22V12h6v10" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
{/if}
|
||||
{:else if item.icon === "chart"}
|
||||
<svg class="h-[18px] w-[18px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75">
|
||||
{#if isActive}
|
||||
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path
|
||||
d="M18 3a1 1 0 011 1v16a1 1 0 11-2 0V4a1 1 0 011-1zM12 7a1 1 0 011 1v12a1 1 0 11-2 0V8a1 1 0 011-1zM6 11a1 1 0 011 1v8a1 1 0 11-2 0v-8a1 1 0 011-1z"
|
||||
/>
|
||||
</svg>
|
||||
{:else}
|
||||
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75">
|
||||
<path d="M18 20V10M12 20V4M6 20v-6" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
{/if}
|
||||
{:else if item.icon === "document"}
|
||||
<svg class="h-[18px] w-[18px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75">
|
||||
{#if isActive}
|
||||
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M5.625 1.5c-1.036 0-1.875.84-1.875 1.875v17.25c0 1.035.84 1.875 1.875 1.875h12.75c1.035 0 1.875-.84 1.875-1.875V7.875L14.25 1.5H5.625zM14.25 3v4.5a.75.75 0 00.75.75h4.5L14.25 3zM8.25 12.75a.75.75 0 000 1.5h7.5a.75.75 0 000-1.5h-7.5zm0 3a.75.75 0 000 1.5h7.5a.75.75 0 000-1.5h-7.5z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
{:else}
|
||||
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75">
|
||||
<path
|
||||
d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8l-6-6z"
|
||||
stroke-linecap="round"
|
||||
@@ -96,6 +121,7 @@ const bottomItems = [
|
||||
<path d="M14 2v6h6M16 13H8M16 17H8M10 9H8" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<!-- Tooltip -->
|
||||
<span
|
||||
@@ -103,32 +129,35 @@ const bottomItems = [
|
||||
>
|
||||
{item.label}
|
||||
</span>
|
||||
|
||||
<!-- Active indicator -->
|
||||
{#if isActive}
|
||||
<span class="absolute -left-[1px] h-5 w-[3px] rounded-r-full bg-foreground"></span>
|
||||
{/if}
|
||||
</a>
|
||||
{/each}
|
||||
</nav>
|
||||
|
||||
<!-- Bottom Navigation -->
|
||||
<div class="flex flex-col items-center gap-1">
|
||||
<!-- Bottom items -->
|
||||
<div class="mt-auto flex flex-col items-center gap-3">
|
||||
{#each bottomItems as item}
|
||||
{@const isActive = $page.url.pathname === item.href}
|
||||
<a
|
||||
href={item.href}
|
||||
class={cn(
|
||||
"group relative flex h-10 w-10 items-center justify-center rounded-lg transition-all duration-150",
|
||||
"group relative flex h-8 w-8 items-center justify-center rounded-lg transition-all duration-150",
|
||||
isActive
|
||||
? "bg-sidebar-accent text-foreground"
|
||||
: "text-muted-foreground hover:bg-sidebar-accent/60 hover:text-foreground",
|
||||
? "bg-sidebar-accent text-sidebar-foreground"
|
||||
: "text-sidebar-muted hover:bg-sidebar-accent/50 hover:text-sidebar-foreground",
|
||||
)}
|
||||
aria-label={item.label}
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
>
|
||||
{#if item.icon === "settings"}
|
||||
<svg class="h-[18px] w-[18px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75">
|
||||
{#if isActive}
|
||||
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M11.078 2.25c-.917 0-1.699.663-1.85 1.567L9.05 4.889c-.02.12-.115.26-.297.348a7.493 7.493 0 00-.986.57c-.166.115-.334.126-.45.083L6.3 5.508a1.875 1.875 0 00-2.282.819l-.922 1.597a1.875 1.875 0 00.432 2.385l.84.692c.095.078.17.229.154.43a7.598 7.598 0 000 1.139c.015.2-.059.352-.153.43l-.841.692a1.875 1.875 0 00-.432 2.385l.922 1.597a1.875 1.875 0 002.282.818l1.019-.382c.115-.043.283-.031.45.082.312.214.641.405.985.57.182.088.277.228.297.35l.178 1.071c.151.904.933 1.567 1.85 1.567h1.844c.916 0 1.699-.663 1.85-1.567l.178-1.072c.02-.12.114-.26.297-.349.344-.165.673-.356.985-.57.167-.114.335-.125.45-.082l1.02.382a1.875 1.875 0 002.28-.819l.923-1.597a1.875 1.875 0 00-.432-2.385l-.84-.692c-.095-.078-.17-.229-.154-.43a7.614 7.614 0 000-1.139c-.016-.2.059-.352.153-.43l.84-.692c.708-.582.891-1.59.433-2.385l-.922-1.597a1.875 1.875 0 00-2.282-.818l-1.02.382c-.114.043-.282.031-.449-.083a7.49 7.49 0 00-.985-.57c-.183-.087-.277-.227-.297-.348l-.179-1.072a1.875 1.875 0 00-1.85-1.567h-1.843zM12 15.75a3.75 3.75 0 100-7.5 3.75 3.75 0 000 7.5z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
{:else}
|
||||
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75">
|
||||
<circle cx="12" cy="12" r="3" />
|
||||
<path
|
||||
d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 01-2.83 2.83l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 112.83-2.83l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V3a2 2 0 114 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 112.83 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z"
|
||||
@@ -137,6 +166,7 @@ const bottomItems = [
|
||||
/>
|
||||
</svg>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<span
|
||||
class="pointer-events-none absolute left-full ml-3 whitespace-nowrap rounded-md bg-foreground px-2.5 py-1.5 text-xs font-medium text-background opacity-0 shadow-lg transition-all duration-150 group-hover:opacity-100"
|
||||
@@ -145,15 +175,20 @@ const bottomItems = [
|
||||
</span>
|
||||
</a>
|
||||
{/each}
|
||||
|
||||
<Separator class="my-3 w-8" />
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- User Avatar -->
|
||||
<div class="flex h-[80px] items-center justify-center">
|
||||
<button
|
||||
class="flex h-9 w-9 items-center justify-center rounded-full bg-gradient-to-br from-chart-1 to-chart-2 text-xs font-semibold text-white shadow-sm ring-2 ring-background transition-transform duration-150 hover:scale-105"
|
||||
class="relative h-6 w-6 overflow-hidden rounded-full ring-1 ring-sidebar-border transition-transform duration-150 hover:scale-110"
|
||||
aria-label="User menu"
|
||||
>
|
||||
<div
|
||||
class="flex h-full w-full items-center justify-center bg-gradient-to-br from-amber-500 to-orange-600 text-[10px] font-semibold text-white"
|
||||
>
|
||||
JD
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
Reference in New Issue
Block a user