update: mobile navbar
This commit is contained in:
+20
-11
@@ -24,7 +24,7 @@ function logout() {
|
||||
|
||||
<template>
|
||||
<nav>
|
||||
<div class="ts-container navbar-container">
|
||||
<div class="ts-container navbar-container" v-if="!$isMobile">
|
||||
<div class="ts-wrap">
|
||||
<RouterLink class="ts-header is-brand" to="/">網路攻防實習</RouterLink>
|
||||
<div class="ts-tab is-tall">
|
||||
@@ -43,6 +43,25 @@ function logout() {
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ts-container" v-else>
|
||||
<div class="ts-wrap navbar-container">
|
||||
<RouterLink class="ts-header is-brand has-top-padded has-bottom-padded" to="/">網路攻防實習</RouterLink>
|
||||
<div class="actions ts-wrap">
|
||||
<template v-if="isLoggedIn">
|
||||
<span class="username">{{ username }}</span>
|
||||
<RouterLink class="ts-button is-icon is-outlined" to="/profile"><span class="ts-icon is-user-icon"></span></RouterLink>
|
||||
<div class="ts-button" @click="logout">登出</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<RouterLink class="ts-button" to="/login">登入</RouterLink>
|
||||
<RouterLink class="ts-button" to="/register">註冊</RouterLink>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ts-tab is-tall is-center-aligned">
|
||||
<RouterLink class="item" :to="route.path" :class="{'is-active': route.path == $route.path}" v-for="route in $router.options.routes.filter(route => route.meta.showInNav)">{{ route.meta.navName }}</RouterLink>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
@@ -66,14 +85,4 @@ nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.navbar-container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.actions {
|
||||
margin: 10px 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { reactive } from 'vue';
|
||||
|
||||
const mobileMediaQuery = 'screen and (max-width: 768px)';
|
||||
const matchMedia = window.matchMedia(mobileMediaQuery);
|
||||
|
||||
const isMobile = reactive(matchMedia.matches);
|
||||
|
||||
matchMedia.addEventListener('change', (event) => {
|
||||
isMobile = event.matches;
|
||||
});
|
||||
|
||||
export const install = (app) => {
|
||||
app.config.globalProperties.$isMobile = isMobile;
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import router from './router';
|
||||
import { createPinia } from 'pinia';
|
||||
import { install as installRecaptcha } from "vue3-recaptcha-v2";
|
||||
import { install as installDarkMode } from './lib/darkMode';
|
||||
import { install as installIsMobile } from './lib/isMobile';
|
||||
|
||||
const pinia = createPinia();
|
||||
const app = createApp(App);
|
||||
@@ -12,6 +13,7 @@ const app = createApp(App);
|
||||
app.use(pinia);
|
||||
app.use(router);
|
||||
app.use(installDarkMode);
|
||||
app.use(installIsMobile);
|
||||
app.use(installRecaptcha, {
|
||||
sitekey: import.meta.env.VITE_RECAPTCHA_SITEKEY
|
||||
});
|
||||
|
||||
@@ -38,7 +38,7 @@ const generateMotto = async () => {
|
||||
|
||||
<template>
|
||||
<div class="ts-app-center">
|
||||
<div>
|
||||
<div class="ts-content is-horizontally-fitted">
|
||||
<div class="ts-box ts-content is-center-aligned">
|
||||
<div class="ts-header is-large is-center-aligned">每日金句生成器</div>
|
||||
<div class="ts-header is-secondary is-center-aligned">Powered By Cloudflare Workers AI</div>
|
||||
@@ -53,7 +53,7 @@ const generateMotto = async () => {
|
||||
<button class="ts-button" @click="generateMotto" :disabled="!captchaVerified">生成</button>
|
||||
</div>
|
||||
<div class="ts-content is-center-aligned">
|
||||
<p class="ts-text">每日金句:</p>
|
||||
<p class="ts-text" v-if="mottoLoading || motto">每日金句:</p>
|
||||
<div class="ts-loading" v-if="mottoLoading"></div>
|
||||
<div class="ts-quote" v-if="motto">
|
||||
<p class="ts-text">{{ motto }}</p>
|
||||
|
||||
Reference in New Issue
Block a user