feat: add overlay menu for mobile device

Signed-off-by: Ryan Wang <i@ryanc.cc>
This commit is contained in:
Ryan Wang
2022-10-06 22:06:43 +08:00
parent 4409d28915
commit 87ececb908
12 changed files with 265 additions and 16 deletions

10
env.d.ts vendored Normal file
View File

@@ -0,0 +1,10 @@
/// <reference types="vite/client" />
import type { Alpine } from "alpinejs";
export {};
declare global {
interface Window {
Alpine: Alpine;
}
}

View File

@@ -39,6 +39,7 @@
"@iconify/json": "^2.1.118", "@iconify/json": "^2.1.118",
"@tailwindcss/aspect-ratio": "^0.4.2", "@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/typography": "^0.5.7", "@tailwindcss/typography": "^0.5.7",
"@types/alpinejs": "^3.7.0",
"@types/node": "16", "@types/node": "16",
"@typescript-eslint/eslint-plugin": "^5.39.0", "@typescript-eslint/eslint-plugin": "^5.39.0",
"@typescript-eslint/parser": "^5.39.0", "@typescript-eslint/parser": "^5.39.0",
@@ -55,6 +56,7 @@
"vite-plugin-purge-icons": "^0.9.1" "vite-plugin-purge-icons": "^0.9.1"
}, },
"dependencies": { "dependencies": {
"@iconify/iconify": "^3.0.0" "@iconify/iconify": "^3.0.0",
"alpinejs": "^3.10.3"
} }
} }

36
pnpm-lock.yaml generated
View File

@@ -5,9 +5,11 @@ specifiers:
'@iconify/json': ^2.1.118 '@iconify/json': ^2.1.118
'@tailwindcss/aspect-ratio': ^0.4.2 '@tailwindcss/aspect-ratio': ^0.4.2
'@tailwindcss/typography': ^0.5.7 '@tailwindcss/typography': ^0.5.7
'@types/alpinejs': ^3.7.0
'@types/node': '16' '@types/node': '16'
'@typescript-eslint/eslint-plugin': ^5.39.0 '@typescript-eslint/eslint-plugin': ^5.39.0
'@typescript-eslint/parser': ^5.39.0 '@typescript-eslint/parser': ^5.39.0
alpinejs: ^3.10.3
autoprefixer: ^10.4.12 autoprefixer: ^10.4.12
eslint: ^8.24.0 eslint: ^8.24.0
eslint-config-prettier: ^8.5.0 eslint-config-prettier: ^8.5.0
@@ -22,11 +24,13 @@ specifiers:
dependencies: dependencies:
'@iconify/iconify': 3.0.0 '@iconify/iconify': 3.0.0
alpinejs: 3.10.3
devDependencies: devDependencies:
'@iconify/json': 2.1.118 '@iconify/json': 2.1.118
'@tailwindcss/aspect-ratio': 0.4.2_tailwindcss@3.1.8 '@tailwindcss/aspect-ratio': 0.4.2_tailwindcss@3.1.8
'@tailwindcss/typography': 0.5.7_tailwindcss@3.1.8 '@tailwindcss/typography': 0.5.7_tailwindcss@3.1.8
'@types/alpinejs': 3.7.0
'@types/node': 16.11.64 '@types/node': 16.11.64
'@typescript-eslint/eslint-plugin': 5.39.0_c7dhob3nbh3wwlahpgade2jupi '@typescript-eslint/eslint-plugin': 5.39.0_c7dhob3nbh3wwlahpgade2jupi
'@typescript-eslint/parser': 5.39.0_4at4lsfnhb3djm6qjts2gmiglm '@typescript-eslint/parser': 5.39.0_4at4lsfnhb3djm6qjts2gmiglm
@@ -186,6 +190,12 @@ packages:
tailwindcss: 3.1.8_postcss@8.4.17 tailwindcss: 3.1.8_postcss@8.4.17
dev: true dev: true
/@types/alpinejs/3.7.0:
resolution: {integrity: sha512-iMvJwgJHYFUlMOixKF68BmMQZbnxVA/erh1blbfhY8Z6u6oleEJViz8bye58roLOp8jyBNOsXtobyq7zR/7A2g==}
dependencies:
'@vue/reactivity': 3.2.40
dev: true
/@types/json-schema/7.0.11: /@types/json-schema/7.0.11:
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
dev: true dev: true
@@ -320,6 +330,26 @@ packages:
eslint-visitor-keys: 3.3.0 eslint-visitor-keys: 3.3.0
dev: true dev: true
/@vue/reactivity/3.1.5:
resolution: {integrity: sha512-1tdfLmNjWG6t/CsPldh+foumYFo3cpyCHgBYQ34ylaMsJ+SNHQ1kApMIa8jN+i593zQuaw3AdWH0nJTARzCFhg==}
dependencies:
'@vue/shared': 3.1.5
dev: false
/@vue/reactivity/3.2.40:
resolution: {integrity: sha512-N9qgGLlZmtUBMHF9xDT4EkD9RdXde1Xbveb+niWMXuHVWQP5BzgRmE3SFyUBBcyayG4y1lhoz+lphGRRxxK4RA==}
dependencies:
'@vue/shared': 3.2.40
dev: true
/@vue/shared/3.1.5:
resolution: {integrity: sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==}
dev: false
/@vue/shared/3.2.40:
resolution: {integrity: sha512-0PLQ6RUtZM0vO3teRfzGi4ltLUO5aO+kLgwh4Um3THSR03rpQWLTuRCkuO5A41ITzwdWeKdPHtSARuPkoo5pCQ==}
dev: true
/acorn-jsx/5.3.2_acorn@8.8.0: /acorn-jsx/5.3.2_acorn@8.8.0:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies: peerDependencies:
@@ -362,6 +392,12 @@ packages:
uri-js: 4.4.1 uri-js: 4.4.1
dev: true dev: true
/alpinejs/3.10.3:
resolution: {integrity: sha512-nt/w4hLq9pPaexCsHmO5zV5Alvq4yu9n0Iclti6aV0HmiqLWH/axUb0pn8z3XVuVNcj8EOXOQw+WpwPzMzLBWg==}
dependencies:
'@vue/reactivity': 3.1.5
dev: false
/ansi-regex/5.0.1: /ansi-regex/5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'} engines: {node: '>=8'}

