コンテンツへスキップ

ヘッダー

プレビュー



特徴

  • レスポンシブデザイン: スマホ・タブレット・PC などの画面サイズに合わせてナビゲーションが変化します。
  • アクセシビリティ: スキップリンクや aria-label を活用し、スクリーンリーダーでも快適に操作できる設計です。
  • ダークモード対応: システムの設定に合わせて自動的にライトモード・ダークモードを切り替えます。
  • 直感的なハンバーガーボタン: スマホやタブレットなどの小さな画面でメニューを展開・収束できるハンバーガーアイコンを採用しています。
  • 最低限の Props: logonavItems を指定するだけで、豊富な UI を簡単に実装できます。
ヒント

logo のテキストが長い場合でも、折り返しやはみ出しを防ぐためのスタイルを適用しています。

プロパティ

プロパティ名デフォルト値説明
logostring"LOGO"ヘッダー左上に表示される文字列。クリックするとルートに戻ります。
navItems{label: string; href: string;}[][ { label: "Home", href: "/" } ]表示したいナビゲーションアイテムの配列。

Github

コード例

Header.tsx
import "@/styles/tailwind.css";
import { useState } from "react";
type NavItem = {
label: string;
href: string;
};
type HeaderProps = {
logo?: string;
navItems?: NavItem[];
};
export default function Header({
logo = "LOGO",
navItems = [
{ label: "Home", href: "#" },
{ label: "About", href: "#" },
{ label: "Contact", href: "#" },
],
}: HeaderProps) {
const [isOpen, setIsOpen] = useState(false);
return (
<header className="w-full bg-white text-black dark:bg-black dark:text-white">
<div className="flex items-center justify-between px-4 py-4 md:px-8">
<h1 className="text-xl font-bold overflow-hidden text-ellipsis whitespace-nowrap">
<a
href="/"
className="transition-colors duration-200 hover:opacity-75 focus:opacity-75"
>
{logo}
</a>
</h1>
<button
onClick={() => setIsOpen(!isOpen)}
aria-label="Toggle Menu"
type="button"
aria-expanded={isOpen}
className="inline-flex items-center justify-center p-2 rounded md:hidden hover:bg-gray/10 dark:hover:bg-white/10"
>
<div className="relative w-6 h-6">
<span
className={`absolute block h-[2px] w-6 bg-current transition-transform duration-300 ease-in-out ${
isOpen ? "top-[13px] rotate-45" : "top-[6px]"
}`}
/>
<span
className={`absolute block h-[2px] w-6 bg-current transition-opacity duration-300 ease-in-out ${
isOpen ? "opacity-0" : "top-[13px]"
}`}
/>
<span
className={`absolute block h-[2px] w-6 bg-current transition-transform duration-300 ease-in-out ${
isOpen ? "bottom-[6px] -rotate-45" : "bottom-[6px]"
}`}
/>
</div>
</button>
<nav className="hidden md:flex md:items-center md:space-x-8">
{navItems.map(({ label, href }) => (
<a
key={href}
href={href}
className="block px-2 py-1 transition-opacity duration-200 hover:opacity-75 focus:opacity-75"
>
{label}
</a>
))}
</nav>
</div>
<div
className={`md:hidden transition-[max-height] duration-300 overflow-hidden ${
isOpen
? "max-h-96 border-t border-gray/30 dark:border-white/30"
: "max-h-0"
}`}
>
<ul className="flex flex-col gap-4 py-4 px-4">
{navItems.map(({ label, href }) => (
<li key={href}>
<a
href={href}
className="block px-2 py-1 transition-opacity duration-200 hover:opacity-75 focus:opacity-75"
>
{label}
</a>
</li>
))}
</ul>
</div>
</header>
);
}

使用方法

コンポーネントをインポートして、ページやレイアウトに組み込みます。logonavItems を必要に応じて上書きしてください。 各フレームワークによってインポート先は調整し、実際には上記のコードを別ファイルで管理すると便利です。

// import "@/components/Header";
import Header from "@/components/Header";
export default function Layout({ children }) {
return (
<>
<Header
logo="MyWebsite"
navItems={[
{ label: "Home", href: "/" },
{ label: "Services", href: "/services" },
{ label: "Blog", href: "/blog" },
]}
/>
<main id="main">{children}</main>
</>
);
}

補足情報