- Web Engineer
- アウトバウンド営業
- Webエンジニア(経験者)
- Other occupations (18)
- Development
- Business
はじめに
こんにちは! ふとNotionのようなリサイズ可能なサイドバーの実装方法が気になったので、調べたことをコードを交えてステップバイステップで実装し共有しようと思います。
ステップ1 基本構造の作成
今回は以下のようなUIのダッシュボードをSidebar / Navbar / MainContentコンポーネントを元に作成したいと思います。まずはこれら各コンポーネントの基本的なコードを実装していきます。
src/app/page.tsx
import MainContent from "@/components/MainContent";
import Navbar from "@/components/Navbar";
import Sidebar from "@/components/Sidebar";
export default function Home() {
return (
<div className="h-screen flex flex-col">
<div className="flex-1 flex overflow-hidden">
<Sidebar />
<div className="flex-1 flex flex-col">
<Navbar />
<MainContent />
</div>
</div>
</div>
);
}
src/components/Sidebar/index.tsx
import React from 'react';
const Sidebar = () => {
return (
<aside className="h-full overflow-y-auto p-4 font-semibold">
Sidebar
</aside>
);
};
export default Sidebar;
src/components/Navbar/index.tsx
import React from 'react';
const Navbar = () => {
return (
<nav className="w-full p-4 font-semibold">
Navbar
</nav>
);
};
export default Navbar;
src/components/MainContent/index.tsx
import React from 'react';
const MainContent = () => {
return (
<div className="flex-1 overflow-y-auto bg-zinc-100 p-4 font-semibold">
Main Content
</div>
);
};
export default MainContent;
これらの基本的なコンポーネント実装により以下のようなUIになるかと思います。
ステップ2 サイドバーをリサイズ可能にするためのロジックを追加
このステップでは実際にリサイズ可能なサイドバーを実装します。
classNameを動的に変更するためにclsx
とtailwind-merge
を追加します。
npm i clsx tailwind-merge
src/lib/utils.ts
import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
ロジックをカスタムフックとして実装し、コードの複雑さを解消します。
src/hooks/useSidebarResize.ts
'use client';
import { useCallback, useRef, useState } from 'react';
export const useSidebarResize = () => {
const MIN_SIDEBAR_WIDTH = 200;
const MAX_SIDEBAR_WIDTH = 480;
const isResizingRef = useRef(false);
const [sidebarWidth, setSidebarWidth] = useState(MIN_SIDEBAR_WIDTH);
const [isDragging, setIsDragging] = useState(false);
const handleMouseMove = useCallback((event: MouseEvent) => {
if (!isResizingRef.current) return;
//マウスの現在位置を取得
let newWidth = event.clientX;
if (newWidth < MIN_SIDEBAR_WIDTH) newWidth = MIN_SIDEBAR_WIDTH;
if (newWidth > MAX_SIDEBAR_WIDTH) newWidth = MAX_SIDEBAR_WIDTH;
setSidebarWidth(newWidth);
}, []);
// ドラッグ操作を開始したときに呼び出される
const handleMouseDown = (
event: React.MouseEvent,
) => {
event.preventDefault();
// リサイズを開始
isResizingRef.current = true;
// ドラッグ状態を開始
setIsDragging(true);
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
};
// ドラッグ操作を終了したときに呼び出される
const handleMouseUp = () => {
// リサイズを終了
isResizingRef.current = false;
// ドラッグ状態を終了
setIsDragging(false);
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
};
return { sidebarWidth, isDragging, handleMouseDown };
};
src/components/Sidebar/index.tsx
import { useSidebarResize } from '@/hooks/useSidebarResize';
import React from 'react';
import { cn } from '@/lib/utils';
const Sidebar = () => {
const { sidebarWidth, isDragging, handleMouseDown } = useSidebarResize();
return (
<aside
style={{
width: sidebarWidth,
transition: isDragging ? 'none' : 'width 0.3s ease-in-out',
}}
className={cn(
'h-full overflow-y-auto relative flex flex-col z-[100] transition-all duration-300 ease-in-out p-4 font-semibold'
)}
>
Sidebar
<div
onMouseDown={handleMouseDown}
className="cursor-ew-resize absolute h-full w-1 right-0 top-0"
/>
</aside>
);
};
export default Sidebar;
上記のコードにより、サイドバーをドラッグすることでwidthを制限した範囲内でリサイズできるようになります!
ステップ3 サイドバーを開閉するためのロジックを追加する
…
記事の続きは下のURLをクリック!
https://rightcode.co.jp/blogs/50017
エンジニア積極採用中です!
現在、WEBエンジニア、モバイルエンジニア、デザイナー、営業などを積極採用中です!
採用ページはこちら:https://rightcode.co.jp/recruit
社員の声や社風などを知りたい方はこちら:https://rightcode.co.jp/blogs?category=life
社長と一杯飲みながらお話しませんか?(転職者向け)
特設ページはこちら: https://rightcode.co.jp/gohan-sake-president-talk
もっとワクワクしたいあなたへ
現在、ライトコードでは「WEBエンジニア」「モバイルエンジニア」「ゲームエンジニア」、「デザイナー」「WEBディレクター」「営業」などを積極採用中です!
ライトコードは技術力に定評のある受託開発をメインにしているIT企業です。
有名WEBサービスやアプリの受託開発などの企画、開発案件が目白押しの状況です。
- もっと大きなことに挑戦したい!
- エンジニアとしてもっと成長したい!
- モダンな技術に触れたい!
現状に満足していない方は、まずは、エンジニアとしても第一線を走り続ける弊社代表と気軽にお話してみませんか?
ネット上では、ちょっとユルそうな会社に感じると思いますが(笑)、
実は技術力に定評があり、沢山の実績を残している会社ということをお伝えしたいと思っております。
- ライトコードの魅力を知っていただきたい!
- 社風や文化なども知っていただきたい!
- 技術に対して熱意のある方に入社していただきたい!
一度、【Wantedly内の弊社ページ】や【コーポレートサイト】をのぞいてみてください。