View File

@@ -2,6 +2,12 @@ import "./styles/tailwind.css";
import "./styles/main.css"; import "./styles/main.css";
import "@purge-icons/generated"; import "@purge-icons/generated";
import Alpine from "alpinejs";
window.Alpine = Alpine;
Alpine.start();
const onScroll = () => { const onScroll = () => {
const headerMenu = document.getElementById("header-menu"); const headerMenu = document.getElementById("header-menu");
if (window.scrollY > 0) { if (window.scrollY > 0) {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,12 +1,14 @@
<footer class="mt-10 bg-white py-8"> <footer class="mt-10 bg-white py-8">
<div class="container mx-auto sm:flex sm:items-center sm:justify-between"> <div class="container mx-auto sm:flex sm:items-center sm:justify-between">
<a <a
href="https://halo.run/" href="/"
class="mb-4 flex items-center justify-center sm:mb-0 sm:justify-start" class="mb-4 flex items-center justify-center sm:mb-0 sm:justify-start"
> >
<img src="https://halo.run/logo" class="mr-3 h-8" alt="Halo Logo" /> <img th:src="${site.logo}" class="mr-3 h-8" th:alt="${site.title}" />
<span class="self-center whitespace-nowrap text-2xl font-semibold"> <span
Halo class="self-center whitespace-nowrap text-2xl font-semibold"
th:text="${site.title}"
>
</span> </span>
</a> </a>
<ul <ul
@@ -29,7 +31,8 @@
<hr class="my-6 border-gray-100 sm:mx-auto lg:my-8" /> <hr class="my-6 border-gray-100 sm:mx-auto lg:my-8" />
<span class="container mx-auto block text-center text-sm text-gray-500"> <span class="container mx-auto block text-center text-sm text-gray-500">
© 2022 © 2022
<a href="https://halo.run" class="hover:underline">Halo</a>. All Rights <a href="/" class="hover:underline" th:text="${site.title}"></a>. All Rights
Reserved. Reserved. Powered by
<a href="https://halo.run" class="hover:underline" target="_blank">Halo</a>.
</span> </span>
</footer> </footer>

View File

@@ -16,7 +16,7 @@
</div> </div>
<ul <ul
th:if="${menu != null} and ${not #lists.isEmpty(menu.menuItems)}" th:if="${menu != null} and ${not #lists.isEmpty(menu.menuItems)}"
class="flex items-center gap-6 text-white" class="hidden items-center gap-6 text-white sm:flex"
> >
<li <li
th:each="menuItem : ${menu.menuItems}" th:each="menuItem : ${menu.menuItems}"
@@ -31,6 +31,12 @@
</div> </div>
<div class="flex items-center"> <div class="flex items-center">
<ul class="flex items-center gap-4"> <ul class="flex items-center gap-4">
<li class="sm:hidden" x-on:click="overlayMenu = true">
<span
data-icon="tabler:menu-2"
class="iconify text-lg text-white"
></span>
</li>
<li> <li>
<span <span
data-icon="tabler:brightness-2" data-icon="tabler:brightness-2"

View File

@@ -13,12 +13,12 @@
th:href="@{/assets/dist/style.css}" th:href="@{/assets/dist/style.css}"
href="./assets/dist/style.css" href="./assets/dist/style.css"
/> />
<script th:src="@{/assets/dist/main.iife.js}"></script> <script th:src="@{/assets/dist/main.iife.js}" defer></script>
<th:block th:if="${head != null}"> <th:block th:if="${head != null}">
<th:block th:replace="${head}" /> <th:block th:replace="${head}" />
</th:block> </th:block>
</head> </head>
<body> <body x-data="{ overlayMenu: false }">
<th:block th:replace="modules/header" /> <th:block th:replace="modules/header" />
<section class="container mx-auto"></section> <section class="container mx-auto"></section>
<section <section
@@ -34,5 +34,6 @@
<th:block th:if="${footer != null}"> <th:block th:if="${footer != null}">
<th:block th:replace="${footer}" /> <th:block th:replace="${footer}" />
</th:block> </th:block>
<th:block th:replace="modules/overlay-menu" />
</body> </body>
</html> </html>

View File

@@ -0,0 +1,177 @@
<div class="relative z-10" role="dialog" aria-modal="true" x-show="overlayMenu">
<div
x-show="overlayMenu"
x-on:click="overlayMenu = false"
class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity"
x-transition:enter="ease-in-out duration-300"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="ease-in-out duration-300"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
></div>
<div class="fixed inset-0 overflow-hidden">
<div class="absolute inset-0 overflow-hidden">
<div
class="pointer-events-none fixed inset-y-0 left-0 flex max-w-full pr-20"
>
<div
x-show="overlayMenu"
class="pointer-events-auto w-screen max-w-md"
x-transition:enter="transform transition ease-in-out duration-300"
x-transition:enter-start="-translate-x-full"
x-transition:enter-end="translate-x-0"
x-transition:leave="transform transition ease-in-out duration-300"
x-transition:leave-start="translate-x-0"
x-transition:leave-end="-translate-x-full"
>
<div
class="flex h-full flex-col overflow-y-auto bg-white py-6 shadow-xl"
>
<div class="flex items-center justify-end px-4 sm:px-6">
<button
x-on:click="overlayMenu = false"
type="button"
class="rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none"
>
<span data-icon="tabler:x" class="iconify text-lg"></span>
</button>
</div>
<div class="relative mt-6 flex-1 px-4 sm:px-6">
<div class="absolute inset-0 px-4 sm:px-6">
<div class="flex h-full flex-col items-center gap-4">
<div class="relative h-24 w-24">
<img
th:src="${site.logo}"
th:alt="${site.title}"
class="h-full w-full rounded-full"
/>
<span
class="absolute right-0 bottom-0 flex h-7 w-7 items-center justify-center rounded-full border bg-white p-0.5"
>
🌚
</span>
</div>
<div>
<h1
class="text-2xl font-medium"
th:text="${site.title}"
></h1>
</div>
<div th:if="${not #strings.isEmpty(site.subtitle)}">
<p
class="text-center text-sm text-gray-700"
th:text="${site.subtitle}"
></p>
</div>
<div class="grid grid-cols-4 gap-5">
<div class="inline-flex flex-col items-center">
<span
class="text-xl font-medium tabular-nums text-gray-900"
>97</span
><span class="text-xs font-light text-gray-600"
>文章数</span
>
</div>
<div class="inline-flex flex-col items-center">
<span
class="text-xl font-medium tabular-nums text-gray-900"
>18</span
><span class="text-xs font-light text-gray-600"
>分类数</span
>
</div>
<div class="inline-flex flex-col items-center">
<span
class="text-xl font-medium tabular-nums text-gray-900"
>117</span
><span class="text-xs font-light text-gray-600"
>评论数</span
>
</div>
<div class="inline-flex flex-col items-center">
<span
class="text-xl font-medium tabular-nums text-gray-900"
>92392</span
><span class="text-xs font-light text-gray-600"
>访问量</span
>
</div>
</div>
<div class="grid grid-cols-6 items-center gap-5">
<div
class="flex cursor-pointer items-center justify-center rounded p-1 hover:bg-gray-100"
>
<span
data-icon="simple-icons:wechat"
class="iconify text-[#07C160]"
></span>
</div>
<div
class="flex cursor-pointer items-center justify-center rounded p-1 hover:bg-gray-100"
>
<span
data-icon="simple-icons:bilibili"
class="iconify text-[#00A1D6]"
></span>
</div>
<div
class="flex cursor-pointer items-center justify-center rounded p-1 hover:bg-gray-100"
>
<span
data-icon="simple-icons:github"
class="iconify text-[#181717]"
></span>
</div>
<div
class="flex cursor-pointer items-center justify-center rounded p-1 hover:bg-gray-100"
>
<span
data-icon="simple-icons:twitter"
class="iconify text-[#1DA1F2]"
></span>
</div>
<div
class="flex cursor-pointer items-center justify-center rounded p-1 hover:bg-gray-100"
>
<span
data-icon="simple-icons:telegram"
class="iconify text-[#26A5E4]"
></span>
</div>
<div
class="flex cursor-pointer items-center justify-center rounded p-1 hover:bg-gray-100"
>
<span
data-icon="simple-icons:feedly"
class="iconify text-[#2BB24C]"
></span>
</div>
</div>
<div
class="w-full"
th:with="menu = ${menuFinder.getDefault()}"
>
<ul
th:if="${menu != null} and ${not #lists.isEmpty(menu.menuItems)}"
class="flex w-full flex-col gap-1"
>
<li th:each="menuItem : ${menu.menuItems}" class="w-full">
<a
th:href="${menuItem.status.href}"
th:text="${menuItem.status.displayName}"
class="flex h-full w-full rounded px-3 py-2 text-sm text-gray-900 hover:bg-gray-100"
></a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -3,7 +3,11 @@
> >
<div class="flex flex-col items-center justify-center gap-4"> <div class="flex flex-col items-center justify-center gap-4">
<div class="relative h-24 w-24"> <div class="relative h-24 w-24">
<img src="https://halo.run/logo" class="h-full w-full rounded-full" /> <img
th:src="${site.logo}"
th:alt="${site.title}"
class="h-full w-full rounded-full"
/>
<span <span
class="absolute right-0 bottom-0 flex h-7 w-7 items-center justify-center rounded-full border bg-white p-0.5" class="absolute right-0 bottom-0 flex h-7 w-7 items-center justify-center rounded-full border bg-white p-0.5"
> >
@@ -11,7 +15,7 @@
</span> </span>
</div> </div>
<div><h1 class="text-2xl font-medium" th:text="${site.title}"></h1></div> <div><h1 class="text-2xl font-medium" th:text="${site.title}"></h1></div>
<div> <div th:if="${not #strings.isEmpty(site.subtitle)}">
<p <p
class="text-center text-sm text-gray-700" class="text-center text-sm text-gray-700"
th:text="${site.subtitle}" th:text="${site.subtitle}"

View File

@@ -16,5 +16,5 @@
"noImplicitReturns": true, "noImplicitReturns": true,
"skipLibCheck": true "skipLibCheck": true
}, },
"include": ["src"] "include": ["src", "./env.d.ts"]
} }