or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

core-components.mdhooks.mdindex.mdoption-components.mdutility-components.md
tile.json

core-components.mddocs/

Core Menu Components

Essential components for building basic dropdown menus with proper structure and accessibility. These components work together to create the fundamental menu interaction pattern.

Capabilities

Menu

Root component that provides context, state management, and focus coordination for all child menu components. Does not render any DOM elements.

/**
 * Root menu context provider that manages state and focus
 * @param props - Menu configuration and children
 */
const Menu: React.FC<MenuProps>;

interface MenuProps extends UseMenuProps, ThemingProps<"Menu"> {
  /** Render prop or direct children for menu content */
  children: MaybeRenderProp<{
    isOpen: boolean;
    onClose: () => void;
    forceUpdate: (() => void) | undefined;
  }>;
}

type MaybeRenderProp<P> = React.ReactNode | ((props: P) => React.ReactNode);

Usage Examples:

import { Menu, MenuButton, MenuList, MenuItem } from "@chakra-ui/menu";

// Basic usage
function BasicMenu() {
  return (
    <Menu>
      <MenuButton>Actions</MenuButton>
      <MenuList>
        <MenuItem>Option 1</MenuItem>
        <MenuItem>Option 2</MenuItem>
      </MenuList>
    </Menu>
  );
}

// Render prop pattern
function RenderPropMenu() {
  return (
    <Menu>
      {({ isOpen, onClose }) => (
        <>
          <MenuButton bg={isOpen ? "blue.100" : "white"}>
            {isOpen ? "Close" : "Open"} Menu
          </MenuButton>
          <MenuList>
            <MenuItem onClick={onClose}>Close Menu</MenuItem>
          </MenuList>
        </>
      )}
    </Menu>
  );
}

// Controlled usage
function ControlledMenu() {
  const [isOpen, setIsOpen] = useState(false);
  
  return (
    <Menu 
      isOpen={isOpen} 
      onClose={() => setIsOpen(false)}
      closeOnSelect={false}
    >
      <MenuButton onClick={() => setIsOpen(!isOpen)}>
        Toggle Menu
      </MenuButton>
      <MenuList>
        <MenuItem>Persistent Option</MenuItem>
      </MenuList>
    </Menu>
  );
}

MenuButton

Trigger button that opens and controls the menu. Must be a direct child of Menu component.

/**
 * Menu trigger button with proper ARIA attributes and keyboard handling
 * @param props - Button properties and styling
 * @param ref - Forward ref to the button element
 */
const MenuButton: React.ForwardRefExoticComponent<MenuButtonProps>;

interface MenuButtonProps extends HTMLChakraProps<"button"> {
  /** Alternative component to render instead of button */
  as?: React.ElementType;
  /** Button content */
  children?: React.ReactNode;
}

Usage Examples:

// Basic button
<MenuButton>Click me</MenuButton>

// Custom styled button  
<MenuButton
  px={4}
  py={2}
  transition="all 0.2s"
  borderRadius="md"
  borderWidth="1px"
  _hover={{ bg: "gray.100" }}
  _expanded={{ bg: "blue.200" }}
  _focus={{ boxShadow: "outline" }}
>
  Styled Menu
</MenuButton>

// Custom component as button
<MenuButton as={IconButton} aria-label="Menu" icon={<HamburgerIcon />} />

// Link as menu button
<MenuButton as={Link} href="#" textDecoration="none">
  Menu Link
</MenuButton>

MenuList

Container for menu items that handles positioning, animation, and keyboard navigation.

/**
 * Menu container with positioning, animation, and keyboard handling
 * @param props - Container properties and motion configuration
 * @param ref - Forward ref to the menu list element
 */
const MenuList: React.ForwardRefExoticComponent<MenuListProps>;

interface MenuListProps extends HTMLChakraProps<"div"> {
  /** Props for the positioning wrapper element */
  rootProps?: HTMLChakraProps<"div">;
  /** Framer Motion animation properties */
  motionProps?: HTMLMotionProps<"div">;
  /** Custom z-index for menu positioning */  
  zIndex?: number;
}

Usage Examples:

// Basic menu list
<MenuList>
  <MenuItem>Option 1</MenuItem>
  <MenuItem>Option 2</MenuItem>
</MenuList>

