feat: 新增 navBar 毛玻璃效果

This commit is contained in:
MJM_2025_05\polly 2025-09-09 09:03:37 +08:00
parent da7c5673ef
commit 2093a6161a
3 changed files with 94 additions and 77 deletions

View File

@ -1,10 +1,10 @@
<template> <template>
<nav <nav
class="fixed top-0 w-full h-14 lg:h-16 bg-white/50 backdrop-blur-sm shadow-md flex justify-between items-center px-4 sm:px-6 lg:px-8 z-[80]" class="fixed top-0 w-full h-14 lg:h-16 bg-white/50 backdrop-blur-sm shadow-md grid grid-cols-[1fr_auto_1fr] items-center px-4 sm:px-6 lg:px-8 z-[80]"
> >
<!-- 左側Logo + 機構切換 --> <!-- 左側Logo + 機構切換 -->
<div <div
class="flex items-center gap-4 sm:gap-8 shrink-0 w-[240px] md:w-[280px] lg:w-[340px]" class="col-span-1 justify-self-start flex items-center gap-4 sm:gap-8 shrink-0 w-[240px] md:w-[280px] lg:w-[340px]"
> >
<RouterLink to="/" class="h-9 md:h-11"> <RouterLink to="/" class="h-9 md:h-11">
<img src="/img/logo.png" alt="Logo" class="h-full w-auto" /> <img src="/img/logo.png" alt="Logo" class="h-full w-auto" />
@ -22,7 +22,6 @@
@keydown.enter.prevent="toggleFacility" @keydown.enter.prevent="toggleFacility"
@keydown.space.prevent="toggleFacility" @keydown.space.prevent="toggleFacility"
> >
<!-- 直接顯示不再隱藏 -->
<span class="tracking-wider">{{ displayLabel }}</span> <span class="tracking-wider">{{ displayLabel }}</span>
<!-- caret icon --> <!-- caret icon -->
<svg <svg
@ -37,11 +36,11 @@
</svg> </svg>
</div> </div>
<!-- Dropdown--> <!-- Dropdown -->
<div <div
v-show="isFacilityOpen" v-show="isFacilityOpen"
ref="panelRef" ref="panelRef"
class="absolute top-12 left-0 md:top-12 md:left-0 lg:left-0 z-50 w-56 md:w-64 rounded-md border border-gray-100 bg-white shadow-lg p-2" class="absolute top-12 left-0 z-50 w-56 md:w-64 rounded-md border border-gray-100 bg-white shadow-lg p-2"
@click.stop @click.stop
> >
<ul class="max-h-48 overflow-y-auto text-brand-black"> <ul class="max-h-48 overflow-y-auto text-brand-black">
@ -59,16 +58,17 @@
</div> </div>
</div> </div>
<!-- 中間導覽手機隱藏平板以上顯示桌機放大間距 --> <!-- 中間導覽平板以上顯示置中 -->
<div <div
class="hidden lg:grid min-w-[300px] grid-cols-3 items-center shadow-md rounded-full md:px-0 xl:min-w-[360px] bg-white/60" class="col-span-1 justify-self-center hidden lg:flex items-center rounded-full min-w-[300px] w-[300px] bg-white/60 shadow-md"
> >
<nav class="w-full grid grid-cols-3 divide-x divide-transparent">
<RouterLink to="/" v-slot="{ href, navigate, isExactActive }"> <RouterLink to="/" v-slot="{ href, navigate, isExactActive }">
<a <a
:href="href" :href="href"
@click="navigate" @click="navigate"
:class="[ :class="[
'px-4 lg:px-6 py-2 rounded-full flex justify-center items-center transition-colors', 'w-full py-2 flex justify-center items-center rounded-full transition-colors',
isExactActive ? 'bg-brand-green-light' : 'hover:bg-gray-100', isExactActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
]" ]"
>首頁</a >首頁</a
@ -80,7 +80,7 @@
:href="href" :href="href"
@click="navigate" @click="navigate"
:class="[ :class="[
'px-4 lg:px-6 py-2 rounded-full flex justify-center items-center transition-colors', 'w-full py-2 flex justify-center items-center rounded-full transition-colors',
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100', isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
]" ]"
>營運</a >營運</a
@ -92,16 +92,19 @@
:href="href" :href="href"
@click="navigate" @click="navigate"
:class="[ :class="[
'px-4 lg:px-6 py-2 rounded-full flex justify-center items-center transition-colors', 'w-full py-2 flex justify-center items-center rounded-full transition-colors',
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100', isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
]" ]"
>照護</a >照護</a
> >
</RouterLink> </RouterLink>
</nav>
</div> </div>
<!-- 右側通知 + 使用者手機只顯示圖示平板顯示文字 --> <!-- 右側通知 + 使用者桌機顯示 -->
<div class="hidden lg:flex items-center gap-3 sm:gap-6"> <div
class="col-span-1 justify-self-end hidden lg:flex items-center gap-3 sm:gap-6"
>
<button <button
class="btn bg-white text-brand-black hover:opacity-90 shadow-md border-none rounded-full p-2" class="btn bg-white text-brand-black hover:opacity-90 shadow-md border-none rounded-full p-2"
aria-label="通知" aria-label="通知"
@ -155,7 +158,7 @@
<!-- 手機漢堡按鈕--> <!-- 手機漢堡按鈕-->
<button <button
class="lg:hidden btn bg-white text-brand-black hover:opacity-90 shadow-md border-none rounded-md p-2" class="lg:hidden btn bg-white text-brand-black hover:opacity-90 shadow-md border-none rounded-md p-2 justify-self-end"
@click="toggleMobileMenu" @click="toggleMobileMenu"
:aria-expanded="isMobileMenuOpen" :aria-expanded="isMobileMenuOpen"
aria-controls="mobile-menu" aria-controls="mobile-menu"
@ -233,10 +236,7 @@
<RouterLink to="/" v-slot="{ href, navigate, isExactActive }"> <RouterLink to="/" v-slot="{ href, navigate, isExactActive }">
<a <a
:href="href" :href="href"
@click=" @click="navigate, closeMobileMenu()"
navigate;
closeMobileMenu();
"
:class="[ :class="[
'flex items-center gap-3 rounded-lg px-3 py-3 transition-colors', 'flex items-center gap-3 rounded-lg px-3 py-3 transition-colors',
isExactActive ? 'bg-brand-green-light' : 'hover:bg-gray-100', isExactActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
@ -260,10 +260,7 @@
<RouterLink to="/operation" v-slot="{ href, navigate, isActive }"> <RouterLink to="/operation" v-slot="{ href, navigate, isActive }">
<a <a
:href="href" :href="href"
@click=" @click="navigate, closeMobileMenu()"
navigate;
closeMobileMenu();
"
:class="[ :class="[
'flex items-center gap-3 rounded-lg px-3 py-3 transition-colors', 'flex items-center gap-3 rounded-lg px-3 py-3 transition-colors',
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100', isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
@ -287,10 +284,7 @@
<RouterLink to="/nursing" v-slot="{ href, navigate, isActive }"> <RouterLink to="/nursing" v-slot="{ href, navigate, isActive }">
<a <a
:href="href" :href="href"
@click=" @click="navigate, closeMobileMenu()"
navigate;
closeMobileMenu();
"
:class="[ :class="[
'flex items-center gap-3 rounded-lg px-3 py-3 transition-colors', 'flex items-center gap-3 rounded-lg px-3 py-3 transition-colors',
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100', isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
@ -376,10 +370,7 @@
<RouterLink to="/" v-slot="{ href, navigate, isExactActive }"> <RouterLink to="/" v-slot="{ href, navigate, isExactActive }">
<a <a
:href="href" :href="href"
@click=" @click="navigate, closeMobileMenu()"
navigate;
closeMobileMenu();
"
:class="[ :class="[
'flex items-center gap-3 rounded-lg px-3 py-3 transition-colors', 'flex items-center gap-3 rounded-lg px-3 py-3 transition-colors',
isExactActive ? 'bg-brand-green-light' : 'hover:bg-gray-100', isExactActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
@ -403,10 +394,7 @@
<RouterLink to="/operation" v-slot="{ href, navigate, isActive }"> <RouterLink to="/operation" v-slot="{ href, navigate, isActive }">
<a <a
:href="href" :href="href"
@click=" @click="navigate, closeMobileMenu()"
navigate;
closeMobileMenu();
"
:class="[ :class="[
'flex items-center gap-3 rounded-lg px-3 py-3 transition-colors', 'flex items-center gap-3 rounded-lg px-3 py-3 transition-colors',
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100', isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',
@ -420,7 +408,7 @@
> >
<path <path
fill="currentColor" fill="currentColor"
d="M20 13.75a.75.75 0 0 0-.75-.75h-3a.75.75 0 0 0-.75.75v6.75H14V4.25c0-.728-.002-1.2-.048-1.546c-.044-.325-.115-.427-.172-.484s-.159-.128-.484-.172C12.949 2.002 12.478 2 11.75 2s-1.2.002-1.546.048c-.325.044-.427.115-.484.172s-.128.159-.172.484c-.046.347-.048.818-.048 1.546V20.5H8V8.75A.75.75 0 0 0 7.25 8h-3a.75.75 0 0 0-.75.75V20.5H1.75a.75.75 0 0 0 0 1.5h20a.75.75 0 0 0 0-1.5H20z" d="M20 13.75a.75.75 0 0 0-.75-.75h-3a.75.75 0 0 0-.75.75v6.75H14V4.25c0-.728-.002-1.2-.048-1.546c-.044-.325-.115-.427-.172-.484s-.159-.128-.484-.172C12.949 2.002 12.478 2 11.75 2s-1.2.002-1.546.048c-.325.044-.427.115-.484.172s-.128.159-.172.484c-.046.347-.048 1.818-.048 1.546V20.5H8V8.75A.75.75 0 0 0 7.25 8h-3a.75.75 0 0 0-.75.75V20.5H1.75a.75.75 0 0 0 0 1.5h20a.75.75 0 0 0 0-1.5H20z"
/> />
</svg> </svg>
<span class="text-brand-black">營運</span> <span class="text-brand-black">營運</span>
@ -430,10 +418,7 @@
<RouterLink to="/nursing" v-slot="{ href, navigate, isActive }"> <RouterLink to="/nursing" v-slot="{ href, navigate, isActive }">
<a <a
:href="href" :href="href"
@click=" @click="navigate, closeMobileMenu()"
navigate;
closeMobileMenu();
"
:class="[ :class="[
'flex items-center gap-3 rounded-lg px-3 py-3 transition-colors', 'flex items-center gap-3 rounded-lg px-3 py-3 transition-colors',
isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100', isActive ? 'bg-brand-green-light' : 'hover:bg-gray-100',

View File

@ -64,7 +64,7 @@ const props = defineProps({
chartKey: { type: String, required: true }, chartKey: { type: String, required: true },
currentLegend: { type: String, required: true }, currentLegend: { type: String, required: true },
totalLegend: { type: String, required: true }, totalLegend: { type: String, required: true },
duration: { type: Number, default: 100 }, duration: { type: Number, default: 300 },
}); });
const emit = defineEmits(["select"]); const emit = defineEmits(["select"]);

View File

@ -1112,7 +1112,7 @@ function getResidentsHtml(name) {
? [p.hospitalized.current, p.hospitalized.total] ? [p.hospitalized.current, p.hospitalized.total]
: [0, 0]; : [0, 0];
return ` return `
<div class="tip p-2" style="cursor:pointer" data-facility="${name}"> <div class="tip p-2" style="cursor:pointer; touch-action:none; overscroll-behavior:contain" data-facility="${name}">
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<div class="inline-flex justify-between items-center text-brand-purple-dark font-noto"> <div class="inline-flex justify-between items-center text-brand-purple-dark font-noto">
<div class="inline-flex justify-start items-center gap-1"> <div class="inline-flex justify-start items-center gap-1">
@ -1149,7 +1149,7 @@ function getDietHtml(name) {
veg: { total: 0, normal: 0, soft: 0, tube: 0 }, veg: { total: 0, normal: 0, soft: 0, tube: 0 },
}; };
return ` return `
<div class="tip p-2" style="cursor:pointer" data-facility="${name}"> <div class="tip p-2" style="cursor:pointer; touch-action:none; overscroll-behavior:contain" data-facility="${name}">
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<div class="inline-flex justify-between items-center text-brand-purple-dark font-noto"> <div class="inline-flex justify-between items-center text-brand-purple-dark font-noto">
<div class="inline-flex justify-start items-center gap-1"> <div class="inline-flex justify-start items-center gap-1">
@ -1245,17 +1245,49 @@ function syncTooltips() {
} }
// click // click
// select
const t = m.getTooltip?.(); const t = m.getTooltip?.();
if (t && typeof t.getElement === "function") { if (t && typeof t.getElement === "function") {
const el = t.getElement(); const el = t.getElement();
if (el && !el.__clickBound) { if (el && !el.__bound) {
el.__clickBound = true; el.__bound = true;
el.style.cursor = "pointer"; el.style.cursor = "pointer";
el.addEventListener("click", (e) => { el.setAttribute("tabindex", "-1"); // scroll-into-view
const target = e.currentTarget;
const facility = target?.getAttribute?.("data-facility") || name; //
selectFacility(facility); const block = (ev) => {
ev.preventDefault();
ev.stopPropagation();
};
//
[
"wheel",
"mousewheel",
"DOMMouseScroll",
"touchstart",
"touchmove",
"pointerdown",
"pointermove",
"mousedown",
"mousemove",
].forEach((type) => {
el.addEventListener(type, block, { passive: false });
}); });
//
el.addEventListener(
"click",
(e) => {
block(e);
const facility = el.getAttribute("data-facility") || name;
selectFacility(facility);
},
{ passive: false }
);
//
el.addEventListener("dblclick", block, { passive: false });
} }
} }
} }