website

website src components Header.astro

3.3 KB 130 lines Raw ↗ GitHub ↗

---import { Image } from 'astro:assets';import logo from '../assests/logo.jpg';const { pathname } = Astro.url;const links = [  { href: "/", label: "Home" },  { href: "/showcase", label: "Showcase" },];---<header class="site-header" data-header>  <div class="container header-inner">    <a href="/" class="brand" aria-label="Ryuzaki home">      <Image src={logo} alt="" width={56} height={56} class="brand-mark" />      <span class="brand-name">Ryuzaki</span>    </a>    <nav class="site-nav" aria-label="Primary">      {links.map((l) => (        <a          href={l.href}          class={pathname === l.href ? "nav-link is-active" : "nav-link"}          aria-current={pathname === l.href ? "page" : undefined}        >          {l.label}        </a>      ))}    </nav>  </div>  <div class="scroll-edge" aria-hidden="true"></div></header><style>  .site-header {    position: sticky;    top: 0;    z-index: 50;    background: transparent;    transition: background 240ms var(--ease-spring-soft);  }  .site-header[data-scrolled="true"] {    background: var(--material-thick);    backdrop-filter: blur(20px) saturate(180%);    -webkit-backdrop-filter: blur(20px) saturate(180%);  }  .header-inner {    display: flex;    align-items: center;    justify-content: space-between;    height: 60px;  }  .brand {    display: inline-flex;    align-items: center;    gap: 10px;    color: var(--text);    font-weight: 600;  }  .brand:hover { color: var(--text); }  .brand-mark {    width: 28px;    height: 28px;    border-radius: 7px;    object-fit: cover;    flex-shrink: 0;    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08),                0 2px 8px rgba(0, 0, 0, 0.4);  }  .brand-name {    font-family: var(--mono);    font-size: 0.95rem;    letter-spacing: -0.01em;  }  .site-nav { display: flex; gap: 2px; }  .nav-link {    color: var(--text-muted);    font-size: 0.92rem;    font-weight: 500;    letter-spacing: -0.005em;    padding: 8px 14px;    border-radius: 999px;    transition: color 180ms var(--ease-spring-soft),                background 180ms var(--ease-spring-soft);  }  .nav-link:hover { color: var(--text); background: var(--material-thin); }  .nav-link:active { transform: scale(0.96); }  .nav-link.is-active {    color: var(--accent);    background: var(--accent-soft);  }  .scroll-edge {    height: 0;    overflow: visible;    pointer-events: none;  }  .site-header[data-scrolled="true"] .scroll-edge {    height: 24px;    margin-top: -1px;    background: linear-gradient(      to bottom,      rgba(0, 0, 0, 0.35),      transparent    );    opacity: 0.6;  }  @media (max-width: 480px) {    .brand-name { font-size: 0.88rem; }    .nav-link { padding: 7px 11px; font-size: 0.86rem; }  }</style><script>  function initHeaderScroll() {    const header = document.querySelector("[data-header]");    if (!(header instanceof HTMLElement)) return;    const update = () => {      header.setAttribute("data-scrolled", String(window.scrollY > 8));    };    update();    window.addEventListener("scroll", update, { passive: true });    window.addEventListener("resize", update, { passive: true });  }  if (document.readyState === "loading") {    document.addEventListener("DOMContentLoaded", initHeaderScroll);  } else {    initHeaderScroll();  }</script>