Init
This commit is contained in:
439
src/routes/+layout.svelte
Normal file
439
src/routes/+layout.svelte
Normal file
@@ -0,0 +1,439 @@
|
||||
<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>
|
||||
700
src/routes/+page.svelte
Normal file
700
src/routes/+page.svelte
Normal file
@@ -0,0 +1,700 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
// 特色项目数据
|
||||
const featuredProjects = [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Creative Brand Identity',
|
||||
subtitle: 'Complete visual system for modern brands',
|
||||
badge: 'FEATURED PROJECT',
|
||||
category: 'Brand Design',
|
||||
description: 'A comprehensive brand identity system featuring logo design, color palettes, typography, and brand guidelines.',
|
||||
bgColor: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%), radial-gradient(circle at 20% 80%, rgba(120, 119, 198, 0.3) 0%, transparent 50%), radial-gradient(circle at 80% 20%, rgba(255, 255, 255, 0.15) 0%, transparent 50%)',
|
||||
textColor: 'white',
|
||||
image: '🎨',
|
||||
buttonText: 'View Project'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Mobile App Interface',
|
||||
subtitle: 'Modern UI/UX for digital experiences',
|
||||
badge: 'UI/UX DESIGN',
|
||||
category: 'Digital Design',
|
||||
description: 'Intuitive mobile interface design with focus on user experience and modern aesthetics.',
|
||||
bgColor: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%), radial-gradient(circle at 20% 80%, rgba(240, 147, 251, 0.3) 0%, transparent 50%), radial-gradient(circle at 80% 20%, rgba(255, 255, 255, 0.15) 0%, transparent 50%)',
|
||||
textColor: 'white',
|
||||
image: '📱',
|
||||
buttonText: 'Explore'
|
||||
}
|
||||
];
|
||||
|
||||
const smallProjects = [
|
||||
{
|
||||
id: 3,
|
||||
name: 'Web Portfolio',
|
||||
category: 'Web Design',
|
||||
icon: '💻',
|
||||
bgColor: '#4f46e5'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Print Design',
|
||||
category: 'Graphic Design',
|
||||
icon: '📄',
|
||||
bgColor: '#059669'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'Photography',
|
||||
category: 'Visual Arts',
|
||||
icon: '📸',
|
||||
bgColor: '#dc2626'
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: 'Illustration',
|
||||
category: 'Digital Art',
|
||||
icon: '🖼️',
|
||||
bgColor: '#7c3aed'
|
||||
}
|
||||
];
|
||||
|
||||
function navigateToProject(projectId: number) {
|
||||
goto(`/projects/${projectId}`);
|
||||
}
|
||||
|
||||
function navigateToProjects() {
|
||||
goto('/projects');
|
||||
}
|
||||
|
||||
function navigateToContact() {
|
||||
goto('/contact');
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
console.log('Home page mounted');
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>LiuBai Design - Creative Studio</title>
|
||||
<meta name="description" content="LiuBai Design - Discover amazing creative works and design solutions" />
|
||||
</svelte:head>
|
||||
|
||||
<div class="today-page">
|
||||
<!-- 页面标题 -->
|
||||
<header class="page-header">
|
||||
<h1 class="page-title">Today</h1>
|
||||
<p class="page-subtitle">Discover our latest creative works and design solutions</p>
|
||||
</header>
|
||||
|
||||
<!-- 主要特色项目 -->
|
||||
<section class="hero-section">
|
||||
<div class="hero-card" style="background: {featuredProjects[0].bgColor}" on:click={() => navigateToProject(featuredProjects[0].id)} role="button" tabindex="0">
|
||||
<div class="hero-content">
|
||||
<div class="hero-badge">{featuredProjects[0].badge}</div>
|
||||
<h2 class="hero-title">{featuredProjects[0].title}</h2>
|
||||
<p class="hero-description">{featuredProjects[0].description}</p>
|
||||
<div class="hero-project-info">
|
||||
<div class="project-icon">{featuredProjects[0].image}</div>
|
||||
<div class="project-details">
|
||||
<h3 class="project-name">{featuredProjects[0].subtitle}</h3>
|
||||
<p class="project-category">{featuredProjects[0].category}</p>
|
||||
</div>
|
||||
<button class="project-button" on:click|stopPropagation={() => navigateToProject(featuredProjects[0].id)}>{featuredProjects[0].buttonText}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 项目展示区域 -->
|
||||
<section class="projects-section">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">Featured Works</h2>
|
||||
<p class="section-subtitle">Explore our creative portfolio</p>
|
||||
</div>
|
||||
|
||||
<div class="projects-grid">
|
||||
<!-- 大型项目卡片 -->
|
||||
<div class="large-project-card" style="background: {featuredProjects[1].bgColor}" on:click={() => navigateToProject(featuredProjects[1].id)} role="button" tabindex="0">
|
||||
<div class="card-content">
|
||||
<div class="card-badge">{featuredProjects[1].badge}</div>
|
||||
<h3 class="card-title">{featuredProjects[1].title}</h3>
|
||||
<p class="card-description">{featuredProjects[1].description}</p>
|
||||
<div class="card-project-info">
|
||||
<div class="project-icon small">{featuredProjects[1].image}</div>
|
||||
<div class="project-details">
|
||||
<h4 class="project-name">{featuredProjects[1].subtitle}</h4>
|
||||
<p class="project-category">{featuredProjects[1].category}</p>
|
||||
</div>
|
||||
<button class="project-button small" on:click|stopPropagation={() => navigateToProject(featuredProjects[1].id)}>{featuredProjects[1].buttonText}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 小型项目卡片网格 -->
|
||||
<div class="small-projects-grid">
|
||||
{#each smallProjects as project}
|
||||
<div class="small-project-card" on:click={navigateToProjects} role="button" tabindex="0">
|
||||
<div class="small-card-icon" style="background-color: {project.bgColor}">
|
||||
{project.icon}
|
||||
</div>
|
||||
<h4 class="small-card-title">{project.name}</h4>
|
||||
<p class="small-card-category">{project.category}</p>
|
||||
<button class="small-card-button" on:click|stopPropagation={navigateToProjects}>View</button>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 服务展示 -->
|
||||
<section class="services-section">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">Our Services</h2>
|
||||
<p class="section-subtitle">What we can create for you</p>
|
||||
</div>
|
||||
|
||||
<div class="services-grid">
|
||||
<div class="service-card" on:click={navigateToContact} role="button" tabindex="0">
|
||||
<div class="service-icon">🎨</div>
|
||||
<h3 class="service-title">Brand Identity</h3>
|
||||
<p class="service-description">Complete visual identity systems that tell your brand's story</p>
|
||||
</div>
|
||||
<div class="service-card" on:click={navigateToContact} role="button" tabindex="0">
|
||||
<div class="service-icon">💻</div>
|
||||
<h3 class="service-title">Web Design</h3>
|
||||
<p class="service-description">Modern, responsive websites that engage and convert</p>
|
||||
</div>
|
||||
<div class="service-card" on:click={navigateToContact} role="button" tabindex="0">
|
||||
<div class="service-icon">📱</div>
|
||||
<h3 class="service-title">UI/UX Design</h3>
|
||||
<p class="service-description">Intuitive interfaces that users love to interact with</p>
|
||||
</div>
|
||||
<div class="service-card" on:click={navigateToContact} role="button" tabindex="0">
|
||||
<div class="service-icon">📸</div>
|
||||
<h3 class="service-title">Photography</h3>
|
||||
<p class="service-description">Professional photography for brands and products</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.today-page {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
animation: fadeIn 0.6s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.page-header {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 48px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 8px;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .page-title {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
font-size: 18px;
|
||||
color: #6B7280;
|
||||
margin: 0;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .page-subtitle {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
/* Hero Section */
|
||||
.hero-section {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.hero-card {
|
||||
border-radius: 24px;
|
||||
padding: 48px;
|
||||
color: white;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
min-height: 400px;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
cursor: pointer;
|
||||
transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.hero-card:hover {
|
||||
transform: translateY(-8px) scale(1.02);
|
||||
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.hero-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 50%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.hero-content {
|
||||
width: 100%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.hero-badge {
|
||||
display: inline-block;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
backdrop-filter: blur(10px);
|
||||
padding: 8px 16px;
|
||||
border-radius: 20px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 16px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
animation: slideInUp 0.8s ease-out 0.2s both;
|
||||
}
|
||||
|
||||
@keyframes slideInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: 36px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 16px;
|
||||
line-height: 1.2;
|
||||
animation: slideInUp 0.8s ease-out 0.4s both;
|
||||
}
|
||||
|
||||
.hero-description {
|
||||
font-size: 18px;
|
||||
margin-bottom: 32px;
|
||||
opacity: 0.9;
|
||||
line-height: 1.5;
|
||||
animation: slideInUp 0.8s ease-out 0.6s both;
|
||||
}
|
||||
|
||||
.hero-project-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(20px);
|
||||
padding: 16px 24px;
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
animation: slideInUp 0.8s ease-out 0.8s both;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.hero-project-info:hover {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
border-color: rgba(255, 255, 255, 0.4);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.project-icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.project-icon.small {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
font-size: 24px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.project-details {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.project-name {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.project-category {
|
||||
font-size: 14px;
|
||||
opacity: 0.8;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.project-button {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
color: white;
|
||||
padding: 12px 24px;
|
||||
border-radius: 12px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.project-button::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
transition: width 0.6s, height 0.6s;
|
||||
}
|
||||
|
||||
.project-button:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.project-button:hover::before {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.project-button:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.project-button.small {
|
||||
padding: 8px 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Projects Section */
|
||||
.projects-section {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 8px;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .section-title {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.section-subtitle {
|
||||
font-size: 16px;
|
||||
color: #6B7280;
|
||||
margin: 0;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .section-subtitle {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
.projects-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.large-project-card {
|
||||
border-radius: 20px;
|
||||
padding: 32px;
|
||||
color: white;
|
||||
min-height: 300px;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
cursor: pointer;
|
||||
transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.large-project-card:hover {
|
||||
transform: translateY(-6px) scale(1.02);
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.large-project-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 50%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.card-badge {
|
||||
display: inline-block;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
padding: 6px 12px;
|
||||
border-radius: 16px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 12px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.card-description {
|
||||
font-size: 14px;
|
||||
margin-bottom: 24px;
|
||||
opacity: 0.9;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.card-project-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(20px);
|
||||
padding: 12px 16px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.small-projects-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.small-project-card {
|
||||
background: white;
|
||||
padding: 24px;
|
||||
border-radius: 16px;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
animation: slideInUp 0.6s ease-out both;
|
||||
}
|
||||
|
||||
.small-project-card:nth-child(1) { animation-delay: 0.1s; }
|
||||
.small-project-card:nth-child(2) { animation-delay: 0.2s; }
|
||||
.small-project-card:nth-child(3) { animation-delay: 0.3s; }
|
||||
.small-project-card:nth-child(4) { animation-delay: 0.4s; }
|
||||
|
||||
:global(.dark) .small-project-card {
|
||||
background: rgba(28, 28, 30, 0.8);
|
||||
color: #f5f5f7;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.small-project-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
:global(.dark) .small-project-card:hover {
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -2px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.small-card-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 24px;
|
||||
margin: 0 auto 16px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.small-card-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.small-card-category {
|
||||
font-size: 14px;
|
||||
color: #6B7280;
|
||||
margin-bottom: 16px;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .small-card-category {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
.small-card-button {
|
||||
background: #007AFF;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 16px;
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.small-card-button:hover {
|
||||
background: #0056CC;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* Services Section */
|
||||
.services-section {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.services-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.service-card {
|
||||
background: white;
|
||||
padding: 32px 24px;
|
||||
border-radius: 16px;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
animation: slideInUp 0.6s ease-out both;
|
||||
}
|
||||
|
||||
.service-card:nth-child(1) { animation-delay: 0.2s; }
|
||||
.service-card:nth-child(2) { animation-delay: 0.3s; }
|
||||
.service-card:nth-child(3) { animation-delay: 0.4s; }
|
||||
.service-card:nth-child(4) { animation-delay: 0.5s; }
|
||||
|
||||
:global(.dark) .service-card {
|
||||
background: rgba(28, 28, 30, 0.8);
|
||||
color: #f5f5f7;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.service-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
:global(.dark) .service-card:hover {
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -2px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.service-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.service-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.service-description {
|
||||
font-size: 14px;
|
||||
color: #6B7280;
|
||||
line-height: 1.5;
|
||||
margin: 0;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .service-description {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.hero-card {
|
||||
padding: 32px 24px;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.hero-description {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.hero-project-info {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.projects-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.small-projects-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.services-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
587
src/routes/about/+page.svelte
Normal file
587
src/routes/about/+page.svelte
Normal file
@@ -0,0 +1,587 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
const skills = [
|
||||
{ name: 'Brand Identity', level: 95, icon: '🎨' },
|
||||
{ name: 'UI/UX Design', level: 90, icon: '📱' },
|
||||
{ name: 'Web Development', level: 85, icon: '💻' },
|
||||
{ name: 'Print Design', level: 88, icon: '📄' },
|
||||
{ name: 'Photography', level: 80, icon: '📸' },
|
||||
{ name: 'Illustration', level: 75, icon: '🖼️' }
|
||||
];
|
||||
|
||||
const timeline = [
|
||||
{
|
||||
year: '2024',
|
||||
title: 'Founded LiuBai Design',
|
||||
description: 'Established creative studio focusing on modern brand identity and digital experiences.'
|
||||
},
|
||||
{
|
||||
year: '2023',
|
||||
title: 'Senior Designer at Tech Corp',
|
||||
description: 'Led design team for major product launches and brand redesign initiatives.'
|
||||
},
|
||||
{
|
||||
year: '2022',
|
||||
title: 'Freelance Designer',
|
||||
description: 'Worked with various startups and established companies on branding and web design projects.'
|
||||
},
|
||||
{
|
||||
year: '2021',
|
||||
title: 'Design Degree Completed',
|
||||
description: 'Graduated with honors in Visual Communication Design from Design University.'
|
||||
}
|
||||
];
|
||||
|
||||
onMount(() => {
|
||||
console.log('About page mounted');
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>About - LiuBai Design</title>
|
||||
<meta name="description" content="Learn about LiuBai Design studio and our creative approach" />
|
||||
</svelte:head>
|
||||
|
||||
<div class="about-page">
|
||||
<!-- Hero Section -->
|
||||
<section class="hero-section">
|
||||
<div class="hero-content">
|
||||
<div class="hero-avatar">
|
||||
<div class="avatar-icon">🎨</div>
|
||||
</div>
|
||||
<h1 class="hero-title">About LiuBai Design</h1>
|
||||
<p class="hero-description">
|
||||
We are a creative studio passionate about crafting meaningful brand experiences
|
||||
and digital solutions that connect with people and drive results.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Story Section -->
|
||||
<section class="story-section">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">Our Story</h2>
|
||||
</div>
|
||||
<div class="story-content">
|
||||
<p class="story-text">
|
||||
Founded in 2024, LiuBai Design emerged from a passion for creating visual experiences
|
||||
that not only look beautiful but also serve a purpose. We believe that great design
|
||||
is the perfect balance between aesthetics and functionality.
|
||||
</p>
|
||||
<p class="story-text">
|
||||
Our approach combines strategic thinking with creative execution, ensuring that every
|
||||
project we undertake delivers both visual impact and measurable results for our clients.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Skills Section -->
|
||||
<section class="skills-section">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">What We Do</h2>
|
||||
<p class="section-subtitle">Our areas of expertise</p>
|
||||
</div>
|
||||
<div class="skills-grid">
|
||||
{#each skills as skill, index}
|
||||
<div class="skill-card" style="animation-delay: {index * 0.1}s">
|
||||
<div class="skill-icon">{skill.icon}</div>
|
||||
<h3 class="skill-name">{skill.name}</h3>
|
||||
<div class="skill-bar">
|
||||
<div class="skill-progress" style="width: {skill.level}%"></div>
|
||||
</div>
|
||||
<span class="skill-level">{skill.level}%</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Timeline Section -->
|
||||
<section class="timeline-section">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">Our Journey</h2>
|
||||
<p class="section-subtitle">Key milestones in our creative journey</p>
|
||||
</div>
|
||||
<div class="timeline">
|
||||
{#each timeline as item, index}
|
||||
<div class="timeline-item" style="animation-delay: {index * 0.2}s">
|
||||
<div class="timeline-marker"></div>
|
||||
<div class="timeline-content">
|
||||
<div class="timeline-year">{item.year}</div>
|
||||
<h3 class="timeline-title">{item.title}</h3>
|
||||
<p class="timeline-description">{item.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Values Section -->
|
||||
<section class="values-section">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">Our Values</h2>
|
||||
</div>
|
||||
<div class="values-grid">
|
||||
<div class="value-card">
|
||||
<div class="value-icon">💡</div>
|
||||
<h3 class="value-title">Innovation</h3>
|
||||
<p class="value-description">
|
||||
We constantly explore new design trends and technologies to deliver cutting-edge solutions.
|
||||
</p>
|
||||
</div>
|
||||
<div class="value-card">
|
||||
<div class="value-icon">🤝</div>
|
||||
<h3 class="value-title">Collaboration</h3>
|
||||
<p class="value-description">
|
||||
We work closely with our clients as partners to understand their vision and goals.
|
||||
</p>
|
||||
</div>
|
||||
<div class="value-card">
|
||||
<div class="value-icon">⭐</div>
|
||||
<h3 class="value-title">Excellence</h3>
|
||||
<p class="value-description">
|
||||
We strive for perfection in every detail and never compromise on quality.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contact CTA -->
|
||||
<section class="cta-section">
|
||||
<div class="cta-content">
|
||||
<h2 class="cta-title">Ready to Work Together?</h2>
|
||||
<p class="cta-description">
|
||||
Let's create something amazing together. Get in touch to discuss your project.
|
||||
</p>
|
||||
<button class="cta-button" on:click={() => window.location.href = '/contact'}>
|
||||
Get In Touch
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.about-page {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
animation: fadeIn 0.6s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Hero Section */
|
||||
.hero-section {
|
||||
text-align: center;
|
||||
margin-bottom: 64px;
|
||||
}
|
||||
|
||||
.hero-avatar {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 32px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero-avatar::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, rgba(255,255,255,0.2) 0%, rgba(255,255,255,0) 50%);
|
||||
}
|
||||
|
||||
.avatar-icon {
|
||||
font-size: 48px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: 48px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 16px;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .hero-title {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.hero-description {
|
||||
font-size: 20px;
|
||||
color: #6B7280;
|
||||
line-height: 1.6;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .hero-description {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
/* Section Headers */
|
||||
.section-header {
|
||||
text-align: center;
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 36px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 8px;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .section-title {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.section-subtitle {
|
||||
font-size: 16px;
|
||||
color: #6B7280;
|
||||
margin: 0;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .section-subtitle {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
/* Story Section */
|
||||
.story-section {
|
||||
margin-bottom: 80px;
|
||||
}
|
||||
|
||||
.story-content {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.story-text {
|
||||
font-size: 18px;
|
||||
color: #374151;
|
||||
line-height: 1.7;
|
||||
margin-bottom: 24px;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .story-text {
|
||||
color: #D1D5DB;
|
||||
}
|
||||
|
||||
/* Skills Section */
|
||||
.skills-section {
|
||||
margin-bottom: 80px;
|
||||
}
|
||||
|
||||
.skills-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.skill-card {
|
||||
background: white;
|
||||
padding: 32px 24px;
|
||||
border-radius: 20px;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
animation: slideInUp 0.6s ease-out both;
|
||||
}
|
||||
|
||||
:global(.dark) .skill-card {
|
||||
background: rgba(28, 28, 30, 0.8);
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.skill-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.skill-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.skill-name {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 16px;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .skill-name {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.skill-bar {
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
background: #f3f4f6;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
:global(.dark) .skill-bar {
|
||||
background: #374151;
|
||||
}
|
||||
|
||||
.skill-progress {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #007AFF 0%, #00C7FF 100%);
|
||||
border-radius: 4px;
|
||||
transition: width 1s ease-out 0.5s;
|
||||
}
|
||||
|
||||
.skill-level {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #007AFF;
|
||||
}
|
||||
|
||||
/* Timeline Section */
|
||||
.timeline-section {
|
||||
margin-bottom: 80px;
|
||||
}
|
||||
|
||||
.timeline {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.timeline::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 2px;
|
||||
background: #e5e7eb;
|
||||
}
|
||||
|
||||
:global(.dark) .timeline::before {
|
||||
background: #374151;
|
||||
}
|
||||
|
||||
.timeline-item {
|
||||
position: relative;
|
||||
padding-left: 60px;
|
||||
margin-bottom: 48px;
|
||||
animation: slideInLeft 0.6s ease-out both;
|
||||
}
|
||||
|
||||
.timeline-marker {
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
top: 8px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: #007AFF;
|
||||
border-radius: 50%;
|
||||
border: 3px solid white;
|
||||
box-shadow: 0 0 0 3px #e5e7eb;
|
||||
}
|
||||
|
||||
:global(.dark) .timeline-marker {
|
||||
border-color: rgba(28, 28, 30, 0.8);
|
||||
box-shadow: 0 0 0 3px #374151;
|
||||
}
|
||||
|
||||
.timeline-year {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #007AFF;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.timeline-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .timeline-title {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.timeline-description {
|
||||
font-size: 16px;
|
||||
color: #6B7280;
|
||||
line-height: 1.5;
|
||||
margin: 0;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .timeline-description {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
/* Values Section */
|
||||
.values-section {
|
||||
margin-bottom: 80px;
|
||||
}
|
||||
|
||||
.values-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 32px;
|
||||
}
|
||||
|
||||
.value-card {
|
||||
text-align: center;
|
||||
padding: 32px 24px;
|
||||
}
|
||||
|
||||
.value-icon {
|
||||
font-size: 64px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.value-title {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 16px;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .value-title {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.value-description {
|
||||
font-size: 16px;
|
||||
color: #6B7280;
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .value-description {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
/* CTA Section */
|
||||
.cta-section {
|
||||
text-align: center;
|
||||
padding: 64px 32px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 24px;
|
||||
color: white;
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.cta-title {
|
||||
font-size: 36px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.cta-description {
|
||||
font-size: 18px;
|
||||
margin-bottom: 32px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.cta-button {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||
color: white;
|
||||
padding: 16px 32px;
|
||||
border-radius: 12px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.cta-button:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
border-color: rgba(255, 255, 255, 0.5);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
@keyframes slideInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInLeft {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.hero-title {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.skills-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.values-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.timeline {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.timeline-item {
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
.cta-section {
|
||||
padding: 48px 24px;
|
||||
}
|
||||
|
||||
.cta-title {
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
667
src/routes/contact/+page.svelte
Normal file
667
src/routes/contact/+page.svelte
Normal file
@@ -0,0 +1,667 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
let formData = {
|
||||
name: '',
|
||||
email: '',
|
||||
company: '',
|
||||
project: '',
|
||||
budget: '',
|
||||
message: ''
|
||||
};
|
||||
|
||||
let isSubmitting = false;
|
||||
let submitMessage = '';
|
||||
|
||||
const budgetOptions = [
|
||||
'Under $5,000',
|
||||
'$5,000 - $10,000',
|
||||
'$10,000 - $25,000',
|
||||
'$25,000 - $50,000',
|
||||
'Over $50,000'
|
||||
];
|
||||
|
||||
const projectTypes = [
|
||||
'Brand Identity',
|
||||
'Web Design',
|
||||
'Mobile App',
|
||||
'Print Design',
|
||||
'Photography',
|
||||
'Other'
|
||||
];
|
||||
|
||||
async function handleSubmit() {
|
||||
isSubmitting = true;
|
||||
|
||||
// 模拟表单提交
|
||||
try {
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
// 这里应该是实际的表单提交逻辑
|
||||
console.log('Form submitted:', formData);
|
||||
|
||||
submitMessage = 'Thank you for your message! We\'ll get back to you within 24 hours.';
|
||||
|
||||
// 重置表单
|
||||
formData = {
|
||||
name: '',
|
||||
email: '',
|
||||
company: '',
|
||||
project: '',
|
||||
budget: '',
|
||||
message: ''
|
||||
};
|
||||
} catch (error) {
|
||||
submitMessage = 'Sorry, there was an error sending your message. Please try again.';
|
||||
} finally {
|
||||
isSubmitting = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
console.log('Contact page mounted');
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Contact - LiuBai Design</title>
|
||||
<meta name="description" content="Get in touch with LiuBai Design for your next creative project" />
|
||||
</svelte:head>
|
||||
|
||||
<div class="contact-page">
|
||||
<!-- Hero Section -->
|
||||
<section class="hero-section">
|
||||
<div class="hero-content">
|
||||
<h1 class="hero-title">Let's Create Something Amazing</h1>
|
||||
<p class="hero-description">
|
||||
Ready to bring your vision to life? We'd love to hear about your project
|
||||
and discuss how we can help you achieve your goals.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="contact-content">
|
||||
<!-- Contact Form -->
|
||||
<div class="form-section">
|
||||
<div class="form-header">
|
||||
<h2 class="form-title">Tell Us About Your Project</h2>
|
||||
<p class="form-description">
|
||||
Fill out the form below and we'll get back to you within 24 hours.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{#if submitMessage}
|
||||
<div class="submit-message" class:success={submitMessage.includes('Thank you')} class:error={submitMessage.includes('error')}>
|
||||
{submitMessage}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<form class="contact-form" on:submit|preventDefault={handleSubmit}>
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="name" class="form-label">Name *</label>
|
||||
<input
|
||||
type="text"
|
||||
id="name"
|
||||
bind:value={formData.name}
|
||||
class="form-input"
|
||||
required
|
||||
placeholder="Your full name"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email" class="form-label">Email *</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
bind:value={formData.email}
|
||||
class="form-input"
|
||||
required
|
||||
placeholder="your@email.com"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="company" class="form-label">Company</label>
|
||||
<input
|
||||
type="text"
|
||||
id="company"
|
||||
bind:value={formData.company}
|
||||
class="form-input"
|
||||
placeholder="Your company name"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="project" class="form-label">Project Type</label>
|
||||
<select id="project" bind:value={formData.project} class="form-select">
|
||||
<option value="">Select project type</option>
|
||||
{#each projectTypes as type}
|
||||
<option value={type}>{type}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="budget" class="form-label">Budget Range</label>
|
||||
<select id="budget" bind:value={formData.budget} class="form-select">
|
||||
<option value="">Select budget range</option>
|
||||
{#each budgetOptions as budget}
|
||||
<option value={budget}>{budget}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="message" class="form-label">Project Details *</label>
|
||||
<textarea
|
||||
id="message"
|
||||
bind:value={formData.message}
|
||||
class="form-textarea"
|
||||
required
|
||||
placeholder="Tell us about your project, goals, timeline, and any specific requirements..."
|
||||
rows="6"
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="submit-button"
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
{#if isSubmitting}
|
||||
<span class="loading-spinner">⏳</span>
|
||||
Sending...
|
||||
{:else}
|
||||
Send Message
|
||||
{/if}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Contact Info -->
|
||||
<div class="info-section">
|
||||
<div class="info-card">
|
||||
<h3 class="info-title">Get In Touch</h3>
|
||||
<div class="contact-methods">
|
||||
<div class="contact-method">
|
||||
<div class="method-icon">📧</div>
|
||||
<div class="method-content">
|
||||
<div class="method-label">Email</div>
|
||||
<div class="method-value">hello@liubaidesign.com</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="contact-method">
|
||||
<div class="method-icon">📱</div>
|
||||
<div class="method-content">
|
||||
<div class="method-label">Phone</div>
|
||||
<div class="method-value">+1 (555) 123-4567</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="contact-method">
|
||||
<div class="method-icon">📍</div>
|
||||
<div class="method-content">
|
||||
<div class="method-label">Location</div>
|
||||
<div class="method-value">San Francisco, CA</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-card">
|
||||
<h3 class="info-title">What Happens Next?</h3>
|
||||
<div class="process-steps">
|
||||
<div class="process-step">
|
||||
<div class="step-number">1</div>
|
||||
<div class="step-content">
|
||||
<div class="step-title">We Review</div>
|
||||
<div class="step-description">We'll review your project details and requirements</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-step">
|
||||
<div class="step-number">2</div>
|
||||
<div class="step-content">
|
||||
<div class="step-title">We Connect</div>
|
||||
<div class="step-description">Schedule a call to discuss your vision and goals</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-step">
|
||||
<div class="step-number">3</div>
|
||||
<div class="step-content">
|
||||
<div class="step-title">We Propose</div>
|
||||
<div class="step-description">Receive a detailed proposal and timeline</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-card">
|
||||
<h3 class="info-title">Follow Us</h3>
|
||||
<div class="social-links">
|
||||
<a href="#" class="social-link">
|
||||
<div class="social-icon">📘</div>
|
||||
<span>Facebook</span>
|
||||
</a>
|
||||
<a href="#" class="social-link">
|
||||
<div class="social-icon">📷</div>
|
||||
<span>Instagram</span>
|
||||
</a>
|
||||
<a href="#" class="social-link">
|
||||
<div class="social-icon">🐦</div>
|
||||
<span>Twitter</span>
|
||||
</a>
|
||||
<a href="#" class="social-link">
|
||||
<div class="social-icon">💼</div>
|
||||
<span>LinkedIn</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.contact-page {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
animation: fadeIn 0.6s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Hero Section */
|
||||
.hero-section {
|
||||
text-align: center;
|
||||
margin-bottom: 64px;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: 48px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 16px;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .hero-title {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.hero-description {
|
||||
font-size: 20px;
|
||||
color: #6B7280;
|
||||
line-height: 1.6;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .hero-description {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
/* Contact Content */
|
||||
.contact-content {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr;
|
||||
gap: 48px;
|
||||
}
|
||||
|
||||
/* Form Section */
|
||||
.form-section {
|
||||
background: white;
|
||||
padding: 48px;
|
||||
border-radius: 24px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .form-section {
|
||||
background: rgba(28, 28, 30, 0.8);
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.form-header {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.form-title {
|
||||
font-size: 32px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 8px;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .form-title {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.form-description {
|
||||
font-size: 16px;
|
||||
color: #6B7280;
|
||||
margin: 0;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .form-description {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
.submit-message {
|
||||
padding: 16px;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 24px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.submit-message.success {
|
||||
background: #dcfce7;
|
||||
color: #166534;
|
||||
border: 1px solid #bbf7d0;
|
||||
}
|
||||
|
||||
.submit-message.error {
|
||||
background: #fef2f2;
|
||||
color: #dc2626;
|
||||
border: 1px solid #fecaca;
|
||||
}
|
||||
|
||||
:global(.dark) .submit-message.success {
|
||||
background: rgba(34, 197, 94, 0.1);
|
||||
color: #22c55e;
|
||||
border-color: rgba(34, 197, 94, 0.3);
|
||||
}
|
||||
|
||||
:global(.dark) .submit-message.error {
|
||||
background: rgba(239, 68, 68, 0.1);
|
||||
color: #ef4444;
|
||||
border-color: rgba(239, 68, 68, 0.3);
|
||||
}
|
||||
|
||||
/* Form Styles */
|
||||
.contact-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #374151;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .form-label {
|
||||
color: #D1D5DB;
|
||||
}
|
||||
|
||||
.form-input,
|
||||
.form-select,
|
||||
.form-textarea {
|
||||
padding: 16px;
|
||||
border: 2px solid #e5e7eb;
|
||||
border-radius: 12px;
|
||||
font-size: 16px;
|
||||
transition: all 0.3s ease;
|
||||
background: white;
|
||||
color: #1d1d1f;
|
||||
}
|
||||
|
||||
:global(.dark) .form-input,
|
||||
:global(.dark) .form-select,
|
||||
:global(.dark) .form-textarea {
|
||||
background: rgba(55, 65, 81, 0.5);
|
||||
border-color: #4B5563;
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.form-input:focus,
|
||||
.form-select:focus,
|
||||
.form-textarea:focus {
|
||||
outline: none;
|
||||
border-color: #007AFF;
|
||||
box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.1);
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
resize: vertical;
|
||||
min-height: 120px;
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
background: #007AFF;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 18px 32px;
|
||||
border-radius: 12px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.submit-button:hover:not(:disabled) {
|
||||
background: #0056CC;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.submit-button:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* Info Section */
|
||||
.info-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
background: white;
|
||||
padding: 32px 24px;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .info-card {
|
||||
background: rgba(28, 28, 30, 0.8);
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.info-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 20px;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .info-title {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
/* Contact Methods */
|
||||
.contact-methods {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.contact-method {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.method-icon {
|
||||
font-size: 24px;
|
||||
width: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.method-label {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #9CA3AF;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.method-value {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .method-value {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
/* Process Steps */
|
||||
.process-steps {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.process-step {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.step-number {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: #007AFF;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.step-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #1d1d1f;
|
||||
margin-bottom: 4px;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .step-title {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.step-description {
|
||||
font-size: 12px;
|
||||
color: #6B7280;
|
||||
line-height: 1.4;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .step-description {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
/* Social Links */
|
||||
.social-links {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.social-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 8px 0;
|
||||
color: #1d1d1f;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .social-link {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.social-link:hover {
|
||||
color: #007AFF;
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.social-icon {
|
||||
font-size: 20px;
|
||||
width: 32px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.contact-content {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 32px;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
padding: 32px 24px;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.form-title {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
410
src/routes/projects/+page.svelte
Normal file
410
src/routes/projects/+page.svelte
Normal file
@@ -0,0 +1,410 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
// 项目数据
|
||||
const projects = [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Creative Brand Identity',
|
||||
category: 'Brand Design',
|
||||
description: 'Complete visual identity system for modern brands',
|
||||
image: '🎨',
|
||||
tags: ['Logo Design', 'Brand Guidelines', 'Typography'],
|
||||
status: 'Completed',
|
||||
client: 'Tech Startup',
|
||||
year: '2024'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Mobile App Interface',
|
||||
category: 'UI/UX Design',
|
||||
description: 'Modern mobile interface with focus on user experience',
|
||||
image: '📱',
|
||||
tags: ['Mobile Design', 'User Experience', 'Prototyping'],
|
||||
status: 'In Progress',
|
||||
client: 'E-commerce Platform',
|
||||
year: '2024'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Web Portfolio',
|
||||
category: 'Web Design',
|
||||
description: 'Responsive portfolio website with modern aesthetics',
|
||||
image: '💻',
|
||||
tags: ['Web Development', 'Responsive Design', 'Animation'],
|
||||
status: 'Completed',
|
||||
client: 'Creative Agency',
|
||||
year: '2023'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: 'Print Design Collection',
|
||||
category: 'Graphic Design',
|
||||
description: 'Various print materials including brochures and posters',
|
||||
image: '📄',
|
||||
tags: ['Print Design', 'Layout', 'Typography'],
|
||||
status: 'Completed',
|
||||
client: 'Local Business',
|
||||
year: '2023'
|
||||
}
|
||||
];
|
||||
|
||||
let selectedCategory = 'All';
|
||||
const categories = ['All', 'Brand Design', 'UI/UX Design', 'Web Design', 'Graphic Design'];
|
||||
|
||||
$: filteredProjects = selectedCategory === 'All'
|
||||
? projects
|
||||
: projects.filter(project => project.category === selectedCategory);
|
||||
|
||||
function navigateToProject(projectId: number) {
|
||||
goto(`/projects/${projectId}`);
|
||||
}
|
||||
|
||||
function selectCategory(category: string) {
|
||||
selectedCategory = category;
|
||||
// 更新URL参数
|
||||
const url = new URL(window.location.href);
|
||||
if (category === 'All') {
|
||||
url.searchParams.delete('category');
|
||||
} else {
|
||||
url.searchParams.set('category', category);
|
||||
}
|
||||
goto(url.pathname + url.search, { replaceState: true });
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
// 从URL参数读取分类
|
||||
const urlCategory = $page.url.searchParams.get('category');
|
||||
if (urlCategory && categories.includes(urlCategory)) {
|
||||
selectedCategory = urlCategory;
|
||||
}
|
||||
console.log('Projects page mounted');
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Projects - LiuBai Design</title>
|
||||
<meta name="description" content="Explore our creative projects and design portfolio" />
|
||||
</svelte:head>
|
||||
|
||||
<div class="projects-page">
|
||||
<header class="page-header">
|
||||
<h1 class="page-title">Projects</h1>
|
||||
<p class="page-subtitle">Explore our creative works and design solutions</p>
|
||||
</header>
|
||||
|
||||
<!-- 分类筛选 -->
|
||||
<div class="filter-section">
|
||||
<div class="filter-tabs">
|
||||
{#each categories as category}
|
||||
<button
|
||||
class="filter-tab"
|
||||
class:active={selectedCategory === category}
|
||||
on:click={() => selectCategory(category)}
|
||||
>
|
||||
{category}
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 项目网格 -->
|
||||
<div class="projects-grid">
|
||||
{#each filteredProjects as project (project.id)}
|
||||
<div class="project-card" on:click={() => navigateToProject(project.id)} role="button" tabindex="0">
|
||||
<div class="project-image">
|
||||
<div class="project-icon">{project.image}</div>
|
||||
<div class="project-status" class:completed={project.status === 'Completed'}>
|
||||
{project.status}
|
||||
</div>
|
||||
</div>
|
||||
<div class="project-content">
|
||||
<div class="project-category">{project.category}</div>
|
||||
<h3 class="project-title">{project.title}</h3>
|
||||
<p class="project-description">{project.description}</p>
|
||||
<div class="project-meta">
|
||||
<span class="project-client">{project.client}</span>
|
||||
<span class="project-year">{project.year}</span>
|
||||
</div>
|
||||
<div class="project-tags">
|
||||
{#each project.tags as tag}
|
||||
<span class="tag">{tag}</span>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
{#if filteredProjects.length === 0}
|
||||
<div class="empty-state">
|
||||
<div class="empty-icon">🔍</div>
|
||||
<h3>No projects found</h3>
|
||||
<p>Try selecting a different category</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.projects-page {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
animation: fadeIn 0.6s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.page-header {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 48px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 8px;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .page-title {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
font-size: 18px;
|
||||
color: #6B7280;
|
||||
margin: 0;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .page-subtitle {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.filter-tabs {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.filter-tab {
|
||||
padding: 12px 24px;
|
||||
border: 2px solid #e5e7eb;
|
||||
background: white;
|
||||
border-radius: 25px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
color: #374151;
|
||||
}
|
||||
|
||||
:global(.dark) .filter-tab {
|
||||
background: rgba(28, 28, 30, 0.8);
|
||||
border-color: #374151;
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
.filter-tab:hover {
|
||||
border-color: #007AFF;
|
||||
color: #007AFF;
|
||||
}
|
||||
|
||||
.filter-tab.active {
|
||||
background: #007AFF;
|
||||
border-color: #007AFF;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.projects-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
|
||||
gap: 24px;
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.project-card {
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
cursor: pointer;
|
||||
animation: slideInUp 0.6s ease-out both;
|
||||
}
|
||||
|
||||
:global(.dark) .project-card {
|
||||
background: rgba(28, 28, 30, 0.8);
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.project-card:hover {
|
||||
transform: translateY(-8px);
|
||||
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
:global(.dark) .project-card:hover {
|
||||
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.4), 0 10px 10px -5px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.project-image {
|
||||
height: 200px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.project-icon {
|
||||
font-size: 64px;
|
||||
}
|
||||
|
||||
.project-status {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
padding: 6px 12px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
backdrop-filter: blur(10px);
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.project-status.completed {
|
||||
background: rgba(34, 197, 94, 0.2);
|
||||
color: #22c55e;
|
||||
}
|
||||
|
||||
.project-content {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.project-category {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #007AFF;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.project-title {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 8px;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .project-title {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.project-description {
|
||||
font-size: 14px;
|
||||
color: #6B7280;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 16px;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .project-description {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
.project-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
font-size: 12px;
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
.project-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.tag {
|
||||
padding: 4px 8px;
|
||||
background: #f3f4f6;
|
||||
border-radius: 8px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
color: #374151;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .tag {
|
||||
background: #374151;
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 64px 24px;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 64px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.empty-state h3 {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .empty-state h3 {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.empty-state p {
|
||||
color: #6B7280;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .empty-state p {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.projects-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.filter-tabs {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.filter-tab {
|
||||
padding: 10px 20px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
569
src/routes/projects/[id]/+page.svelte
Normal file
569
src/routes/projects/[id]/+page.svelte
Normal file
@@ -0,0 +1,569 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
// 项目数据(实际应用中应该从API获取)
|
||||
const projectsData = {
|
||||
'1': {
|
||||
id: 1,
|
||||
title: 'Creative Brand Identity',
|
||||
category: 'Brand Design',
|
||||
description: 'A comprehensive brand identity system featuring logo design, color palettes, typography, and brand guidelines for a modern tech startup.',
|
||||
image: '🎨',
|
||||
client: 'Tech Startup',
|
||||
year: '2024',
|
||||
duration: '3 months',
|
||||
status: 'Completed',
|
||||
tags: ['Logo Design', 'Brand Guidelines', 'Typography', 'Color Theory'],
|
||||
challenge: 'Create a modern, memorable brand identity that reflects innovation and trustworthiness while appealing to both B2B and B2C audiences.',
|
||||
solution: 'Developed a clean, geometric logo with a vibrant color palette and comprehensive brand guidelines that ensure consistency across all touchpoints.',
|
||||
results: 'Increased brand recognition by 150% and improved customer engagement across digital platforms.',
|
||||
gallery: ['🎨', '🖼️', '📊', '📱', '💻', '📄']
|
||||
},
|
||||
'2': {
|
||||
id: 2,
|
||||
title: 'Mobile App Interface',
|
||||
category: 'UI/UX Design',
|
||||
description: 'Modern mobile interface design with focus on user experience and accessibility for an e-commerce platform.',
|
||||
image: '📱',
|
||||
client: 'E-commerce Platform',
|
||||
year: '2024',
|
||||
duration: '4 months',
|
||||
status: 'In Progress',
|
||||
tags: ['Mobile Design', 'User Experience', 'Prototyping', 'Accessibility'],
|
||||
challenge: 'Design an intuitive shopping experience that reduces cart abandonment and improves conversion rates.',
|
||||
solution: 'Created a streamlined user flow with clear navigation, optimized product discovery, and simplified checkout process.',
|
||||
results: 'Currently in development phase with promising user testing results showing 40% improvement in task completion.',
|
||||
gallery: ['📱', '🛒', '💳', '🔍', '⭐', '📊']
|
||||
},
|
||||
'3': {
|
||||
id: 3,
|
||||
title: 'Web Portfolio',
|
||||
category: 'Web Design',
|
||||
description: 'Responsive portfolio website with modern aesthetics and smooth animations for a creative agency.',
|
||||
image: '💻',
|
||||
client: 'Creative Agency',
|
||||
year: '2023',
|
||||
duration: '2 months',
|
||||
status: 'Completed',
|
||||
tags: ['Web Development', 'Responsive Design', 'Animation', 'Performance'],
|
||||
challenge: 'Create a visually stunning portfolio that showcases work effectively while maintaining fast loading times.',
|
||||
solution: 'Implemented a clean, grid-based layout with optimized images and smooth CSS animations.',
|
||||
results: 'Achieved 95+ PageSpeed score and increased client inquiries by 200%.',
|
||||
gallery: ['💻', '🎨', '📸', '🎬', '📱', '⚡']
|
||||
},
|
||||
'4': {
|
||||
id: 4,
|
||||
title: 'Print Design Collection',
|
||||
category: 'Graphic Design',
|
||||
description: 'Various print materials including brochures, posters, and business cards for local businesses.',
|
||||
image: '📄',
|
||||
client: 'Local Business',
|
||||
year: '2023',
|
||||
duration: '1 month',
|
||||
status: 'Completed',
|
||||
tags: ['Print Design', 'Layout', 'Typography', 'Brand Consistency'],
|
||||
challenge: 'Create cohesive print materials that work across different formats and maintain brand consistency.',
|
||||
solution: 'Developed a flexible design system that adapts to various print formats while maintaining visual hierarchy.',
|
||||
results: 'Improved brand perception and increased foot traffic by 30%.',
|
||||
gallery: ['📄', '📰', '🏷️', '📋', '📊', '🎨']
|
||||
}
|
||||
};
|
||||
|
||||
$: projectId = $page.params.id;
|
||||
$: project = projectsData[projectId];
|
||||
|
||||
function goBack() {
|
||||
window.history.back();
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
if (!project) {
|
||||
// 如果项目不存在,重定向到项目列表页
|
||||
window.location.href = '/projects';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{project?.title || 'Project'} - LiuBai Design</title>
|
||||
<meta name="description" content={project?.description || 'Project details'} />
|
||||
</svelte:head>
|
||||
|
||||
{#if project}
|
||||
<div class="project-detail">
|
||||
<!-- 返回按钮 -->
|
||||
<button class="back-button" on:click={goBack}>
|
||||
← Back to Projects
|
||||
</button>
|
||||
|
||||
<!-- 项目头部 -->
|
||||
<header class="project-header">
|
||||
<div class="project-hero">
|
||||
<div class="project-hero-image">
|
||||
<div class="hero-icon">{project.image}</div>
|
||||
</div>
|
||||
<div class="project-hero-content">
|
||||
<div class="project-category">{project.category}</div>
|
||||
<h1 class="project-title">{project.title}</h1>
|
||||
<p class="project-description">{project.description}</p>
|
||||
|
||||
<div class="project-meta-grid">
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">Client</span>
|
||||
<span class="meta-value">{project.client}</span>
|
||||
</div>
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">Year</span>
|
||||
<span class="meta-value">{project.year}</span>
|
||||
</div>
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">Duration</span>
|
||||
<span class="meta-value">{project.duration}</span>
|
||||
</div>
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">Status</span>
|
||||
<span class="meta-value status" class:completed={project.status === 'Completed'}>
|
||||
{project.status}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="project-tags">
|
||||
{#each project.tags as tag}
|
||||
<span class="tag">{tag}</span>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- 项目内容 -->
|
||||
<div class="project-content">
|
||||
<div class="content-section">
|
||||
<h2>Challenge</h2>
|
||||
<p>{project.challenge}</p>
|
||||
</div>
|
||||
|
||||
<div class="content-section">
|
||||
<h2>Solution</h2>
|
||||
<p>{project.solution}</p>
|
||||
</div>
|
||||
|
||||
<div class="content-section">
|
||||
<h2>Results</h2>
|
||||
<p>{project.results}</p>
|
||||
</div>
|
||||
|
||||
<div class="content-section">
|
||||
<h2>Gallery</h2>
|
||||
<div class="gallery-grid">
|
||||
{#each project.gallery as item, index}
|
||||
<div class="gallery-item" style="animation-delay: {index * 0.1}s">
|
||||
<div class="gallery-icon">{item}</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 相关项目 -->
|
||||
<div class="related-projects">
|
||||
<h2>More Projects</h2>
|
||||
<div class="related-grid">
|
||||
{#each Object.values(projectsData).filter(p => p.id !== project.id).slice(0, 3) as relatedProject}
|
||||
<div class="related-card" on:click={() => window.location.href = `/projects/${relatedProject.id}`}>
|
||||
<div class="related-image">
|
||||
<div class="related-icon">{relatedProject.image}</div>
|
||||
</div>
|
||||
<div class="related-content">
|
||||
<div class="related-category">{relatedProject.category}</div>
|
||||
<h3 class="related-title">{relatedProject.title}</h3>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="loading">
|
||||
<div class="loading-spinner">🔄</div>
|
||||
<p>Loading project...</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.project-detail {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
animation: fadeIn 0.6s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.back-button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 0;
|
||||
background: none;
|
||||
border: none;
|
||||
color: #007AFF;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.back-button:hover {
|
||||
color: #0056CC;
|
||||
transform: translateX(-4px);
|
||||
}
|
||||
|
||||
.project-header {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.project-hero {
|
||||
display: grid;
|
||||
grid-template-columns: 300px 1fr;
|
||||
gap: 48px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.project-hero-image {
|
||||
aspect-ratio: 1;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.project-hero-image::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 50%);
|
||||
}
|
||||
|
||||
.hero-icon {
|
||||
font-size: 120px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.project-category {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #007AFF;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.project-title {
|
||||
font-size: 48px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 16px;
|
||||
color: #1d1d1f;
|
||||
line-height: 1.2;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .project-title {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.project-description {
|
||||
font-size: 18px;
|
||||
color: #6B7280;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 32px;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .project-description {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
.project-meta-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 24px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.meta-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.meta-label {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #9CA3AF;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.meta-value {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .meta-value {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.meta-value.status {
|
||||
color: #f59e0b;
|
||||
}
|
||||
|
||||
.meta-value.status.completed {
|
||||
color: #22c55e;
|
||||
}
|
||||
|
||||
.project-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.tag {
|
||||
padding: 8px 16px;
|
||||
background: #f3f4f6;
|
||||
border-radius: 20px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: #374151;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .tag {
|
||||
background: #374151;
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
.project-content {
|
||||
margin-bottom: 64px;
|
||||
}
|
||||
|
||||
.content-section {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.content-section h2 {
|
||||
font-size: 32px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 16px;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .content-section h2 {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.content-section p {
|
||||
font-size: 16px;
|
||||
color: #6B7280;
|
||||
line-height: 1.7;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .content-section p {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
.gallery-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.gallery-item {
|
||||
aspect-ratio: 1;
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
animation: slideInUp 0.6s ease-out both;
|
||||
}
|
||||
|
||||
:global(.dark) .gallery-item {
|
||||
background: rgba(28, 28, 30, 0.8);
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.gallery-item:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.gallery-icon {
|
||||
font-size: 48px;
|
||||
}
|
||||
|
||||
.related-projects {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.related-projects h2 {
|
||||
font-size: 32px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 24px;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .related-projects h2 {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.related-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.related-card {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:global(.dark) .related-card {
|
||||
background: rgba(28, 28, 30, 0.8);
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.related-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.related-image {
|
||||
height: 150px;
|
||||
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.related-icon {
|
||||
font-size: 48px;
|
||||
}
|
||||
|
||||
.related-content {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.related-category {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #007AFF;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.related-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #1d1d1f;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.dark) .related-title {
|
||||
color: #f5f5f7;
|
||||
}
|
||||
|
||||
.loading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 400px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
font-size: 48px;
|
||||
animation: spin 1s linear infinite;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
@keyframes slideInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.project-hero {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.project-hero-image {
|
||||
max-width: 200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.hero-icon {
|
||||
font-size: 80px;
|
||||
}
|
||||
|
||||
.project-title {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.project-meta-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.gallery-grid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
|
||||
}
|
||||
|
||||
.related-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user