mirror of
https://github.com/kogakure/website-astro-stefanimhoff.de.git
synced 2026-02-03 20:15:27 +00:00
feat: add mobile menu and modal
This commit is contained in:
committed by
Stefan Imhoff
parent
10b674cb2f
commit
76a7b16d7a
@@ -9,7 +9,7 @@ import navigation from '../data/navigation.json';
|
|||||||
<ul class="flex flex-wrap">
|
<ul class="flex flex-wrap">
|
||||||
{
|
{
|
||||||
navigation.map(({ title, url }) => (
|
navigation.map(({ title, url }) => (
|
||||||
<li class="mie-[10px] xs:mie-[15px]">
|
<li class="mie-[10px] xs:mie-[5px]">
|
||||||
<Link
|
<Link
|
||||||
class="rounded-2 pli-3 pbe-2 pbs-3 hover:bg-shibui-950/10 focus:bg-shibui-950/10 hover:dark:bg-shibui-50/10 focus:dark:bg-shibui-50/10"
|
class="rounded-2 pli-3 pbe-2 pbs-3 hover:bg-shibui-950/10 focus:bg-shibui-950/10 hover:dark:bg-shibui-50/10 focus:dark:bg-shibui-50/10"
|
||||||
data-umami-event={title}
|
data-umami-event={title}
|
||||||
|
|||||||
22
src/components/MenuLink.astro
Normal file
22
src/components/MenuLink.astro
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
import { Menu } from './icons';
|
||||||
|
import Link from './Link.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<Link
|
||||||
|
aria-label="Open the navigation menu"
|
||||||
|
class="h-clickarea w-clickarea scale-75 transition-transform duration-500 ease-in-out hover:scale-90 focus:scale-90 md:col-span-1 md:hidden print:hidden"
|
||||||
|
href="#menu"
|
||||||
|
id="menu-link"
|
||||||
|
title="Menu"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
aria-hidden="true"
|
||||||
|
class="flex h-clickarea w-clickarea cursor-pointer items-center justify-center border-none text-[0] outline-none"
|
||||||
|
data-umami-event="Menu"
|
||||||
|
tabindex={-1}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<Menu aria-hidden="true" className="icon h-icon w-icon" />
|
||||||
|
</button>
|
||||||
|
</Link>
|
||||||
92
src/components/MenuModal.astro
Normal file
92
src/components/MenuModal.astro
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
---
|
||||||
|
import Link from './Link.astro';
|
||||||
|
import MenuNavigation from './MenuNavigation.astro';
|
||||||
|
import { Close } from './icons';
|
||||||
|
---
|
||||||
|
|
||||||
|
<dialog id="menu-dialog">
|
||||||
|
<header
|
||||||
|
class="flex h-[clamp(1.5rem,_5.55vw,_9rem)] w-full items-center justify-end overflow-x-hidden block-start-0 md:h-[clamp(4rem,_5.55vw,_9rem)] md:pie-gap md:pis-gap"
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
id="close-menu"
|
||||||
|
class="relative left-[10px] outline-none transition-transform duration-500 ease-in-out block-start-0 hover:scale-125"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
aria-label="Close Menu Modal"
|
||||||
|
class="flex h-[2em] w-[2em] cursor-pointer items-center justify-center text-shibui-950 dark:text-shibui-200/[0.87]"
|
||||||
|
>
|
||||||
|
<Close className="icon h-[1.5em] w-[1.5em]" />
|
||||||
|
</button>
|
||||||
|
</Link>
|
||||||
|
</header>
|
||||||
|
<section
|
||||||
|
class="flex h-[calc(100%_-_clamp(1.5rem,_5.55vw,_9rem))] w-full flex-col items-center justify-center overflow-x-hidden md:h-[calc(100%_-_clamp(4rem,_5.55vw,_9rem))] md:pie-gap md:pis-gap"
|
||||||
|
>
|
||||||
|
<MenuNavigation />
|
||||||
|
</section>
|
||||||
|
</dialog>
|
||||||
|
|
||||||
|
<style is:global>
|
||||||
|
dialog::backdrop {
|
||||||
|
@apply bg-shibui-100 backdrop-blur-md dark:bg-shibui-900 md:bg-shibui-100/60 md:dark:bg-shibui-900/60;
|
||||||
|
animation: show-dimmer 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.hide::backdrop {
|
||||||
|
animation: hide-dimmer 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog {
|
||||||
|
@apply h-dvh max-w-[950px] rounded-2 md:max-h-[90vh];
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog[open] {
|
||||||
|
@apply w-[calc(100%_-_5.55vw_*_2)] bg-shibui-100 p-0 font-sans font-normal leading-relaxed text-shibui-950 common-ligatures dark:bg-shibui-900 dark:text-shibui-200/[0.87] md:dark:bg-shibui-800;
|
||||||
|
animation: show-modal 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.hide {
|
||||||
|
animation: hide-modal 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes show-modal {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(50px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes show-dimmer {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes hide-modal {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(50px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes hide-dimmer {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
44
src/components/MenuNavigation.astro
Normal file
44
src/components/MenuNavigation.astro
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
import data from '../data/subnavigation.json';
|
||||||
|
|
||||||
|
import Link from './Link.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<nav class="navigation glow flex gap-15" aria-label="Subnavigation" role="navigation">
|
||||||
|
<ul>
|
||||||
|
<li class="mbe-[20px]">
|
||||||
|
<Link
|
||||||
|
href="/"
|
||||||
|
class="text-5 font-light decoration-4 underline-offset-auto hover:underline hover:decoration-shibui-900/20 focus:underline focus:decoration-shibui-900/20 dark:hover:decoration-shibui-100/20 dark:focus:decoration-shibui-100/20"
|
||||||
|
>
|
||||||
|
Home
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
{
|
||||||
|
data.main.map(({ title, url }) => (
|
||||||
|
<li class="mbe-[20px]">
|
||||||
|
<Link
|
||||||
|
href={url}
|
||||||
|
class="text-5 font-light decoration-4 underline-offset-auto hover:underline hover:decoration-shibui-900/20 focus:underline focus:decoration-shibui-900/20 dark:hover:decoration-shibui-100/20 dark:focus:decoration-shibui-100/20"
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
<ul class="mie-10">
|
||||||
|
{
|
||||||
|
data.misc.map(({ title, url }) => (
|
||||||
|
<li class="mbe-[5px]">
|
||||||
|
<Link
|
||||||
|
href={url}
|
||||||
|
class="font-light decoration-4 underline-offset-auto hover:underline hover:decoration-shibui-900/20 focus:underline focus:decoration-shibui-900/20 dark:hover:decoration-shibui-100/20 dark:focus:decoration-shibui-100/20"
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
@@ -4,6 +4,7 @@ import ThemeToggle from '../components/ThemeToggle.astro';
|
|||||||
import Logo from '../components/Logo.astro';
|
import Logo from '../components/Logo.astro';
|
||||||
|
|
||||||
import SearchLink from './SearchLink.astro';
|
import SearchLink from './SearchLink.astro';
|
||||||
|
import MenuLink from './MenuLink.astro';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
class?: string;
|
class?: string;
|
||||||
@@ -27,5 +28,6 @@ const { class: className, navigation = true } = Astro.props;
|
|||||||
{navigation && <MainNavigation />}
|
{navigation && <MainNavigation />}
|
||||||
<SearchLink />
|
<SearchLink />
|
||||||
<ThemeToggle />
|
<ThemeToggle />
|
||||||
|
<MenuLink />
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
function setSearchLink() {
|
function setSearchLink() {
|
||||||
const body = document.body;
|
const body = document.body;
|
||||||
const dialog = document.querySelector('dialog');
|
const dialog = document.querySelector<HTMLDialogElement>('#search-dialog');
|
||||||
const openDialogLink = document.getElementById('search-link');
|
const openDialogLink = document.getElementById('search-link');
|
||||||
const closeDialogLink = document.getElementById('close-search');
|
const closeDialogLink = document.getElementById('close-search');
|
||||||
|
|
||||||
@@ -76,24 +76,36 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSearchModalLink() {
|
function setMenuLink() {
|
||||||
const dialog = document.querySelector('dialog');
|
const body = document.body;
|
||||||
|
const dialog = document.querySelector<HTMLDialogElement>('#menu-dialog');
|
||||||
|
const openDialogLink = document.getElementById('menu-link');
|
||||||
|
const closeDialogLink = document.getElementById('close-menu');
|
||||||
|
|
||||||
dialog?.addEventListener('click', (event) => {
|
dialog?.addEventListener('close', () => {
|
||||||
if (event.target === dialog) {
|
body.style.overflow = 'auto';
|
||||||
if (!dialog.classList.contains('hide')) {
|
});
|
||||||
dialog.classList.add('hide');
|
|
||||||
dialog.addEventListener(
|
openDialogLink?.addEventListener('click', (event) => {
|
||||||
'animationend',
|
event.preventDefault();
|
||||||
(animationEvent) => {
|
dialog?.showModal();
|
||||||
if (animationEvent.animationName === 'hide-modal') {
|
body.style.overflow = 'hidden';
|
||||||
dialog.close();
|
});
|
||||||
dialog.classList.remove('hide');
|
|
||||||
}
|
closeDialogLink?.addEventListener('click', (event) => {
|
||||||
},
|
event.preventDefault();
|
||||||
{ once: true }
|
if (!dialog?.classList.contains('hide')) {
|
||||||
);
|
dialog?.classList.add('hide');
|
||||||
}
|
dialog?.addEventListener(
|
||||||
|
'animationend',
|
||||||
|
(animationEvent) => {
|
||||||
|
if (animationEvent.animationName === 'hide-modal') {
|
||||||
|
dialog?.close();
|
||||||
|
dialog?.classList.remove('hide');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ once: true }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -122,7 +134,7 @@
|
|||||||
setActiveLink();
|
setActiveLink();
|
||||||
setEmailLink();
|
setEmailLink();
|
||||||
setSearchLink();
|
setSearchLink();
|
||||||
setSearchModalLink();
|
setMenuLink();
|
||||||
setUpLink();
|
setUpLink();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import Link from './Link.astro';
|
|||||||
import { Close } from './icons';
|
import { Close } from './icons';
|
||||||
---
|
---
|
||||||
|
|
||||||
<dialog>
|
<dialog id="search-dialog">
|
||||||
<header
|
<header
|
||||||
class="flex h-[clamp(1.5rem,_5.55vw,_9rem)] w-full items-center justify-end overflow-x-hidden block-start-0 md:h-[clamp(4rem,_5.55vw,_9rem)] md:pie-gap md:pis-gap"
|
class="flex h-[clamp(1.5rem,_5.55vw,_9rem)] w-full items-center justify-end overflow-x-hidden block-start-0 md:h-[clamp(4rem,_5.55vw,_9rem)] md:pie-gap md:pis-gap"
|
||||||
>
|
>
|
||||||
@@ -115,7 +115,7 @@ import { Close } from './icons';
|
|||||||
}
|
}
|
||||||
|
|
||||||
.pagefind-ui__results {
|
.pagefind-ui__results {
|
||||||
@apply !grid-cols-[repeat(auto-fill,_minmax(400px,_1fr))] !gap-x-gap !pbe-12 lg:!grid;
|
@apply !gap-x-gap !pbe-12 lg:!grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagefind-ui__result {
|
.pagefind-ui__result {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import ThemeProvider from '../components/ThemeProvider.astro';
|
|||||||
import PageHeader from '../components/PageHeader.astro';
|
import PageHeader from '../components/PageHeader.astro';
|
||||||
import PageFooter from '../components/PageFooter.astro';
|
import PageFooter from '../components/PageFooter.astro';
|
||||||
import SearchModal from '../components/SearchModal.astro';
|
import SearchModal from '../components/SearchModal.astro';
|
||||||
|
import MenuModal from '../components/MenuModal.astro';
|
||||||
import Scripts from '../components/Scripts.astro';
|
import Scripts from '../components/Scripts.astro';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
@@ -172,6 +173,7 @@ const webManifest = isProduction && {
|
|||||||
{footer && <PageFooter />}
|
{footer && <PageFooter />}
|
||||||
</div>
|
</div>
|
||||||
<SearchModal />
|
<SearchModal />
|
||||||
|
<MenuModal />
|
||||||
<script>
|
<script>
|
||||||
console.info(
|
console.info(
|
||||||
'👋 I see you’re interested in the source code of this site? You can find it here 👉 https://github.com/kogakure/website-astro-stefanimhoff.de'
|
'👋 I see you’re interested in the source code of this site? You can find it here 👉 https://github.com/kogakure/website-astro-stefanimhoff.de'
|
||||||
|
|||||||
Reference in New Issue
Block a user