📱 Responsive header

This commit is contained in:
2025-08-30 18:11:26 -04:00
parent b8445f4a1b
commit eef297d4a1
12 changed files with 447 additions and 213 deletions
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M96 160C96 142.3 110.3 128 128 128L512 128C529.7 128 544 142.3 544 160C544 177.7 529.7 192 512 192L128 192C110.3 192 96 177.7 96 160zM96 320C96 302.3 110.3 288 128 288L512 288C529.7 288 544 302.3 544 320C544 337.7 529.7 352 512 352L128 352C110.3 352 96 337.7 96 320zM544 480C544 497.7 529.7 512 512 512L128 512C110.3 512 96 497.7 96 480C96 462.3 110.3 448 128 448L512 448C529.7 448 544 462.3 544 480z"/></svg>

After

Width:  |  Height:  |  Size: 631 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M183.1 137.4C170.6 124.9 150.3 124.9 137.8 137.4C125.3 149.9 125.3 170.2 137.8 182.7L275.2 320L137.9 457.4C125.4 469.9 125.4 490.2 137.9 502.7C150.4 515.2 170.7 515.2 183.2 502.7L320.5 365.3L457.9 502.6C470.4 515.1 490.7 515.1 503.2 502.6C515.7 490.1 515.7 469.8 503.2 457.3L365.8 320L503.1 182.6C515.6 170.1 515.6 149.8 503.1 137.3C490.6 124.8 470.3 124.8 457.8 137.3L320.5 274.7L183.1 137.4z"/></svg>

After

Width:  |  Height:  |  Size: 624 B

-76
View File
@@ -1,76 +0,0 @@
---
import Avatar from './Avatar.astro';
const { pathname } = Astro.url;
interface Props {}
interface NavLink {
label: string;
path: string;
}
const navLinks: NavLink[] = [
{ label: 'Blog', path: 'blog' },
{ label: 'Now', path: 'now' },
{ label: 'Projects', path: 'projects' },
];
const pathComponents = pathname.split('/').slice(1);
---
<header>
<a href="/">
<Avatar size={60} />
</a>
<nav>
{
navLinks.map((link) => (
<li>
<a href={`/${link.path}`}>
<span>{link.label}</span>
</a>
{pathComponents[0] === link.path ? <div class="underline" /> : null}
</li>
))
}
</nav>
</header>
<style>
header {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
height: 120px;
}
header > h1 > a {
color: var(--text);
}
header > nav {
display: flex;
flex-direction: row;
list-style: none;
gap: 20px;
font-size: 1.15rem;
}
header > nav > li > a:hover {
text-decoration: none;
}
header > nav > li > .selected {
font-weight: bold;
}
.underline {
height: 2px;
width: 100%;
background-color: var(--orange);
}
</style>
+114
View File
@@ -0,0 +1,114 @@
---
import BarsIcon from '../../assets/svg/bars.svg';
import CloseIcon from '../../assets/svg/xmark.svg';
import { navLinks } from '../../data/nav-links';
---
<div
x-data="{ open: false }"
class="drawer-container"
@keydown.escape="open = false"
>
<button @click="open = !open">
<BarsIcon class="bars-icon" width={24} height={24} />
</button>
<div
class="overlay"
@click="open = !open"
x-show="open"
x-transition:enter-start="hidden-overlay"
x-transition:enter-end="visible-overlay"
x-transition:leave-start="visible-overlay"
x-transition:leave-end="hidden-overlay"
>
</div>
<div
class="drawer"
x-show="open"
x-transition:enter-start="hidden-drawer"
x-transition:enter-end="visible-drawer"
x-transition:leave-start="visible-drawer"
x-transition:leave-end="hidden-drawer"
>
<button @click="open = !open">
<CloseIcon class="bars-icon" width={24} height={24} /></button
>
<hr />
<ul>
{
navLinks.map((link) => (
<li>
<a href={`/${link.path}`}>
<span>{link.label}</span>
</a>
</li>
))
}
</ul>
</div>
</div>
<style>
:root {
--transition: all 0.1s ease-in-out;
}
button {
background: none;
color: inherit;
padding: 2px 2px -2px;
border: none;
line-height: 1;
aspect-ratio: square;
}
button:active {
opacity: 0.3;
}
@media screen and (min-width: 600px) {
.drawer-container {
display: none;
}
}
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.6);
z-index: 2;
transition: var(--transition);
}
.hidden-overlay {
opacity: 0;
}
.drawer {
right: 0;
top: 0;
background-color: var(--background);
position: absolute;
width: 200px;
height: 100vh;
padding: 12px;
z-index: 3;
transition: var(--transition);
}
ul {
list-style: none;
}
li {
margin-bottom: 12px;
}
.hidden-drawer {
transform: translateX(220px);
}
</style>
+41
View File
@@ -0,0 +1,41 @@
---
import Nav from './Nav.astro';
import Drawer from './Drawer.astro';
---
<header>
<div class="container">
<h1><a href="/">ghall.space</a></h1>
<Nav />
<Drawer />
</div>
</header>
<style>
header {
margin-bottom: 20px;
height: 70px;
background-color: rgba(252, 252, 252, 90%);
backdrop-filter: blur(10px);
width: 100%;
top: 0;
position: fixed;
z-index: 1;
}
.container {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
max-width: var(--max-page-width);
margin: auto;
padding: 0 10px;
height: 100%;
}
h1 > a {
font-size: 1.6rem;
color: var(--text);
}
</style>
+50
View File
@@ -0,0 +1,50 @@
---
import { navLinks } from '../../data/nav-links';
const { pathname } = Astro.url;
const pathComponents = pathname.split('/').slice(1);
---
<nav>
{
navLinks.map((link) => (
<li>
<a href={`/${link.path}`}>
<span>{link.label}</span>
</a>
{pathComponents[0] === link.path ? <div class="underline" /> : null}
</li>
))
}
</nav>
<style>
nav {
display: flex;
flex-direction: row;
list-style: none;
gap: 20px;
font-size: 1.15rem;
}
a:hover {
text-decoration: none;
}
.selected {
font-weight: bold;
}
.underline {
height: 2px;
width: 100%;
background-color: var(--orange);
}
@media screen and (max-width: 600px) {
nav {
display: none;
}
}
</style>
+10
View File
@@ -0,0 +1,10 @@
export interface NavLink {
label: string;
path: string;
}
export const navLinks: NavLink[] = [
{ label: 'Blog', path: 'blog' },
{ label: 'Now', path: 'now' },
{ label: 'Projects', path: 'projects' },
];
+9 -2
View File
@@ -26,10 +26,11 @@
--red: #d20f39;
--orange: #fe640b;
--text: #4c4f69;
--background: #fff8fa;
--background: #fcfcfc;
--radius: 5px;
--shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;
--border: 1px solid #8c8fa1;
--max-page-width: 800px;
}
@media (prefers-color-scheme: dark) {
@@ -52,9 +53,15 @@ html {
}
body {
margin: 0;
padding: 0;
}
main {
max-width: 800px;
margin: auto;
padding: 0 1rem;
margin-top: 100px;
}
a {
@@ -76,7 +83,7 @@ article img {
box-shadow: var(--shadow);
display: block;
margin: auto;
max-width: 100%;
max-width: var(--max-page-width);
height: auto;
}
+1 -1
View File
@@ -1,7 +1,7 @@
---
import '../global.css';
import Header from '@components/Header.astro';
import Header from '@components/Header/Header.astro';
import Footer from '@components/Footer.astro';
export interface Props {