// Custom styling
<MenuList bg="gray.800" color="white" border="none">
  <MenuItem>Dark Theme Option</MenuItem>
</MenuList>

// Custom animations
<MenuList
  motionProps={{
    variants: {
      enter: { y: 0, opacity: 1 },
      exit: { y: -20, opacity: 0 }
    }
  }}
>
  <MenuItem>Animated Option</MenuItem>
</MenuList>

// Positioning wrapper props
<MenuList rootProps={{ bg: "blue.50", p: 2 }}>
  <MenuItem>Wrapped Option</MenuItem>
</MenuList>

MenuItem

Individual selectable menu item with optional icon and command text.

/**
 * Individual menu item with icon and command support
 * @param props - Item properties including content and behavior
 * @param ref - Forward ref to the menu item element
 */
const MenuItem: React.ForwardRefExoticComponent<MenuItemProps>;

interface MenuItemProps extends Omit<HTMLChakraProps<"button">, "disabled" | "aria-disabled">, MenuItemOptions {
  /** Item content */
  children?: React.ReactNode;
}

interface MenuItemOptions {
  /** Whether the menu item is disabled */
  isDisabled?: boolean;
  /** Whether disabled items remain keyboard focusable */
  isFocusable?: boolean;
  /** Override parent menu's closeOnSelect behavior */
  closeOnSelect?: boolean;
  /** Icon to display before the item text */
  icon?: React.ReactElement;
  /** Spacing between icon and text */
  iconSpacing?: SystemProps["mr"];
  /** Command/shortcut text to display on the right */
  command?: string;
  /** Spacing between text and command */
  commandSpacing?: SystemProps["ml"];
}

Usage Examples:

// Basic menu item
<MenuItem>Simple Item</MenuItem>

// With icon and command
<MenuItem icon={<DownloadIcon />} command="⌘D">
  Download
</MenuItem>

// Disabled item
<MenuItem isDisabled>
  Disabled Option
</MenuItem>

// Custom component
<MenuItem as="a" href="/profile">
  Go to Profile
</MenuItem>

// Custom click handler
<MenuItem onClick={() => console.log("Clicked!")}>
  Custom Action
</MenuItem>

// Override close behavior
<MenuItem closeOnSelect={false}>
  Keep Menu Open
</MenuItem>

// Custom styling
<MenuItem 
  bg="red.50" 
  color="red.600"
  _hover={{ bg: "red.100" }}
>
  Delete Item
</MenuItem>

Common Patterns

Menu with Icons and Commands

function IconCommandMenu() {
  return (
    <Menu>
      <MenuButton>File</MenuButton>
      <MenuList>
        <MenuItem icon={<AddIcon />} command="⌘N">
          New File
        </MenuItem>
        <MenuItem icon={<EditIcon />} command="⌘O">
          Open File  
        </MenuItem>
        <MenuItem icon={<DownloadIcon />} command="⌘S">
          Save File
        </MenuItem>
        <MenuItem isDisabled icon={<DeleteIcon />}>
          Delete File
        </MenuItem>
      </MenuList>
    </Menu>
  );
}

Conditional Menu Items

function ConditionalMenu({ isLoggedIn, canDelete }) {
  return (
    <Menu>
      <MenuButton>Actions</MenuButton>
      <MenuList>
        <MenuItem>View</MenuItem>
        <MenuItem>Edit</MenuItem>
        {isLoggedIn && (
          <MenuItem>Share</MenuItem>
        )}
        {canDelete && (
          <MenuItem color="red.500">Delete</MenuItem>
        )}
      </MenuList>
    </Menu>
  );
}

Menu with Mixed Content

function MixedContentMenu() {
  return (
    <Menu>
      <MenuButton>Profile</MenuButton>
      <MenuList>
        <MenuItem minH="48px">
          <Avatar size="sm" mr={3} />
          <Box>
            <Text fontWeight="semibold">John Doe</Text>
            <Text fontSize="sm" color="gray.500">john@example.com</Text>
          </Box>
        </MenuItem>
        <MenuDivider />
        <MenuItem>Settings</MenuItem>
        <MenuItem>Billing</MenuItem>
        <MenuDivider />
        <MenuItem color="red.500">Sign Out</MenuItem>
      </MenuList>
    </Menu>
  );
}