439 lines
12 KiB
Svelte
439 lines
12 KiB
Svelte
<script lang="ts">
|
|
import { onMount } from 'svelte';
|
|
import { page } from '$app/stores';
|
|
import { goto } from '$app/navigation';
|
|
|
|
let isDarkMode = false;
|
|
let currentPath = '/';
|
|
let currentCategory: string | null = null;
|
|
|
|
const primaryNav = [
|
|
{ label: 'Today', href: '/', icon: 'today' },
|
|
{ label: 'Projects', href: '/projects', icon: 'projects' },
|
|
{ label: 'About', href: '/about', icon: 'about' },
|
|
{ label: 'Contact', href: '/contact', icon: 'contact' }
|
|
];
|
|
|
|
const categoryNav = [
|
|
{ label: 'Brand Design', href: '/projects?category=Brand Design' },
|
|
{ label: 'UI/UX Design', href: '/projects?category=UI/UX Design' },
|
|
{ label: 'Web Design', href: '/projects?category=Web Design' },
|
|
{ label: 'Graphic Design', href: '/projects?category=Graphic Design' },
|
|
{ label: 'Photography', href: '/projects?category=Photography' },
|
|
{ label: 'Print Design', href: '/projects?category=Print Design' }
|
|
];
|
|
|
|
function toggleTheme() {
|
|
isDarkMode = !isDarkMode;
|
|
document.documentElement.classList.toggle('dark', isDarkMode);
|
|
}
|
|
|
|
function navigateTo(href: string) {
|
|
goto(href);
|
|
}
|
|
|
|
$: currentPath = $page.url.pathname;
|
|
$: currentCategory = $page.url.searchParams.get('category');
|
|
|
|
onMount(() => {
|
|
// 检测系统主题偏好
|
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
isDarkMode = prefersDark;
|
|
document.documentElement.classList.toggle('dark', isDarkMode);
|
|
});
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<meta name="description" content="LiuBai Design - A modern creative studio experience built with SvelteKit" />
|
|
</svelte:head>
|
|
|
|
<div class="app-shell">
|
|
<aside class="sidebar">
|
|
<header class="sidebar__header">
|
|
<div class="sidebar__store-icon" aria-hidden="true">🎨</div>
|
|
<div class="sidebar__heading">
|
|
<span class="sidebar__title">LiuBai Design</span>
|
|
<span class="sidebar__subtitle">Creative Studio</span>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="sidebar__search">
|
|
<span class="sidebar__search-icon" aria-hidden="true">🔍</span>
|
|
<input type="search" placeholder="Search" aria-label="Search LiuBai Design" />
|
|
</div>
|
|
|
|
<nav class="sidebar__nav">
|
|
<div class="sidebar__section" aria-label="Primary navigation">
|
|
{#each primaryNav as item}
|
|
<button
|
|
class:active={item.href === '/' ? currentPath === '/' : currentPath.startsWith(item.href)}
|
|
on:click={() => navigateTo(item.href)}
|
|
>
|
|
<span class="sidebar__bullet" aria-hidden="true">•</span>
|
|
{item.label}
|
|
</button>
|
|
{/each}
|
|
</div>
|
|
|
|
<div class="sidebar__section" aria-label="Design categories">
|
|
<span class="sidebar__section-label">Design Categories</span>
|
|
{#each categoryNav as item}
|
|
<button
|
|
class:active={currentCategory === item.label}
|
|
on:click={() => navigateTo(item.href)}
|
|
>
|
|
{item.label}
|
|
</button>
|
|
{/each}
|
|
</div>
|
|
</nav>
|
|
|
|
<footer class="sidebar__footer">
|
|
<button on:click={toggleTheme} aria-label="Toggle theme">
|
|
<span class="sidebar__avatar" aria-hidden="true">{isDarkMode ? '☀️' : '🌙'}</span>
|
|
{isDarkMode ? 'Light' : 'Dark'}
|
|
</button>
|
|
<button aria-label="Account">
|
|
<span class="sidebar__avatar" aria-hidden="true">🧑💻</span>
|
|
Account
|
|
</button>
|
|
</footer>
|
|
</aside>
|
|
|
|
<main class="content">
|
|
<slot />
|
|
</main>
|
|
</div>
|
|
|
|
<style>
|
|
:global(html) {
|
|
height: 100%;
|
|
scroll-behavior: smooth;
|
|
}
|
|
|
|
:global(body) {
|
|
margin: 0;
|
|
padding: 0;
|
|
font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
transition: background-color 0.3s ease, color 0.3s ease;
|
|
}
|
|
|
|
/* 亮色模式 */
|
|
:global(body) {
|
|
background: #f5f5f7;
|
|
color: #1d1d1f;
|
|
}
|
|
|
|
/* 暗色模式 */
|
|
:global(.dark body) {
|
|
background: radial-gradient(circle at top left, rgba(46, 46, 82, 0.6), transparent 40%),
|
|
radial-gradient(circle at bottom right, rgba(36, 36, 60, 0.5), transparent 45%),
|
|
#050506;
|
|
color: #ffffff;
|
|
}
|
|
|
|
.app-shell {
|
|
display: grid;
|
|
grid-template-columns: 280px minmax(0, 1fr);
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.sidebar {
|
|
display: grid;
|
|
grid-template-rows: auto auto 1fr auto;
|
|
gap: 32px;
|
|
padding: 32px 24px;
|
|
background: rgba(255, 255, 255, 0.8);
|
|
border-right: 1px solid rgba(0, 0, 0, 0.08);
|
|
backdrop-filter: blur(30px);
|
|
box-shadow: 12px 0 40px rgba(0, 0, 0, 0.1);
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
:global(.dark) .sidebar {
|
|
background: rgba(10, 10, 18, 0.9);
|
|
border-right: 1px solid rgba(255, 255, 255, 0.08);
|
|
box-shadow: 12px 0 40px rgba(0, 0, 0, 0.35);
|
|
}
|
|
|
|
.sidebar__header {
|
|
display: flex;
|
|
gap: 12px;
|
|
align-items: center;
|
|
}
|
|
|
|
.sidebar__store-icon {
|
|
width: 36px;
|
|
height: 36px;
|
|
border-radius: 12px;
|
|
background: linear-gradient(135deg, #4f46e5 0%, #9333ea 100%);
|
|
display: grid;
|
|
place-items: center;
|
|
font-size: 20px;
|
|
color: white;
|
|
}
|
|
|
|
.sidebar__heading {
|
|
display: flex;
|
|
flex-direction: column;
|
|
color: rgba(0, 0, 0, 0.9);
|
|
transition: color 0.3s ease;
|
|
}
|
|
|
|
:global(.dark) .sidebar__heading {
|
|
color: rgba(255, 255, 255, 0.9);
|
|
}
|
|
|
|
.sidebar__title {
|
|
font-size: 15px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.02em;
|
|
}
|
|
|
|
.sidebar__subtitle {
|
|
font-size: 13px;
|
|
color: rgba(255, 255, 255, 0.55);
|
|
}
|
|
|
|
.sidebar__search {
|
|
position: relative;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.sidebar__search-icon {
|
|
position: absolute;
|
|
left: 14px;
|
|
font-size: 14px;
|
|
color: rgba(0, 0, 0, 0.4);
|
|
transition: color 0.3s ease;
|
|
}
|
|
|
|
:global(.dark) .sidebar__search-icon {
|
|
color: rgba(255, 255, 255, 0.4);
|
|
}
|
|
|
|
.sidebar__search input {
|
|
width: 100%;
|
|
padding: 10px 14px 10px 34px;
|
|
border-radius: 12px;
|
|
border: none;
|
|
background: rgba(0, 0, 0, 0.08);
|
|
color: rgba(0, 0, 0, 0.88);
|
|
font-size: 13px;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
:global(.dark) .sidebar__search input {
|
|
background: rgba(255, 255, 255, 0.08);
|
|
color: rgba(255, 255, 255, 0.88);
|
|
}
|
|
|
|
.sidebar__search input:focus {
|
|
outline: none;
|
|
background: rgba(0, 0, 0, 0.12);
|
|
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.35);
|
|
}
|
|
|
|
:global(.dark) .sidebar__search input:focus {
|
|
background: rgba(255, 255, 255, 0.12);
|
|
box-shadow: 0 0 0 2px rgba(147, 197, 253, 0.35);
|
|
}
|
|
|
|
.sidebar__nav {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 36px;
|
|
}
|
|
|
|
.sidebar__section {
|
|
display: grid;
|
|
gap: 4px;
|
|
}
|
|
|
|
.sidebar__section-label {
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.08em;
|
|
color: rgba(0, 0, 0, 0.35);
|
|
margin-bottom: 8px;
|
|
transition: color 0.3s ease;
|
|
}
|
|
|
|
:global(.dark) .sidebar__section-label {
|
|
color: rgba(255, 255, 255, 0.35);
|
|
}
|
|
|
|
.sidebar__section button {
|
|
position: relative;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
padding: 10px 14px;
|
|
border-radius: 12px;
|
|
border: none;
|
|
background: transparent;
|
|
color: rgba(0, 0, 0, 0.66);
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
:global(.dark) .sidebar__section button {
|
|
color: rgba(255, 255, 255, 0.66);
|
|
}
|
|
|
|
.sidebar__section button:hover {
|
|
color: rgba(0, 0, 0, 0.9);
|
|
background: rgba(0, 0, 0, 0.06);
|
|
}
|
|
|
|
:global(.dark) .sidebar__section button:hover {
|
|
color: rgba(255, 255, 255, 0.9);
|
|
background: rgba(255, 255, 255, 0.06);
|
|
}
|
|
|
|
.sidebar__section button.active {
|
|
color: #ffffff;
|
|
background: linear-gradient(135deg, rgba(88, 88, 255, 0.45), rgba(138, 92, 255, 0.45));
|
|
}
|
|
|
|
.sidebar__bullet {
|
|
width: 6px;
|
|
height: 6px;
|
|
border-radius: 50%;
|
|
background: rgba(0, 0, 0, 0.4);
|
|
transition: background 0.3s ease;
|
|
}
|
|
|
|
:global(.dark) .sidebar__bullet {
|
|
background: rgba(255, 255, 255, 0.4);
|
|
}
|
|
|
|
.sidebar__section button.active .sidebar__bullet {
|
|
background: #ffffff;
|
|
box-shadow: 0 0 10px rgba(255, 255, 255, 0.8);
|
|
}
|
|
|
|
.sidebar__footer button {
|
|
width: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
padding: 12px 14px;
|
|
border-radius: 12px;
|
|
border: 1px solid rgba(0, 0, 0, 0.08);
|
|
background: rgba(0, 0, 0, 0.03);
|
|
color: rgba(0, 0, 0, 0.72);
|
|
font-size: 13px;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
:global(.dark) .sidebar__footer button {
|
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
background: rgba(255, 255, 255, 0.03);
|
|
color: rgba(255, 255, 255, 0.72);
|
|
}
|
|
|
|
.sidebar__footer button:hover {
|
|
border-color: rgba(0, 0, 0, 0.2);
|
|
background: rgba(0, 0, 0, 0.08);
|
|
color: #000000;
|
|
}
|
|
|
|
:global(.dark) .sidebar__footer button:hover {
|
|
border-color: rgba(255, 255, 255, 0.2);
|
|
background: rgba(255, 255, 255, 0.08);
|
|
color: #ffffff;
|
|
}
|
|
|
|
.sidebar__avatar {
|
|
width: 28px;
|
|
height: 28px;
|
|
border-radius: 9px;
|
|
background: rgba(0, 0, 0, 0.1);
|
|
display: grid;
|
|
place-items: center;
|
|
transition: background 0.3s ease;
|
|
}
|
|
|
|
:global(.dark) .sidebar__avatar {
|
|
background: rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
.content {
|
|
position: relative;
|
|
overflow-y: auto;
|
|
padding: 48px 56px 64px;
|
|
background: linear-gradient(180deg, rgba(245, 245, 247, 0.9) 0%, rgba(240, 240, 242, 0.92) 55%, rgba(235, 235, 237, 0.96) 100%);
|
|
box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.05);
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
:global(.dark) .content {
|
|
background: linear-gradient(180deg, rgba(16, 16, 28, 0.9) 0%, rgba(8, 8, 18, 0.92) 55%, rgba(6, 6, 12, 0.96) 100%);
|
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
|
|
}
|
|
|
|
.content::-webkit-scrollbar {
|
|
width: 10px;
|
|
}
|
|
|
|
.content::-webkit-scrollbar-track {
|
|
background: rgba(200, 200, 200, 0.7);
|
|
}
|
|
|
|
:global(.dark) .content::-webkit-scrollbar-track {
|
|
background: rgba(12, 12, 18, 0.7);
|
|
}
|
|
|
|
.content::-webkit-scrollbar-thumb {
|
|
background: rgba(150, 150, 150, 0.45);
|
|
border-radius: 6px;
|
|
}
|
|
|
|
:global(.dark) .content::-webkit-scrollbar-thumb {
|
|
background: rgba(110, 110, 145, 0.45);
|
|
}
|
|
|
|
@media (max-width: 1024px) {
|
|
.app-shell {
|
|
grid-template-columns: 240px 1fr;
|
|
}
|
|
|
|
.content {
|
|
padding: 36px 32px 48px;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 860px) {
|
|
.app-shell {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.sidebar {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 10;
|
|
grid-template-rows: auto;
|
|
grid-auto-flow: column;
|
|
overflow-x: auto;
|
|
padding: 20px 24px;
|
|
gap: 24px;
|
|
}
|
|
|
|
.sidebar__nav,
|
|
.sidebar__footer {
|
|
display: none;
|
|
}
|
|
|
|
.content {
|
|
padding: 24px;
|
|
}
|
|
}
|
|
</style> |