Side Navigationブロック
SideNavigationコンポーネントは、ReactとTypeScriptで構築された完全にカスタマイズ可能でアクセシブルなサイドナビゲーションメニューです。モダンなデザインパターン、モバイルレスポンシブ動作、フローティングと固定モード、柔軟なカスタマイズオプションを備えた完全なナビゲーションインターフェースを提供します。
🚀 インストール
npm install @nodeblocks/frontend-side-navigation-block
📖 使用法
import {SideNavigation} from '@nodeblocks/frontend-side-navigation-block';
- 基本的な使用法
- 高度な使用法
ライブエディター
function BasicSideNavigation() { const [isMenuOpen, setIsMenuOpen] = useState(false); const navigationHeader = { icon: 'home' as const, text: 'ホーム', href: '#home', }; const navigationLinks = [ {icon: 'dashboard' as const, text: 'ダッシュボード', href: '#dashboard'}, {icon: 'shopping_cart' as const, text: 'プロダクト', href: '#products'}, {icon: 'reorder' as const, text: '注文', href: '#orders'}, {icon: 'settings' as const, text: '設定', href: '#settings'}, {icon: 'help' as const, text: 'サポート', href: '#support'}, ]; return ( <SideNavigation isFloating={true} isMenuOpen={isMenuOpen} setIsMenuOpen={setIsMenuOpen} header={navigationHeader} links={navigationLinks}> <SideNavigation.Links /> </SideNavigation> ); }
結果
Loading...
ライブエディター
function AdvancedSideNavigation() { const [isMenuOpen, setIsMenuOpen] = useState(false); const navigationHeader = { icon: 'home' as const, text: 'ホーム', href: '#home', }; const navigationLinks = [ {icon: '📊' as const, text: 'ダッシュボード', href: '#dashboard', color: '#007bff'}, {icon: '🛍️' as const, text: 'プロダクト', href: '#products', color: '#007bff'}, {icon: '📦' as const, text: '注文', href: '#orders', color: '#007bff'}, {icon: '⚙️' as const, text: '設定', href: '#settings', color: '#007bff'}, {icon: '💬' as const, text: 'サポート', href: '#support', color: '#007bff'}, ]; return ( <SideNavigation isFloating={true} isMenuOpen={isMenuOpen} setIsMenuOpen={setIsMenuOpen} header={navigationHeader} links={[]} // オーバーライド関数内で使用する > {({defaultBlocks, defaultBlockOrder}) => { return { blocks: { ...defaultBlocks, // 🧭 完全なコンポーネントオーバーライド付きリッチナビゲーションリンク links: { ...defaultBlocks.links, props: { ...defaultBlocks.links.props, className: 'custom-links', children: ( <nav style={{ display: 'flex', flexDirection: 'column', gap: '8px', padding: '20px', background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', minHeight: '100vh', width: isMenuOpen ? '280px' : '60px', transition: 'all 0.3s ease', position: 'relative', overflow: 'hidden', }} > {/* ヘッダーセクション */} <div style={{ display: 'flex', alignItems: 'center', gap: '12px', padding: '16px 12px', backgroundColor: 'rgba(255, 255, 255, 0.1)', borderRadius: '12px', marginBottom: '20px', backdropFilter: 'blur(10px)', border: '1px solid rgba(255, 255, 255, 0.2)', }} > <div style={{ width: '40px', height: '40px', backgroundColor: '#fff', borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '1.2rem', color: '#667eea', fontWeight: 'bold', boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)', }} > 🏠 </div> {isMenuOpen && ( <div style={{color: 'white'}}> <div style={{fontWeight: 'bold', fontSize: '1.1rem'}}>私のアプリ</div> <div style={{fontSize: '0.8rem', opacity: 0.8}}>おかえりなさい!</div> </div> )} </div> {/* ナビゲーションリンク */} <div style={{display: 'flex', flexDirection: 'column', gap: '6px'}}> {navigationLinks.map((item, index) => ( <a key={index} href={item.href} style={{ display: 'flex', alignItems: 'center', gap: '15px', padding: '14px 16px', borderRadius: '10px', textDecoration: 'none', color: 'white', transition: 'all 0.3s ease', backgroundColor: 'rgba(255, 255, 255, 0.1)', border: '1px solid rgba(255, 255, 255, 0.1)', backdropFilter: 'blur(10px)', }} onMouseEnter={e => { e.currentTarget.style.backgroundColor = item.color; e.currentTarget.style.transform = 'translateX(8px)'; //@ts-expect-error - color is not a valid property e.currentTarget.style.boxShadow = `0 4px 15px ${item.color}40`; }} onMouseLeave={e => { e.currentTarget.style.backgroundColor = 'rgba(255, 255, 255, 0.1)'; e.currentTarget.style.transform = 'translateX(0)'; e.currentTarget.style.boxShadow = 'none'; }} > <div style={{ fontSize: '1.4rem', minWidth: '24px', textAlign: 'center', }} > {item.icon} </div> {isMenuOpen && ( <div style={{ fontSize: '0.95rem', fontWeight: '500', whiteSpace: 'nowrap', }} > {item.text} </div> )} </a> ))} </div> </nav> ), }, }, }, blockOrder: defaultBlockOrder, }; }} </SideNavigation> ); }
結果
Loading...
🔧 プロパティリファレンス
メインコンポーネントプロパティ
プロパティ | 型 | デフォルト | 説明 |
---|---|---|---|
isFloating | boolean | undefined | ナビゲーションがコンテンツの上にフロート(モバイルスタイル)するか、固定位置にするか |
isMenuOpen | boolean | undefined | ナビゲーションメニューが開いているか閉じているかを制御 |
setIsMenuOpen | (isMenuOpen: boolean) => void | 必須 | メニューの開閉状態を制御する関数 |
header | { icon?: IconType; text?: ReactNode; href: string } | 必須 | オプションのアイコン、テキストコンテンツ、hrefを持つヘッダーリンクオブジェクト |
links | { icon?: IconType; text?: ReactNode; href: string }[] | 必須 | オプションのアイコンを持つナビゲーションリンクオブジェクトの配列 |
children | BlocksOverride | undefined | デフォルトブロックをオーバーライドするか、カスタムナビゲーションコンポーネントを追加する関数 |
サブコンポーネント
SideNavigationコンポーネントは複数のサブコンポーネントを提供します。すべてのサブコンポーネントは、メインコンポーネントのコンテキストからデフォルト値を受け取り、プロパティを通じてこれらの値をオーバーライドできます。
SideNavigation.Overlay
プロパティ | 型 | デフォルト | 説明 |
---|---|---|---|
children | ReactNode | undefined | オーバーレイのカスタムコンテンツ |
setIsMenuOpen | (isMenuOpen: boolean) => void | コンテキストから | オーバーレイがクリックされたときにメニュー状態を制御する関数 |
注意: このコンポーネントはすべてのHTML div
要素プロパティを継承します。
SideNavigation.MenuButton
プロパティ | 型 | デフォルト | 説明 |
---|---|---|---|
children | ReactNode | <Icon icon="menu" /> | メニューボタンのカスタムコンテンツ(デフォルトはハンバーガーアイコン) |
isMenuOpen | boolean | コンテキストから | 現在のメニュー開閉状態 |
setIsMenuOpen | (isMenuOpen: boolean) => void | コンテキストから | メニュー状態を切り替える関数 |
注意: このコンポーネントはすべてのHTML button
要素プロパティを継承します。
SideNavigation.Links
プロパティ | 型 | デフォルト | 説明 |
---|---|---|---|
children | ReactNode | デフォルトリンクレンダリング | デフォルトリンクレンダリングをオーバーライドするカスタムコンテンツ |
header | { icon?: IconType; text?: ReactNode; href: string } | コンテキストから | 表示するヘッダーリンクオブジェクト |
links | { icon?: IconType; text?: ReactNode; href: string }[] | コンテキストから | 表示するナビゲーションリンクの配列 |
注意: このコンポーネントはすべてのHTML nav
要素プロパティを継承します。
🔧 TypeScriptサポート
包括的な型定義による完全なTypeScriptサポート:
import {SideNavigation} from '@nodeblocks/frontend-side-navigation-block';
import {ComponentProps, ReactNode} from 'react';
// メインコンポーネントインターフェース
interface SideNavigationProps extends Omit<ComponentProps<'aside'>, 'children'> {
isFloating?: boolean;
isMenuOpen?: boolean;
setIsMenuOpen: (isMenuOpen: boolean) => void;
header: { icon?: string; text?: ReactNode; href: string };
links: { icon?: string; text?: ReactNode; href: string }[];
}
// 包括的な型付けでの使用例
interface CustomNavigationData {
headerItem: { icon?: string; text?: ReactNode; href: string };
menuItems: { icon?: string; text?: ReactNode; href: string }[];
isResponsive: boolean;
onMenuToggle: (isOpen: boolean) => void;
}
const NavigationComponent = ({headerItem, menuItems, isResponsive, onMenuToggle}: CustomNavigationData) => {
const [isOpen, setIsOpen] = useState(false);
const handleMenuToggle = (isMenuOpen: boolean) => {
setIsOpen(isMenuOpen);
onMenuToggle(isMenuOpen);
};
return (
<SideNavigation
isFloating={isResponsive}
isMenuOpen={isOpen}
setIsMenuOpen={handleMenuToggle}
header={headerItem}
links={menuItems}
onClick={e => console.log('ナビゲーションがクリックされました')}>
<SideNavigation.Links />
</SideNavigation>
);
};
React、TypeScript、モダンWebスタンダードを使用して❤️で構築されました。