index.tsx58 lines · main
| 1 | import { Badge, Menu } from 'ui' |
| 2 | |
| 3 | import type { ProductMenuGroup } from './ProductMenu.types' |
| 4 | import { ProductMenuItem } from './ProductMenuItem' |
| 5 | |
| 6 | interface ProductMenuProps { |
| 7 | page?: string |
| 8 | menu: ProductMenuGroup[] |
| 9 | /** Called when a menu item link is clicked (e.g. to close a sheet on navigation) */ |
| 10 | onItemClick?: () => void |
| 11 | } |
| 12 | |
| 13 | export const ProductMenu = ({ page, menu, onItemClick }: ProductMenuProps) => { |
| 14 | return ( |
| 15 | <div className="flex flex-col space-y-4"> |
| 16 | <Menu type="pills"> |
| 17 | {menu.map((group, idx) => ( |
| 18 | <div key={group.key || group.title}> |
| 19 | <div className="my-4 space-y-4"> |
| 20 | <div className="md:mx-3"> |
| 21 | <Menu.Group |
| 22 | title={ |
| 23 | group.title ? ( |
| 24 | <div className="flex flex-col space-y-2 uppercase font-mono"> |
| 25 | <span>{group.title}</span> |
| 26 | {group.isPreview && <Badge variant="warning">Not production ready</Badge>} |
| 27 | </div> |
| 28 | ) : null |
| 29 | } |
| 30 | /> |
| 31 | <div> |
| 32 | {group.items.map((item) => { |
| 33 | const isActive = !!item.pages |
| 34 | ? item.pages.includes(page ?? '') |
| 35 | : page === item.key |
| 36 | |
| 37 | return ( |
| 38 | <ProductMenuItem |
| 39 | key={item.key} |
| 40 | item={item} |
| 41 | isActive={isActive} |
| 42 | target={item.isExternal ? '_blank' : '_self'} |
| 43 | onClick={onItemClick} |
| 44 | /> |
| 45 | ) |
| 46 | })} |
| 47 | </div> |
| 48 | </div> |
| 49 | </div> |
| 50 | {idx !== menu.length - 1 && ( |
| 51 | <div className="h-px w-[calc(100%-1.5rem)] mx-auto md:w-full bg-border-overlay" /> |
| 52 | )} |
| 53 | </div> |
| 54 | ))} |
| 55 | </Menu> |
| 56 | </div> |
| 57 | ) |
| 58 | } |