Skip to main content
Glama

@arizeai/phoenix-mcp

Official
by Arize-ai
Menu.stories.tsx5.74 kB
import { useMemo } from "react"; import { Autocomplete, Collection, Header, Input, MenuSection, SubmenuTrigger, useFilter, } from "react-aria-components"; import { Meta } from "@storybook/react"; import { Button, Flex, Icon, Icons, Menu, MenuItem, MenuTrigger, Popover, SearchField, Separator, Text, View, } from "@phoenix/components"; const meta: Meta<typeof Menu> = { title: "Menu", component: Menu, parameters: { layout: "centered", }, }; export default meta; const NESTED_MENU_ITEMS = [ { id: "1", name: "Item 1 Group", children: [ { id: "1.1", name: "Item 1.1", }, ], }, { id: "2", name: "Item 2 Group", }, { id: "3", name: "Item 3 Group", children: [ { id: "3.1", name: "Item 3.1", }, { id: "3.2", name: "Item 3.2", }, { id: "3.3", name: "Item 3.3 Group", children: [ { id: "3.3.1", name: "Item 3.3.1", }, ], }, ], }, ]; export const Template = () => { return ( <MenuTrigger> <Button>Open Menu</Button> <Popover> <Menu> <MenuItem>Item 1</MenuItem> <MenuItem>Item 2</MenuItem> <MenuItem>Item 3</MenuItem> </Menu> </Popover> </MenuTrigger> ); }; Template.args = {}; export const DynamicSearchableMenu = () => { const { contains } = useFilter({ sensitivity: "base" }); return ( <Flex direction="column" gap="size-200"> <Text>View the storybook for comments on implementation</Text> <MenuTrigger> <div> <Button leadingVisual={<Icon svg={<Icons.Search />} />}> Searchable Menu </Button> </div> <Popover> {/* Wrap the menu in an Autocomplete component */} <Autocomplete filter={contains}> {/* Nest a SearchField as child, it will automatically filter the sibling menu items */} <View paddingX="size-100" marginTop="size-100"> <SearchField aria-label="Search" autoFocus> <Input placeholder="Search..." /> </SearchField> </View> {/* Provide the items as a prop to menu, instantiating a react-aria collection */} <Menu items={NESTED_MENU_ITEMS}> {function renderMenuItem({ id, name, children }) { // handle items with children to generate submenus if (children) { return ( <SubmenuTrigger> <MenuItem key={id}>{name}</MenuItem> <Popover> {/* You can nest another Autocomplete here */} <Autocomplete filter={contains}> <View paddingX="size-100" marginTop="size-100"> {/* This will find the nearest autocomplete and menu items */} <SearchField aria-label="Search"> <Input placeholder="Search..." /> </SearchField> </View> <Menu items={children}> {/* recursively call the render fn to render submenu item children */} {(item) => renderMenuItem(item)} </Menu> </Autocomplete> </Popover> </SubmenuTrigger> ); } // handle items with no children return <MenuItem key={id}>{name}</MenuItem>; }} </Menu> </Autocomplete> </Popover> </MenuTrigger> </Flex> ); }; export const SectionedMenu = () => { const lastSection = useMemo(() => { return NESTED_MENU_ITEMS[NESTED_MENU_ITEMS.length - 1]; }, []); return ( <Flex direction="column" gap="size-200"> <Text>View the storybook for comments on implementation</Text> <MenuTrigger> <div> <Button>Menu with Sections</Button> </div> <Popover> <Menu items={NESTED_MENU_ITEMS} renderEmptyState={() => "No Items in Section"} > {/* You could support nested section rendering by naming this render function and calling it recursively. For now, this example just renders sections one level deep */} {(section) => { // do not render empty sections, it is difficult to add an empty state to them // you could possibly add a menu item that links to the place to add data that would populate this section if (!section.children) return <></>; return ( <> <MenuSection> <Header> <Flex justifyContent="space-between" alignItems="center"> <Text weight="heavy">{section.name}</Text> <Text size="S">({section.children.length})</Text> </Flex> </Header> <Collection items={section.children}> {(item) => <MenuItem key={item.id}>{item.name}</MenuItem>} </Collection> </MenuSection> {/* Only render a separator if this is not the last section, otherwise it looks ugly */} {section.name !== lastSection.name && <Separator />} </> ); }} </Menu> </Popover> </MenuTrigger> </Flex> ); };

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Arize-ai/phoenix'

If you have feedback or need assistance with the MCP directory API, please join our Discord server