feat(layout): 添加 SVG 图标系统并更新侧边栏导航
- 引入 Sprite 组件统一管理 SVG 图标 - 创建 Icon 组件支持动态加载图标- 定义 icon-ids 类型确保图标引用安全- 更新 Sidebar 使用新图标组件替换 emoji - 添加 HomeIcon 和 network 图标资源- 调整侧边栏样式和宽度 - 修复 Header 按钮 title 属性替代 aria-label - 新增 IP 工具页面路由 - 添加全局阴影变量 --main-border-shadow
This commit is contained in:
36
src/lib/components/Icon.svelte
Normal file
36
src/lib/components/Icon.svelte
Normal file
@@ -0,0 +1,36 @@
|
||||
<script lang="ts">
|
||||
import type { IconId } from '$lib/types/icon-ids';
|
||||
|
||||
export let id: IconId;
|
||||
export let size: number | string ;
|
||||
export let className: string = '';
|
||||
$: dimensions = typeof size === 'number' ? `${size}px` : size;
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<svg {...$$restProps}
|
||||
role="img"
|
||||
class={className}
|
||||
aria-hidden="true"
|
||||
width={dimensions?dimensions:24}
|
||||
height={dimensions?dimensions:24}
|
||||
>
|
||||
<use href={`#${id}`} />
|
||||
</svg>
|
||||
|
||||
|
||||
|
||||
<style>
|
||||
.app-icon {
|
||||
/* 确保图标与文本基线对齐 */
|
||||
vertical-align: middle;
|
||||
/* 防止用户选择图标,提高用户体验 */
|
||||
user-select: none;
|
||||
/* 默认显示为行内块级元素 */
|
||||
display: inline-block;
|
||||
/* 确保它能响应 CSS 动画 */
|
||||
transition: color 0.2s, transform 0.2s;
|
||||
}
|
||||
</style>
|
||||
|
||||
23
src/lib/components/icon/HomeIcon.svelte
Normal file
23
src/lib/components/icon/HomeIcon.svelte
Normal file
@@ -0,0 +1,23 @@
|
||||
<script>
|
||||
</script>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" {...$$restProps}>
|
||||
<g fill="none">
|
||||
<path fill="url(#SVGkm4eqcHj)" d="M6 9h4v5H6z" />
|
||||
<path fill="url(#SVG4sqiUdhg)" d="M8.687 2.273a1 1 0 0 0-1.374 0l-4.844 4.58A1.5 1.5 0 0 0 2 7.943v4.569a1.5 1.5 0 0 0 1.5 1.5h3v-4a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v4h3a1.5 1.5 0 0 0 1.5-1.5v-4.57a1.5 1.5 0 0 0-.47-1.09z" />
|
||||
<path fill="url(#SVGbhYexcuE)" fill-rule="evenodd" d="m8.004 2.636l5.731 5.41a.75.75 0 1 0 1.03-1.091L8.86 1.382a1.25 1.25 0 0 0-1.724.007L1.23 7.059a.75.75 0 0 0 1.038 1.082z" clip-rule="evenodd" />
|
||||
<defs>
|
||||
<linearGradient id="SVGkm4eqcHj" x1="8" x2="4.796" y1="9" y2="14.698" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#944600" />
|
||||
<stop offset="1" stop-color="#cd8e02" />
|
||||
</linearGradient>
|
||||
<linearGradient id="SVG4sqiUdhg" x1="3.145" x2="14.93" y1="1.413" y2="10.981" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#ffd394" />
|
||||
<stop offset="1" stop-color="#ffb357" />
|
||||
</linearGradient>
|
||||
<linearGradient id="SVGbhYexcuE" x1="10.262" x2="6.945" y1="-.696" y2="7.895" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#ff921f" />
|
||||
<stop offset="1" stop-color="#eb4824" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</g>
|
||||
</svg>
|
||||
@@ -11,22 +11,21 @@
|
||||
</script>
|
||||
|
||||
<header class="custom-titlebar" data-tauri-drag-region>
|
||||
<div class="app-title" data-tauri-drag-region>
|
||||
|
||||
</div>
|
||||
<div class="app-title" data-tauri-drag-region></div>
|
||||
|
||||
<div class="window-controls">
|
||||
<button type="button" aria-label="最小化窗口" data-tauri-drag-region="false" class="h-btn btn-minimize" on:click={minimize}></button>
|
||||
<button type="button" title="最小化窗口" data-tauri-drag-region="false" class="h-btn btn-minimize" on:click={minimize}></button>
|
||||
<button
|
||||
type="button"
|
||||
data-tauri-drag-region="false"
|
||||
class="h-btn btn-max"
|
||||
aria-label="最大化窗口"
|
||||
title="最大化窗口"
|
||||
on:click={maximize}></button>
|
||||
<button type="button"
|
||||
data-tauri-drag-region="false"
|
||||
class="h-btn btn-close"
|
||||
aria-label="关闭窗口"
|
||||
title="关闭应用"
|
||||
on:click={closeWindow}></button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -4,26 +4,34 @@
|
||||
|
||||
// 模拟导航项数据
|
||||
// 确保对象字面量语法正确无误
|
||||
const navItems = [
|
||||
{ icon: '🏠', label: '主页', path: '/' },
|
||||
{ icon: '⭐', label: '收藏', path: '/favorites' },
|
||||
{ icon: '💬', label: '聊天', path: '/chat' },
|
||||
{ icon: '⚙️', label: '设置', path: '/settings' },
|
||||
import { goto } from '$app/navigation';
|
||||
import Icon from '$lib/components/Icon.svelte';
|
||||
import type { IconId } from '$lib/types/icon-ids';
|
||||
import HomeIcon from '$lib/components/icon/HomeIcon.svelte';
|
||||
|
||||
const navItems:[{icon: IconId, label: string, path: string}] = [
|
||||
{ icon: 'network', label: 'IP工具', path: '/iptools' },
|
||||
];
|
||||
|
||||
let activePath: string = '/'; // 明确声明类型
|
||||
|
||||
function navigate(path: string) {
|
||||
activePath = path;
|
||||
// goto(path); // 实际应用中使用 SvelteKit 的导航
|
||||
goto(path);
|
||||
console.log(`导航到: ${path}`);
|
||||
}
|
||||
</script>
|
||||
|
||||
<nav class="sidebar">
|
||||
<!-- 顶部图标/Logo -->
|
||||
<div class="sidebar-logo">
|
||||
<span role="img" aria-label="App Logo">⚛️</span>
|
||||
<div class="sidebar-logo pt-2 pb-2">
|
||||
<button type="button"
|
||||
class="cursor-pointer"
|
||||
title="回到主页"
|
||||
on:click={() => navigate('/')}>
|
||||
<HomeIcon width="24" height="24" />
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- 中间导航图标 -->
|
||||
@@ -35,7 +43,7 @@
|
||||
on:click={() => navigate(item.path)}
|
||||
title={item.label}
|
||||
>
|
||||
{item.icon}
|
||||
<Icon id={item.icon} className="hover:text-neutral-400 transition-all duration-1000" size="24" />
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
@@ -51,7 +59,7 @@
|
||||
/* 侧边栏的基础样式 */
|
||||
.sidebar {
|
||||
/* 根据图片,侧边栏宽度较窄,可能在 60px 左右 */
|
||||
width: 25px;
|
||||
width: 35px;
|
||||
min-width: 35px; /* 确保它不会收缩 */
|
||||
height: 100%;
|
||||
background-color: var(--main-bg-color); /* 比主背景稍亮 */
|
||||
@@ -59,14 +67,12 @@
|
||||
flex-direction: column; /* 垂直排列内容 */
|
||||
align-items: center;
|
||||
padding: 10px 0;
|
||||
box-shadow: 1px 0 3px rgba(255, 255, 255, 0.1);
|
||||
box-shadow: var(--main-border-shadow);
|
||||
user-select: none; /* 阻止文本选择 */
|
||||
}
|
||||
|
||||
/* Logo/顶部区域 */
|
||||
.sidebar-logo {
|
||||
font-size: 1rem;
|
||||
margin-bottom: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
16
src/lib/components/ui/Sprite.svelte
Normal file
16
src/lib/components/ui/Sprite.svelte
Normal file
@@ -0,0 +1,16 @@
|
||||
<script>
|
||||
</script>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display:none" >
|
||||
|
||||
<symbol id="network" viewBox="0 0 24 24">
|
||||
<g fill="none">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18 7.96c2.59-.125 4.379.274 4.625 1.193c.429 1.6-3.98 4.172-9.849 5.745c-5.868 1.572-10.972 1.55-11.401-.051c-.254-.948 1.188-2.236 3.625-3.455" />
|
||||
<path fill="currentColor" fill-rule="evenodd" d="M4 12a8 8 0 1 1 15.985.491c-1.653.879-3.904 1.754-6.467 2.44c-2.874.77-5.526 1.14-7.478 1.131a12 12 0 0 1-.956-.039A7.96 7.96 0 0 1 4 12m2.766 6.05a8.003 8.003 0 0 0 12.658-3.065c-1.561.697-3.4 1.346-5.389 1.879c-2.668.715-5.208 1.115-7.269 1.186" clip-rule="evenodd" />
|
||||
</g>
|
||||
</symbol>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</svg>
|
||||
Reference in New Issue
Block a user