finish basic sidebar
This commit is contained in:
parent
9200befaf8
commit
8f18560a38
6
bun.lock
6
bun.lock
|
@ -4,7 +4,9 @@
|
|||
"": {
|
||||
"name": "fpga-weblab",
|
||||
"dependencies": {
|
||||
"log-symbols": "^7.0.0",
|
||||
"pinia": "^3.0.1",
|
||||
"ts-log": "^2.2.7",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "4",
|
||||
},
|
||||
|
@ -413,6 +415,8 @@
|
|||
|
||||
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.29.2", "", { "os": "win32", "cpu": "x64" }, "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA=="],
|
||||
|
||||
"log-symbols": ["log-symbols@7.0.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0", "yoctocolors": "^2.1.1" } }, "sha512-zrc91EDk2M+2AXo/9BTvK91pqb7qrPg2nX/Hy+u8a5qQlbaOflCKO+6SqgZ+M+xUFxGdKTgwnGiL96b1W3ikRA=="],
|
||||
|
||||
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
|
||||
|
||||
"magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="],
|
||||
|
@ -501,6 +505,8 @@
|
|||
|
||||
"totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],
|
||||
|
||||
"ts-log": ["ts-log@2.2.7", "", {}, "sha512-320x5Ggei84AxzlXp91QkIGSw5wgaLT6GeAH0KsqDmRZdVWW2OiSeVvElVoatk3f7nicwXlElXsoFkARiGE2yg=="],
|
||||
|
||||
"typescript": ["typescript@5.7.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw=="],
|
||||
|
||||
"undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="],
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
"type-check": "bunx --bun vue-tsc --build"
|
||||
},
|
||||
"dependencies": {
|
||||
"log-symbols": "^7.0.0",
|
||||
"pinia": "^3.0.1",
|
||||
"ts-log": "^2.2.7",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "4"
|
||||
},
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import LoginCard from './components/LoginCard.vue';
|
||||
import { useThemeStore } from './stores/theme';
|
||||
|
||||
const theme = useThemeStore()
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :data-theme="theme.currentTheme">
|
||||
<header>
|
||||
<RouterLink to="/user"> Go to User</RouterLink>
|
||||
<RouterLink to="/login"> Go to Login</RouterLink>
|
||||
|
@ -11,6 +17,7 @@ import LoginCard from './components/LoginCard.vue';
|
|||
<main>
|
||||
<RouterView />
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
@import "tailwindcss";
|
||||
|
||||
@plugin "daisyui" {
|
||||
themes: winter --default, night;
|
||||
themes: winter --default, night --prefersdark;
|
||||
}
|
||||
|
||||
@custom-variant dark (&:where([data-theme=night], [data-theme=night] *));
|
||||
@custom-variant light (&:where([data-theme=winter], [data-theme=winter] *));
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
<template>
|
||||
<div class="card card-dash sidebar-base">
|
||||
<div :class="themeSidebar">
|
||||
<div class="card-body flex">
|
||||
<!-- Avatar and Name -->
|
||||
<div class="flex items-center">
|
||||
<!-- Img -->
|
||||
<div class="avatar h-10">
|
||||
<div class="rounded-full">
|
||||
<img src="../assets/user.svg" alt="User" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="mx-5 grow">
|
||||
<label class="text-2xl">User Name</label>
|
||||
<!-- Text -->
|
||||
<div v-if="!isClose" class="mx-5 grow">
|
||||
<label class="text-2xl">用户名</label>
|
||||
</div>
|
||||
<button class="btn btn-square rounded-lg p-2">
|
||||
|
||||
<!-- Toggle Button -->
|
||||
<button class="btn btn-square rounded-lg p-2" @click="toggleSidebar">
|
||||
<img src="../assets/left.svg" alt="Menu Button" class="opacity-50">
|
||||
</button>
|
||||
</div>
|
||||
|
@ -21,8 +25,8 @@
|
|||
<ul class="menu h-full w-full">
|
||||
<li v-for="item in items" class="text-lg my-1">
|
||||
<a>
|
||||
<img class="h-[1em] opacity-50 mx-1" :src="item.icon" alt="An icon" />
|
||||
{{ item.msg }}
|
||||
<img class="h-[1.5em] opacity-50 mx-1" :src="item.icon" alt="An icon" />
|
||||
<p v-if="!isClose">{{ item.msg }}</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
@ -30,49 +34,15 @@
|
|||
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="mb-5">
|
||||
<label class="swap swap-rotate">
|
||||
<!-- this hidden checkbox controls the state -->
|
||||
<input type="checkbox" class="theme-controller" value="synthwave" />
|
||||
|
||||
<!-- sun icon -->
|
||||
<svg class="swap-off h-10 w-10 fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z" />
|
||||
</svg>
|
||||
|
||||
<!-- moon icon -->
|
||||
<svg class="swap-on h-10 w-10 fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M21.64,13a1,1,0,0,0-1.05-.14,8.05,8.05,0,0,1-3.37.73A8.15,8.15,0,0,1,9.08,5.49a8.59,8.59,0,0,1,.25-2A1,1,0,0,0,8,2.36,10.14,10.14,0,1,0,22,14.05,1,1,0,0,0,21.64,13Zm-9.5,6.69A8.14,8.14,0,0,1,7.08,5.22v.27A10.15,10.15,0,0,0,17.22,15.63a9.79,9.79,0,0,0,2.1-.22A8.11,8.11,0,0,1,12.14,19.73Z" />
|
||||
</svg>
|
||||
</label>
|
||||
|
||||
<label class="toggle text-base-content">
|
||||
<input type="checkbox" value="synthwave" class="theme-controller">
|
||||
|
||||
<svg aria-label="sun" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<g stroke-linejoin="round" stroke-linecap="round" stroke-width="2" fill="none" stroke="currentColor">
|
||||
<circle cx="12" cy="12" r="4"></circle>
|
||||
<path d="M12 2v2"></path>
|
||||
<path d="M12 20v2"></path>
|
||||
<path d="m4.93 4.93 1.41 1.41"></path>
|
||||
<path d="m17.66 17.66 1.41 1.41"></path>
|
||||
<path d="M2 12h2"></path>
|
||||
<path d="M20 12h2"></path>
|
||||
<path d="m6.34 17.66-1.41 1.41"></path>
|
||||
<path d="m19.07 4.93-1.41 1.41"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
<svg aria-label="moon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<g stroke-linejoin="round" stroke-linecap="round" stroke-width="2" fill="none" stroke="currentColor">
|
||||
<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
</label>
|
||||
</div>
|
||||
<ul class="menu w-full">
|
||||
<li class="mb-5">
|
||||
<a @click="theme.toggleTheme" class="text-xl">
|
||||
<ThemeControlButton />
|
||||
<p v-if="!isClose">改变主题</p>
|
||||
<ThemeControlToggle v-if="!isClose" />
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@ -80,6 +50,13 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import iconMenu from "../assets/menu.svg"
|
||||
import { useThemeStore } from "@/stores/theme";
|
||||
import { ref } from "vue";
|
||||
import ThemeControlButton from "./ThemeControlButton.vue";
|
||||
import ThemeControlToggle from "./ThemeControlToggle.vue";
|
||||
|
||||
const theme = useThemeStore()
|
||||
const isClose = ref(false)
|
||||
|
||||
const items = [
|
||||
{ id: 1, icon: iconMenu, msg: "btn1" },
|
||||
|
@ -87,16 +64,46 @@ const items = [
|
|||
{ id: 3, icon: iconMenu, msg: "btn3" },
|
||||
{ id: 4, icon: iconMenu, msg: "btn4" },
|
||||
]
|
||||
|
||||
const themeSidebar = ref("")
|
||||
|
||||
function closeSidebar() {
|
||||
isClose.value = true;
|
||||
console.info("Close sidebar")
|
||||
}
|
||||
|
||||
function openSidebar() {
|
||||
isClose.value = false;
|
||||
console.info("Open sidebar")
|
||||
}
|
||||
|
||||
function toggleSidebar() {
|
||||
if (isClose.value) {
|
||||
openSidebar()
|
||||
themeSidebar.value = "card-dash sidebar-base sidebar-open"
|
||||
}
|
||||
else {
|
||||
closeSidebar()
|
||||
themeSidebar.value = "card-dash sidebar-base sidebar-close"
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="postcss">
|
||||
@import "../assets/main.css";
|
||||
@reference "../assets/main.css";
|
||||
|
||||
.sidebar-base {
|
||||
@apply shadow-xl w-80 h-screen
|
||||
@apply card shadow-xl h-screen;
|
||||
}
|
||||
|
||||
.sidebar-open {}
|
||||
.sidebar-open {
|
||||
@apply w-80
|
||||
}
|
||||
|
||||
.sidebar-close {}
|
||||
.sidebar-close {
|
||||
@apply w-31
|
||||
}
|
||||
|
||||
@custom-variant
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<template>
|
||||
<div>
|
||||
<label class="swap swap-rotate">
|
||||
<!-- this hidden checkbox controls the state -->
|
||||
<input type="checkbox" value="synthwave" @click="theme.toggleTheme" :checked="checkState" />
|
||||
|
||||
<!-- sun icon -->
|
||||
<svg class="swap-off h-10 w-10 fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z" />
|
||||
</svg>
|
||||
|
||||
<!-- moon icon -->
|
||||
<svg class="swap-on h-10 w-10 fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M21.64,13a1,1,0,0,0-1.05-.14,8.05,8.05,0,0,1-3.37.73A8.15,8.15,0,0,1,9.08,5.49a8.59,8.59,0,0,1,.25-2A1,1,0,0,0,8,2.36,10.14,10.14,0,1,0,22,14.05,1,1,0,0,0,21.64,13Zm-9.5,6.69A8.14,8.14,0,0,1,7.08,5.22v.27A10.15,10.15,0,0,0,17.22,15.63a9.79,9.79,0,0,0,2.1-.22A8.11,8.11,0,0,1,12.14,19.73Z" />
|
||||
</svg>
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useThemeStore } from '@/stores/theme';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const theme = useThemeStore();
|
||||
|
||||
const checkState = computed(() => {
|
||||
return theme.isDarkTheme()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="postcss">
|
||||
@import "../assets/main.css"
|
||||
</style>
|
|
@ -0,0 +1,45 @@
|
|||
<template>
|
||||
<div>
|
||||
<label class="toggle text-base-content">
|
||||
<input type="checkbox" value="synthwave" class="theme-controller" @click="theme.toggleTheme"
|
||||
:checked="checkState">
|
||||
|
||||
<svg aria-label="sun" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<g stroke-linejoin="round" stroke-linecap="round" stroke-width="2" fill="none" stroke="currentColor">
|
||||
<circle cx="12" cy="12" r="4"></circle>
|
||||
<path d="M12 2v2"></path>
|
||||
<path d="M12 20v2"></path>
|
||||
<path d="m4.93 4.93 1.41 1.41"></path>
|
||||
<path d="m17.66 17.66 1.41 1.41"></path>
|
||||
<path d="M2 12h2"></path>
|
||||
<path d="M20 12h2"></path>
|
||||
<path d="m6.34 17.66-1.41 1.41"></path>
|
||||
<path d="m19.07 4.93-1.41 1.41"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
<svg aria-label="moon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<g stroke-linejoin="round" stroke-linecap="round" stroke-width="2" fill="none" stroke="currentColor">
|
||||
<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useThemeStore } from '@/stores/theme';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const theme = useThemeStore();
|
||||
|
||||
const checkState = computed(() => {
|
||||
return theme.isDarkTheme()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="postcss">
|
||||
@import "../assets/main.css"
|
||||
</style>
|
|
@ -10,3 +10,4 @@ export const useCounterStore = defineStore('counter', () => {
|
|||
|
||||
return { count, doubleCount, increment }
|
||||
})
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
import { ref, computed } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useThemeStore = defineStore('theme', () => {
|
||||
const allTheme = ["winter", "night"]
|
||||
const darkTheme = "night";
|
||||
const lightTheme = "winter";
|
||||
const currentTheme = ref("night")
|
||||
|
||||
function setTheme(theme: string) {
|
||||
const isContained: boolean = allTheme.includes(theme)
|
||||
if (isContained) {
|
||||
currentTheme.value = theme
|
||||
}
|
||||
else {
|
||||
console.error('Not have such theme: ${theme}')
|
||||
}
|
||||
}
|
||||
|
||||
function toggleTheme() {
|
||||
if (currentTheme.value == darkTheme) {
|
||||
currentTheme.value = lightTheme;
|
||||
} else if (currentTheme.value == lightTheme) {
|
||||
currentTheme.value = darkTheme;
|
||||
} else {
|
||||
currentTheme.value = lightTheme;
|
||||
}
|
||||
}
|
||||
|
||||
function isDarkTheme(): boolean {
|
||||
return currentTheme.value == darkTheme
|
||||
}
|
||||
|
||||
function isLightTheme(): boolean {
|
||||
return currentTheme.value == lightTheme
|
||||
}
|
||||
|
||||
return {
|
||||
allTheme,
|
||||
currentTheme,
|
||||
setTheme,
|
||||
toggleTheme,
|
||||
isDarkTheme,
|
||||
isLightTheme
|
||||
}
|
||||
})
|
||||
|
Loading…
Reference in New Issue