サイドバー (別名ドロワー) は、オーバーレイとして表示されるコンテナコンポーネントです。
import { Sidebar } from 'primereact/sidebar';
サイドバーはコンテナとして使用され、可視性は`visible`のバインドと`onHide`イベントコールバックで制御されます。
<div className="card flex justify-content-center">
<Sidebar visible={visible} onHide={() => setVisible(false)}>
<h2>Sidebar</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</p>
</Sidebar>
<Button icon="pi pi-arrow-right" onClick={() => setVisible(true)} />
</div>
サイドバーの位置は`position`プロパティで設定され、`left`、`right`、`top`、`bottom`の値を取ることができます。
<div className="flex gap-2 justify-content-center">
<Button icon="pi pi-arrow-right" onClick={() => setVisibleLeft(true)} />
<Button icon="pi pi-arrow-left" onClick={() => setVisibleRight(true)} />
<Button icon="pi pi-arrow-down" onClick={() => setVisibleTop(true)} />
<Button icon="pi pi-arrow-up" onClick={() => setVisibleBottom(true)} />
</div>
<Sidebar visible={visibleLeft} position="left" onHide={() => setVisibleLeft(false)}>
<h2>Left Sidebar</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</p>
</Sidebar>
<Sidebar visible={visibleRight} position="right" onHide={() => setVisibleRight(false)}>
<h2>Right Sidebar</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</p>
</Sidebar>
<Sidebar visible={visibleTop} position="top" onHide={() => setVisibleTop(false)}>
<h2>Top Sidebar</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</p>
</Sidebar>
<Sidebar visible={visibleBottom} position="bottom" onHide={() => setVisibleBottom(false)}>
<h2>Bottom Sidebar</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</p>
</Sidebar>
サイドバーの寸法は`style`または`className`プロパティで定義できます。PrimeFlexなどのCSSユーティリティライブラリと併用すると、レスポンシブにもなります。
<div className="card flex justify-content-center">
<Sidebar visible={visible} onHide={() => setVisible(false)} fullScreen>
<h2>Sidebar</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</p>
</Sidebar>
<Button icon="pi pi-th-large" onClick={() => setVisible(true)} />
</div>
`fullScreen`プロパティを有効にすると、サイドバーはページ全体を覆うことができます。
<div className="card flex justify-content-center">
<Sidebar visible={visible} onHide={() => setVisible(false)} fullScreen>
<h2>Sidebar</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</p>
</Sidebar>
<Button icon="pi pi-arrow-right" onClick={() => setVisible(true)} />
</div>
ヘッダーセクションに追加のコンテンツは、`icons`と`header`プロパティを使用して提供されます。
<Sidebar visible={visible} onHide={() => setVisible(false)} icons={customIcons}>
<h2>Sidebar</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</p>
</Sidebar>
<Button icon="pi pi-plus" onClick={() => setVisible(true)} />
`content`プロパティを定義することでヘッドレスモードが有効になり、デフォルトの要素ではなく、サイドバーのUI全体を実装できます。
<Sidebar
visible={visible}
onHide={() => setVisible(false)}
content={({ closeIconRef, hide }) => (
<div className="min-h-screen flex relative lg:static surface-ground">
<div id="app-sidebar-2" className="surface-section h-screen block flex-shrink-0 absolute lg:static left-0 top-0 z-1 border-right-1 surface-border select-none" style={{ width: '280px' }}>
<div className="flex flex-column h-full">
<div className="flex align-items-center justify-content-between px-4 pt-3 flex-shrink-0">
<span className="inline-flex align-items-center gap-2">
<svg width="35" height="40" viewBox="0 0 35 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="..."
fill="var(--primary-color)"
/>
<path
d="..."
fill="var(--text-color)"
/>
</svg>
<span className="font-semibold text-2xl text-primary">Your Logo</span>
</span>
<span>
<Button type="button" ref={closeIconRef} onClick={(e) => hide(e)} icon="pi pi-times" rounded outlined className="h-2rem w-2rem"></Button>
</span>
</div>
<div className="overflow-y-auto">
<ul className="list-none p-3 m-0">
<li>
<StyleClass nodeRef={btnRef1} selector="@next" enterClassName="hidden" enterActiveClassName="slidedown" leaveToClassName="hidden" leaveActiveClassName="slideup">
<div ref={btnRef1} className="p-ripple p-3 flex align-items-center justify-content-between text-600 cursor-pointer">
<span className="font-medium">FAVORITES</span>
<i className="pi pi-chevron-down"></i>
<Ripple />
</div>
</StyleClass>
<ul className="list-none p-0 m-0 overflow-hidden">
<li>
<a className="p-ripple flex align-items-center cursor-pointer p-3 border-round text-700 hover:surface-100 transition-duration-150 transition-colors w-full">
<i className="pi pi-home mr-2"></i>
<span className="font-medium">Dashboard</span>
<Ripple />
</a>
</li>
<li>
<a className="p-ripple flex align-items-center cursor-pointer p-3 border-round text-700 hover:surface-100 transition-duration-150 transition-colors w-full">
<i className="pi pi-bookmark mr-2"></i>
<span className="font-medium">Bookmarks</span>
<Ripple />
</a>
</li>
<li>
<StyleClass nodeRef={btnRef2} selector="@next" enterClassName="hidden" enterActiveClassName="slidedown" leaveToClassName="hidden" leaveActiveClassName="slideup">
<a ref={btnRef2} className="p-ripple flex align-items-center cursor-pointer p-3 border-round text-700 hover:surface-100 transition-duration-150 transition-colors w-full">
<i className="pi pi-chart-line mr-2"></i>
<span className="font-medium">Reports</span>
<i className="pi pi-chevron-down ml-auto mr-1"></i>
<Ripple />
</a>
</StyleClass>
<ul className="list-none py-0 pl-3 pr-0 m-0 hidden overflow-y-hidden transition-all transition-duration-400 transition-ease-in-out">
<li>
<StyleClass nodeRef={btnRef3} selector="@next" enterClassName="hidden" enterActiveClassName="slidedown" leaveToClassName="hidden" leaveActiveClassName="slideup">
<a ref={btnRef3} className="p-ripple flex align-items-center cursor-pointer p-3 border-round text-700 hover:surface-100 transition-duration-150 transition-colors w-full">
<i className="pi pi-chart-line mr-2"></i>
<span className="font-medium">Revenue</span>
<i className="pi pi-chevron-down ml-auto mr-1"></i>
<Ripple />
</a>
</StyleClass>
<ul className="list-none py-0 pl-3 pr-0 m-0 hidden overflow-y-hidden transition-all transition-duration-400 transition-ease-in-out">
<li>
<a className="p-ripple flex align-items-center cursor-pointer p-3 border-round text-700 hover:surface-100 transition-duration-150 transition-colors w-full">
<i className="pi pi-table mr-2"></i>
<span className="font-medium">View</span>
<Ripple />
</a>
</li>
<li>
<a className="p-ripple flex align-items-center cursor-pointer p-3 border-round text-700 hover:surface-100 transition-duration-150 transition-colors w-full">
<i className="pi pi-search mr-2"></i>
<span className="font-medium">Search</span>
<Ripple />
</a>
</li>
</ul>
</li>
<li>
<a className="p-ripple flex align-items-center cursor-pointer p-3 border-round text-700 hover:surface-100 transition-duration-150 transition-colors w-full">
<i className="pi pi-chart-line mr-2"></i>
<span className="font-medium">Expenses</span>
<Ripple />
</a>
</li>
</ul>
</li>
<li>
<a className="p-ripple flex align-items-center cursor-pointer p-3 border-round text-700 hover:surface-100 transition-duration-150 transition-colors w-full">
<i className="pi pi-users mr-2"></i>
<span className="font-medium">Team</span>
<Ripple />
</a>
</li>
<li>
<a className="p-ripple flex align-items-center cursor-pointer p-3 border-round text-700 hover:surface-100 transition-duration-150 transition-colors w-full">
<i className="pi pi-comments mr-2"></i>
<span className="font-medium">Messages</span>
<span className="inline-flex align-items-center justify-content-center ml-auto bg-blue-500 text-0 border-circle" style={{ minWidth: '1.5rem', height: '1.5rem' }}>
3
</span>
<Ripple />
</a>
</li>
<li>
<a className="p-ripple flex align-items-center cursor-pointer p-3 border-round text-700 hover:surface-100 transition-duration-150 transition-colors w-full">
<i className="pi pi-calendar mr-2"></i>
<span className="font-medium">Calendar</span>
<Ripple />
</a>
</li>
<li>
<a className="p-ripple flex align-items-center cursor-pointer p-3 border-round text-700 hover:surface-100 transition-duration-150 transition-colors w-full">
<i className="pi pi-cog mr-2"></i>
<span className="font-medium">Settings</span>
<Ripple />
</a>
</li>
</ul>
</li>
</ul>
<ul className="list-none p-3 m-0">
<li>
<StyleClass nodeRef={btnRef4} selector="@next" enterClassName="hidden" enterActiveClassName="slidedown" leaveToClassName="hidden" leaveActiveClassName="slideup">
<div ref={btnRef4} className="p-ripple p-3 flex align-items-center justify-content-between text-600 cursor-pointer">
<span className="font-medium">APPLICATION</span>
<i className="pi pi-chevron-down"></i>
<Ripple />
</div>
</StyleClass>
<ul className="list-none p-0 m-0 overflow-hidden">
<li>
<a className="p-ripple flex align-items-center cursor-pointer p-3 border-round text-700 hover:surface-100 transition-duration-150 transition-colors w-full">
<i className="pi pi-folder mr-2"></i>
<span className="font-medium">Projects</span>
<Ripple />
</a>
</li>
<li>
<a className="p-ripple flex align-items-center cursor-pointer p-3 border-round text-700 hover:surface-100 transition-duration-150 transition-colors w-full">
<i className="pi pi-chart-bar mr-2"></i>
<span className="font-medium">Performance</span>
<Ripple />
</a>
</li>
<li>
<a className="p-ripple flex align-items-center cursor-pointer p-3 border-round text-700 hover:surface-100 transition-duration-150 transition-colors w-full">
<i className="pi pi-cog mr-2"></i>
<span className="font-medium">Settings</span>
<Ripple />
</a>
</li>
</ul>
</li>
</ul>
</div>
<div className="mt-auto">
<hr className="mb-3 mx-3 border-top-1 border-none surface-border" />
<a v-ripple className="m-3 flex align-items-center cursor-pointer p-3 gap-2 border-round text-700 hover:surface-100 transition-duration-150 transition-colors p-ripple">
<Avatar image="https://primefaces.org/cdn/primereact/images/avatar/amyelsner.png" shape="circle" />
<span className="font-bold">Amy Elsner</span>
</a>
</div>
</div>
</div>
</div>
)}
></Sidebar>
サイドバーコンポーネントはデフォルトで`complementary`ロールを使用します。ルート要素に属性が渡されるため、使用例に応じてariaロールを変更でき、`aria-labelledby`などの追加属性を追加できます。さらに、開いている間はフォーカスがサイドバー内に保持されるため、`aria-modal`が追加されます。
キーボードでアクセスできるボタンなどのトリガーコンポーネントを使用することをお勧めします。そうでない場合は、`tabIndex`を追加する必要があります。
トリガー要素では、`aria-expanded`と`aria-controls`も明示的に処理する必要があります。
<Button icon="pi pi-arrow-right" onClick={(e) => setVisible(true)} aria-controls={visible ? 'sbar' : null} aria-expanded={visible ? true : false}/>
<Sidebar id="sidebar" visible={visible} onHide={() => setVisible(false)} role="region">
Content
</Sidebar>
キー | 機能 |
---|---|
tab | サイドバー内の次のフォーカス可能な要素にフォーカスを移動します。 |
shift + tab | サイドバー内の前のフォーカス可能な要素にフォーカスを移動します。 |
escape | `closeOnEscape`がtrueの場合、ダイアログを閉じます。 |
キー | 機能 |
---|---|
enter | サイドバーを閉じます。 |
space | サイドバーを閉じます。 |