# How to handle Menu/Popout triggers Using react context to manage collections ``` NOTE: Not completely correct code snippets ``` Current proposed API (insipired by Ant design for the Submenu part): ```typescript const example = ( <Menu trigger={<Button />}> <MenuItem /> <MenuItem /> <SubMenu content="Menu item slot"> <MenuItem /> <MenuItem /> <MenuItem /> </SubMenu> </Menu> ) ``` Intent: * find some way to couple trigger and menu together in a way that makes sense * implicitly require consumers to use correct menu semantics Pros: * For simple cases it looks 'correct' * Not too unlike DOM structure Cons: * Where is the trigger actually rendered ? it's the children of menu that should be rendered in the popup * Customization of the `SubMenu` trigger slot can be messy * Open questions on slot selection: why use slot for the trigger but not menu content ? ```typescript= <SubMenu content={{children: (ComponentType, props) => <MyCustomComponent />}} /> ``` * Questionable difference in `Submenu` API -> it really is just a `Menu` # Other ways of doing it ### React spectrum A modified way proposed by shift, I am very convinced, would like quorum on some of the cons: ```typescript= <Menu> {createMenuTrigger(({open, ref, ...rest}) => <div {...rest}>Something</div>)} <MenuTrigger {/**no props**/}>{element}</MenuTrigger> <MenuList> <MenuItem /> <Menu> <MenuTrigger> <MenuItem /> </MenuTrigger> <MenuList> <MenuItem /> <MenuItem /> </MenuList> </Menu> </MenuList> </Menu> ``` Pros: * Scalable, and makes sense and reuses components+concepts * JSX resembles the DOM a lot more Cons: * No build time validations * What happens if there are multiple triggers or multiple children in `MenuTrigger` ? * in React spectrum -> silently breaks * Validation -> to throw at runtime/test time # Reakit I am interested... but very new to composition ```typescript= const PreferencesMenu = React.forwardRef((props, ref) => { const menu = useMenuState(); return ( <> <MenuButton ref={ref} {...menu} {...props}> Preferences </MenuButton> <Menu {...menu}> <MenuItem {...menu}>Settings</MenuItem> <MenuItem {...menu}> Extensions </MenuItem> </Menu> </> ); }); function Example() { const menu = useMenuState(); return ( <> <MenuButton {...menu}>Code</MenuButton> <Menu {...menu}> <MenuItem {...menu} as={PreferencesMenu} /> </Menu> </> ); } ```