はじめに
この記事では、ReactとTypeScriptを使用して、ページを一定の位置までスクロールすると表示されるメニューの作り方をご紹介します。メニューは滑らかにフェードインおよびフェードアウトするようにCSSでアニメーションを追加します。
完成イメージ
ディレクトリ
scroll-menu
├── node_modules
├── public
├── src
│ ├── App.css
│ ├── App.tsx
│ ├── index.css
│ ├── index.tsx
│ ├── Menu.css
│ └── Menu.tsx
├── tailwind.config.js
├── package.json
└── tsconfig.json
作り方
1. プロジェクトのセットアップ
まず、TypeScriptを使用したReactプロジェクトを作成して、Tailwind CSSとdaisyUIをインストールします。
npx create-react-app scroll-menu --template typescript
cd scroll-menu
npm install -D tailwindcss
npx tailwindcss init -p
npm install daisyui
2. Tailwind CSSとdaisyUIの設定
tailwind.config.js
ファイルを以下のように設定します。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{js,jsx,ts,tsx}"],
theme: {
extend: {},
},
plugins: [require("daisyui")],
};
src/index.css
ファイルにTailwind CSSのベーススタイルをインポートします。
@tailwind base;
@tailwind components;
@tailwind utilities;
3. Menuコンポーネントの作成
次に、Menuコンポーネントを作成します。src/Menu.tsx
ファイルを作成し、以下のコードを追加します。
import React from 'react'
import "./Menu.css";
interface MenuProps {
show: boolean;
}
const Menu: React.FC<MenuProps> = ({show}) => {
return (
<ul className={`menu bg-base-200 rounded-box w-56 ${show ? 'show' : ''}`}>
<li>
<h2 className="menu-title">Title</h2>
<ul>
<li><a>Item 1</a></li>
<li><a>Item 2</a></li>
<li><a>Item 3</a></li>
</ul>
</li>
</ul>
);
}
export default Menu
show
については、この後に説明するスクロールイベントの処理で管理していて、親コンポーネントの App.tsx
から子コンポーネントの Menu.tsx
にPropsとして渡されてきます。
この行の ${show ? 'show' : ''}
で渡されてきた show
プロパティの値に基づいて CSSの show
クラスを動的に追加しています。 true
の場合は show
クラスが追加され、メニューが表示されます。 false
の場合は show
クラスが追加されず、メニューは非表示のままです。
bg-base-200 rounded-box w-56
はdaisyUIが提供しているスタイルです。
<ul className={menu bg-base-200 rounded-box w-56 ${show ? 'show' : ''}}>
4. CSSの設定
表示/非表示のアニメーションを追加するために、CSSファイルを作成して設定します。src/Menu.css
ファイルを作成し、以下の内容を追加します。
daisyUIで設定している menu
クラスに位置の調整と表示・非表示のスタイルを追加しています。
.menu {
position: fixed;
top: 15px;
right: 25px;
opacity: 0;
transition: opacity 0.5s ease, transform 0.5s ease;
}
.menu.show {
opacity: 1;
}
5. スクロールイベントの処理
次に、スクロールイベントを処理してメニューの表示/非表示を切り替えるコードをsrc/App.tsx
に追加します。
import React, { useEffect, useState } from 'react';
import './App.css';
import Menu from './Menu';
function App() {
const [showMenu, setShowMenu] = useState(false)
const handleScroll = () => {
const scrollTop = window.scrollY;
if (scrollTop > 50) { // 50px以上スクロールしたら表示
setShowMenu(true);
} else {
setShowMenu(false)
}
};
useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return (
<div className="App">
<header className="App-header">
<h1 className="text-4xl font-bold text-black">Scroll Menu</h1>
</header>
<Menu show={showMenu} />
</div>
);
}
export default App;
handleScroll
関数でスクロールに位置をチェックして、showMenu
の状態を更新します。今回の場合、スクロールの位置が50px以上でメニューを表示、それ以外で非表示の切り替えをしています。
const handleScroll = () => {
const scrollTop = window.scrollY;
if (scrollTop > 50) { // 50px以上スクロールしたら表示
setShowMenu(true);
} else {
setShowMenu(false)
}
};
以下は、コンポーネントが初めてレンダリングされたときにスクロールイベントリスナーを追加し、ユーザーがページをスクロールするたびに handleScroll
関数が実行されるようにしています。
また、return () => { window.removeEventListener("scroll", handleScroll); };
でコンポーネントが破棄されるときにイベントリスナーを削除することで、不要なイベント処理を防いでいます。
useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
親コンポーネントの App.tsx
から子コンポーネントの Menu.tsx
へPropsを渡しています。 showMenu
は親コンポーネントで管理されているスクロールイベントの状態で、true
または false
になります。
<Menu show={showMenu} />
おわりに
以上で、ReactとTypeScriptを使用してスクロール時に表示されるメニューの作り方を説明しました。この方法を使えば、ユーザーが特定の位置までスクロールしたときにメニューを表示するインタラクティブなWebアプリケーションを簡単に作成できます。必要に応じてカスタマイズして、自分のプロジェクトに取り入れてみてください。