Skip to content

DropdownMenu

WARNING

⚠️ If you need to customize your work with the dropdown menu, please refer to the documentation intergalactic/popper

The component is a wrap over intergalactic/dropdown with the following logic:

  • Display of the list of options in a dropdown window
  • Scrolling the list of options using the keyboard
tsx
import React from 'react';
import DropdownMenu from 'intergalactic/dropdown-menu';
import { ButtonTrigger } from 'intergalactic/base-trigger';
import { Text } from 'intergalactic/typography';
import { Flex } from 'intergalactic/flex-box';

const Demo = () => {
  return (
    <Flex direction='column'>
      <Text tag='label' size={200} htmlFor='dropdown-menu-basic'>
        Button trigger
      </Text>
      <DropdownMenu>
        <DropdownMenu.Trigger mt={2} mr='auto' id='dropdown-menu-basic' tag={ButtonTrigger}>
          Click me
        </DropdownMenu.Trigger>
        <DropdownMenu.Menu>
          <DropdownMenu.Item>Item 1</DropdownMenu.Item>
          <DropdownMenu.Item>Item 2</DropdownMenu.Item>
          <DropdownMenu.Item>Item 3</DropdownMenu.Item>
          <DropdownMenu.Item>Item 4</DropdownMenu.Item>
        </DropdownMenu.Menu>
      </DropdownMenu>
    </Flex>
  );
};

export default Demo;
import React from 'react';
import DropdownMenu from 'intergalactic/dropdown-menu';
import { ButtonTrigger } from 'intergalactic/base-trigger';
import { Text } from 'intergalactic/typography';
import { Flex } from 'intergalactic/flex-box';

const Demo = () => {
  return (
    <Flex direction='column'>
      <Text tag='label' size={200} htmlFor='dropdown-menu-basic'>
        Button trigger
      </Text>
      <DropdownMenu>
        <DropdownMenu.Trigger mt={2} mr='auto' id='dropdown-menu-basic' tag={ButtonTrigger}>
          Click me
        </DropdownMenu.Trigger>
        <DropdownMenu.Menu>
          <DropdownMenu.Item>Item 1</DropdownMenu.Item>
          <DropdownMenu.Item>Item 2</DropdownMenu.Item>
          <DropdownMenu.Item>Item 3</DropdownMenu.Item>
          <DropdownMenu.Item>Item 4</DropdownMenu.Item>
        </DropdownMenu.Menu>
      </DropdownMenu>
    </Flex>
  );
};

export default Demo;

There are several methods of displaying the dropdown menu in the component. We will show each of them below.

The first method

We implement it with the help of the combination of two components:

  • DropdownMenu.Popper – layout of a dropdown window
  • DropdownMenu.List and ScrollArea with option list styles

This method is good when you need a flexible content customization in a dropdown menu.

tsx
import React from 'react';
import DropdownMenu from 'intergalactic/dropdown-menu';
import Button from 'intergalactic/button';
import Link from 'intergalactic/link';
import { Text } from 'intergalactic/typography';
import Notice from 'intergalactic/notice';
import SpinContainer from 'intergalactic/spin-container';
import FileExportM from 'intergalactic/icon/FileExport/m';

const Demo = () => {
  const [loading, setLoading] = React.useState(false);

  const handleClick = () => {
    setLoading(true);
    setTimeout(() => setLoading(false), 1000);
  };

  return (
    <DropdownMenu>
      <DropdownMenu.Trigger tag={Button}>
        <Button.Addon>
          <FileExportM />
        </Button.Addon>
        <Button.Text>Export</Button.Text>
      </DropdownMenu.Trigger>
      <DropdownMenu.Popper wMax='257px'>
        <SpinContainer loading={loading}>
          <DropdownMenu.List>
            <DropdownMenu.Item onClick={handleClick}>Excel</DropdownMenu.Item>
            <DropdownMenu.Item onClick={handleClick}>CSV</DropdownMenu.Item>
            <DropdownMenu.Item onClick={handleClick}>CSV Semicolon</DropdownMenu.Item>
          </DropdownMenu.List>
          <Notice
            theme='warning'
            style={{
              padding: '12px 8px',
              borderWidth: 0,
              borderTopWidth: '1px',
              borderRadius: '0 0 6px 6px',
            }}
          >
            <Notice.Content>
              <Text tag='strong' mb={1} style={{ display: 'block' }}>
                Export failed
              </Text>
              <Text lineHeight='18px'>
                If the problem persists, please contact us at{' '}
                <Link inline href='mailto:feedback@semrush.com'>
                  feedback@semrush.com
                </Link>
              </Text>
            </Notice.Content>
          </Notice>
        </SpinContainer>
      </DropdownMenu.Popper>
    </DropdownMenu>
  );
};

export default Demo;
import React from 'react';
import DropdownMenu from 'intergalactic/dropdown-menu';
import Button from 'intergalactic/button';
import Link from 'intergalactic/link';
import { Text } from 'intergalactic/typography';
import Notice from 'intergalactic/notice';
import SpinContainer from 'intergalactic/spin-container';
import FileExportM from 'intergalactic/icon/FileExport/m';

const Demo = () => {
  const [loading, setLoading] = React.useState(false);

  const handleClick = () => {
    setLoading(true);
    setTimeout(() => setLoading(false), 1000);
  };

  return (
    <DropdownMenu>
      <DropdownMenu.Trigger tag={Button}>
        <Button.Addon>
          <FileExportM />
        </Button.Addon>
        <Button.Text>Export</Button.Text>
      </DropdownMenu.Trigger>
      <DropdownMenu.Popper wMax='257px'>
        <SpinContainer loading={loading}>
          <DropdownMenu.List>
            <DropdownMenu.Item onClick={handleClick}>Excel</DropdownMenu.Item>
            <DropdownMenu.Item onClick={handleClick}>CSV</DropdownMenu.Item>
            <DropdownMenu.Item onClick={handleClick}>CSV Semicolon</DropdownMenu.Item>
          </DropdownMenu.List>
          <Notice
            theme='warning'
            style={{
              padding: '12px 8px',
              borderWidth: 0,
              borderTopWidth: '1px',
              borderRadius: '0 0 6px 6px',
            }}
          >
            <Notice.Content>
              <Text tag='strong' mb={1} style={{ display: 'block' }}>
                Export failed
              </Text>
              <Text lineHeight='18px'>
                If the problem persists, please contact us at{' '}
                <Link inline href='mailto:feedback@semrush.com'>
                  feedback@semrush.com
                </Link>
              </Text>
            </Notice.Content>
          </Notice>
        </SpinContainer>
      </DropdownMenu.Popper>
    </DropdownMenu>
  );
};

export default Demo;

The second method

The easiest method is to use DropdownMenu.Menu.

It is appropriate when it is necessary to manage only the content within the options list.

DropdownMenu.Menu is a wrap over DropdownMenu.Popper and DropdownMenu.List. All props will fall through to DropdownMenu.List.

tsx
import React from 'react';
import DropdownMenu from 'intergalactic/dropdown-menu';
import { ButtonTrigger } from 'intergalactic/base-trigger';
import { Text } from 'intergalactic/typography';
import { Flex } from 'intergalactic/flex-box';

const Demo = () => {
  return (
    <Flex direction='column'>
      <Text tag='label' size={200} htmlFor='dropdown-menu-children-items'>
        Button trigger
      </Text>
      <DropdownMenu>
        <DropdownMenu.Trigger
          tag={ButtonTrigger}
          mt={2}
          mr='auto'
          id='dropdown-menu-children-items'
        >
          Click me
        </DropdownMenu.Trigger>
        {/* Adding max-height to the dropdown menu */}
        <DropdownMenu.Menu hMax={'180px'}>
          <DropdownMenu.ItemTitle>List heading</DropdownMenu.ItemTitle>
          <DropdownMenu.Item>Item 1</DropdownMenu.Item>
          <DropdownMenu.Item>Item 2</DropdownMenu.Item>
          <DropdownMenu.Item>Item 3</DropdownMenu.Item>
          <DropdownMenu.Item>Item 4</DropdownMenu.Item>
          <DropdownMenu.Item>Item 5</DropdownMenu.Item>
          <DropdownMenu.Item>Item 6</DropdownMenu.Item>
          <DropdownMenu.Item>Item 7</DropdownMenu.Item>
          <DropdownMenu.Item>Item 8</DropdownMenu.Item>
          <DropdownMenu.Item>Item 9</DropdownMenu.Item>
        </DropdownMenu.Menu>
      </DropdownMenu>
    </Flex>
  );
};

export default Demo;
import React from 'react';
import DropdownMenu from 'intergalactic/dropdown-menu';
import { ButtonTrigger } from 'intergalactic/base-trigger';
import { Text } from 'intergalactic/typography';
import { Flex } from 'intergalactic/flex-box';

const Demo = () => {
  return (
    <Flex direction='column'>
      <Text tag='label' size={200} htmlFor='dropdown-menu-children-items'>
        Button trigger
      </Text>
      <DropdownMenu>
        <DropdownMenu.Trigger
          tag={ButtonTrigger}
          mt={2}
          mr='auto'
          id='dropdown-menu-children-items'
        >
          Click me
        </DropdownMenu.Trigger>
        {/* Adding max-height to the dropdown menu */}
        <DropdownMenu.Menu hMax={'180px'}>
          <DropdownMenu.ItemTitle>List heading</DropdownMenu.ItemTitle>
          <DropdownMenu.Item>Item 1</DropdownMenu.Item>
          <DropdownMenu.Item>Item 2</DropdownMenu.Item>
          <DropdownMenu.Item>Item 3</DropdownMenu.Item>
          <DropdownMenu.Item>Item 4</DropdownMenu.Item>
          <DropdownMenu.Item>Item 5</DropdownMenu.Item>
          <DropdownMenu.Item>Item 6</DropdownMenu.Item>
          <DropdownMenu.Item>Item 7</DropdownMenu.Item>
          <DropdownMenu.Item>Item 8</DropdownMenu.Item>
          <DropdownMenu.Item>Item 9</DropdownMenu.Item>
        </DropdownMenu.Menu>
      </DropdownMenu>
    </Flex>
  );
};

export default Demo;

Elements of the list

The component has several variants of list elements layout:

  • DropdownMenu.Item, which is an element of the list (can be selected with the keyboard)
  • DropdownMenu.ItemTitle, which is the title of the list (cannot be selected with the keyboard)
  • DropdownMenu.ItemHint, which is list subhead or message with additional information (cannot be selected with the keyboard)
tsx
import React from 'react';
import DropdownMenu from 'intergalactic/dropdown-menu';
import { ButtonTrigger } from 'intergalactic/base-trigger';
import { Text } from 'intergalactic/typography';
import { Flex } from 'intergalactic/flex-box';

const Demo = () => {
  return (
    <Flex direction='column'>
      <Text tag='label' size={200} htmlFor='dropdown-menu-elements-of-the-list'>
        Elements of the list
      </Text>
      <DropdownMenu>
        <DropdownMenu.Trigger
          tag={ButtonTrigger}
          mt={2}
          mr='auto'
          id='dropdown-menu-elements-of-the-list'
        >
          I'll show u some options, buddy
        </DropdownMenu.Trigger>
        <DropdownMenu.Menu>
          <DropdownMenu.ItemTitle>I'm title</DropdownMenu.ItemTitle>
          <DropdownMenu.ItemHint>I'm hint</DropdownMenu.ItemHint>
          <DropdownMenu.Item>I'm item</DropdownMenu.Item>
        </DropdownMenu.Menu>
      </DropdownMenu>
    </Flex>
  );
};

export default Demo;
import React from 'react';
import DropdownMenu from 'intergalactic/dropdown-menu';
import { ButtonTrigger } from 'intergalactic/base-trigger';
import { Text } from 'intergalactic/typography';
import { Flex } from 'intergalactic/flex-box';

const Demo = () => {
  return (
    <Flex direction='column'>
      <Text tag='label' size={200} htmlFor='dropdown-menu-elements-of-the-list'>
        Elements of the list
      </Text>
      <DropdownMenu>
        <DropdownMenu.Trigger
          tag={ButtonTrigger}
          mt={2}
          mr='auto'
          id='dropdown-menu-elements-of-the-list'
        >
          I'll show u some options, buddy
        </DropdownMenu.Trigger>
        <DropdownMenu.Menu>
          <DropdownMenu.ItemTitle>I'm title</DropdownMenu.ItemTitle>
          <DropdownMenu.ItemHint>I'm hint</DropdownMenu.ItemHint>
          <DropdownMenu.Item>I'm item</DropdownMenu.Item>
        </DropdownMenu.Menu>
      </DropdownMenu>
    </Flex>
  );
};

export default Demo;

Render-function

As with the lower-level components, you can access the component logic by passing the render-function into the body.

You can see the list of available methods in the API.

tsx
import React from 'react';
import DropdownMenu from 'intergalactic/dropdown-menu';
import { ButtonTrigger } from 'intergalactic/base-trigger';
import { Box } from '@semcore/flex-box';
import { Text } from 'intergalactic/typography';
import { Flex } from 'intergalactic/flex-box';

const Demo = () => {
  return (
    <Flex direction='column'>
      <Text tag='label' size={200} htmlFor='dropdown-menu-render-function'>
        Dropdown menu with render function
      </Text>
      <DropdownMenu>
        {(props, handlers) => {
          const {
            getTriggerProps, // encapsulates Trigger logic
            getPopperProps, // encapsulates Popper logic
            getListProps, // encapsulates List logic
            getItemProps, // // encapsulates Item logic
          } = props;

          const popperProps = getPopperProps();

          return (
            <React.Fragment>
              <ButtonTrigger
                {...getTriggerProps()}
                mt={2}
                mr='auto'
                id='dropdown-menu-render-function'
              >
                Click me
              </ButtonTrigger>
              <Box
                {...popperProps}
                hidden={!popperProps.visible}
                zIndex={10}
                p={2}
                style={{
                  backgroundColor: 'var(--intergalactic-bg-primary-neutral, #FFF)',
                  border: '1px solid gray',
                }}
              >
                <ul {...getListProps()}>
                  <li {...getItemProps()}>Option 1</li>
                  <li {...getItemProps()}>Option 2</li>
                  <li {...getItemProps()}>Option 3</li>
                  <li {...getItemProps()}>Option 4</li>
                  <li {...getItemProps()}>Option 5</li>
                </ul>
                <button type='button' onClick={() => handlers.visible(false)}>
                  Close me
                </button>
                <button type='button' onClick={() => handlers.highlightedIndex(2)}>
                  Highlight item 3
                </button>
              </Box>
            </React.Fragment>
          );
        }}
      </DropdownMenu>
    </Flex>
  );
};

export default Demo;
import React from 'react';
import DropdownMenu from 'intergalactic/dropdown-menu';
import { ButtonTrigger } from 'intergalactic/base-trigger';
import { Box } from '@semcore/flex-box';
import { Text } from 'intergalactic/typography';
import { Flex } from 'intergalactic/flex-box';

const Demo = () => {
  return (
    <Flex direction='column'>
      <Text tag='label' size={200} htmlFor='dropdown-menu-render-function'>
        Dropdown menu with render function
      </Text>
      <DropdownMenu>
        {(props, handlers) => {
          const {
            getTriggerProps, // encapsulates Trigger logic
            getPopperProps, // encapsulates Popper logic
            getListProps, // encapsulates List logic
            getItemProps, // // encapsulates Item logic
          } = props;

          const popperProps = getPopperProps();

          return (
            <React.Fragment>
              <ButtonTrigger
                {...getTriggerProps()}
                mt={2}
                mr='auto'
                id='dropdown-menu-render-function'
              >
                Click me
              </ButtonTrigger>
              <Box
                {...popperProps}
                hidden={!popperProps.visible}
                zIndex={10}
                p={2}
                style={{
                  backgroundColor: 'var(--intergalactic-bg-primary-neutral, #FFF)',
                  border: '1px solid gray',
                }}
              >
                <ul {...getListProps()}>
                  <li {...getItemProps()}>Option 1</li>
                  <li {...getItemProps()}>Option 2</li>
                  <li {...getItemProps()}>Option 3</li>
                  <li {...getItemProps()}>Option 4</li>
                  <li {...getItemProps()}>Option 5</li>
                </ul>
                <button type='button' onClick={() => handlers.visible(false)}>
                  Close me
                </button>
                <button type='button' onClick={() => handlers.highlightedIndex(2)}>
                  Highlight item 3
                </button>
              </Box>
            </React.Fragment>
          );
        }}
      </DropdownMenu>
    </Flex>
  );
};

export default Demo;

Nested dropdown menus

You can use DropdownMenu.Nesting and DropdownMenu.Nesting.Trigger to create basic nested menus. Refer to this example to see needed components structure.

tsx
import React from 'react';
import DropdownMenu from 'intergalactic/dropdown-menu';
import { ButtonTrigger } from 'intergalactic/base-trigger';
import ChevronRightIcon from 'intergalactic/icon/ChevronRight/m';
import { Text } from 'intergalactic/typography';
import { Flex } from 'intergalactic/flex-box';

const Demo = () => {
  return (
    <Flex direction='column'>
      <Text tag='label' size={200} htmlFor='dropdown-menu-nested'>
        Nested dropdown menu
      </Text>
      <DropdownMenu>
        <DropdownMenu.Trigger mt={2} mr='auto' id='dropdown-menu-nested' tag={ButtonTrigger}>
          Click me
        </DropdownMenu.Trigger>
        <DropdownMenu.Menu>
          <DropdownMenu.Item>Item 1</DropdownMenu.Item>
          <DropdownMenu.Item>Item 2</DropdownMenu.Item>
          <DropdownMenu.Item>Item 3</DropdownMenu.Item>
          <DropdownMenu.Nesting>
            <DropdownMenu placement='right' interaction='hover' timeout={[0, 300]}>
              <DropdownMenu.Trigger tag={DropdownMenu.Nesting.Trigger}>
                Item 4
                <DropdownMenu.Nesting.Addon tag={ChevronRightIcon} color='icon-secondary-neutral' />
              </DropdownMenu.Trigger>
              <DropdownMenu.Menu w={120}>
                <DropdownMenu.Nesting>
                  <DropdownMenu placement='right' interaction='hover' timeout={[0, 300]}>
                    <DropdownMenu.Trigger tag={DropdownMenu.Nesting.Trigger}>
                      Item 4.1
                      <DropdownMenu.Nesting.Addon
                        tag={ChevronRightIcon}
                        color='icon-secondary-neutral'
                      />
                    </DropdownMenu.Trigger>
                    <DropdownMenu.Menu w={120}>
                      <DropdownMenu.Item>Item 4.1.1</DropdownMenu.Item>
                      <DropdownMenu.Item>Item 4.1.2</DropdownMenu.Item>
                      <DropdownMenu.Item>Item 4.1.3</DropdownMenu.Item>
                    </DropdownMenu.Menu>
                  </DropdownMenu>
                </DropdownMenu.Nesting>
                <DropdownMenu.Nesting>
                  <DropdownMenu placement='right' interaction='hover' timeout={[0, 300]}>
                    <DropdownMenu.Trigger tag={DropdownMenu.Nesting.Trigger}>
                      Item 4.2
                      <DropdownMenu.Nesting.Addon
                        tag={ChevronRightIcon}
                        color='icon-secondary-neutral'
                      />
                    </DropdownMenu.Trigger>
                    <DropdownMenu.Menu w={120}>
                      <DropdownMenu.Nesting>
                        <DropdownMenu placement='right' interaction='hover' timeout={[0, 300]}>
                          <DropdownMenu.Trigger tag={DropdownMenu.Nesting.Trigger}>
                            Item 4.2.1
                            <DropdownMenu.Nesting.Addon
                              tag={ChevronRightIcon}
                              color='icon-secondary-neutral'
                            />
                          </DropdownMenu.Trigger>
                          <DropdownMenu.Menu w={120}>
                            <DropdownMenu.Item>Item 4.2.1.1</DropdownMenu.Item>
                            <DropdownMenu.Item>Item 4.2.1.2</DropdownMenu.Item>
                            <DropdownMenu.Item>Item 4.2.1.3</DropdownMenu.Item>
                          </DropdownMenu.Menu>
                        </DropdownMenu>
                      </DropdownMenu.Nesting>
                      <DropdownMenu.Item>Item 4.2.2</DropdownMenu.Item>
                      <DropdownMenu.Item>Item 4.2.3</DropdownMenu.Item>
                    </DropdownMenu.Menu>
                  </DropdownMenu>
                </DropdownMenu.Nesting>
                <DropdownMenu.Item>Item 4.3</DropdownMenu.Item>
              </DropdownMenu.Menu>
            </DropdownMenu>
          </DropdownMenu.Nesting>
          <DropdownMenu.Item>Item 5</DropdownMenu.Item>
        </DropdownMenu.Menu>
      </DropdownMenu>
    </Flex>
  );
};

export default Demo;
import React from 'react';
import DropdownMenu from 'intergalactic/dropdown-menu';
import { ButtonTrigger } from 'intergalactic/base-trigger';
import ChevronRightIcon from 'intergalactic/icon/ChevronRight/m';
import { Text } from 'intergalactic/typography';
import { Flex } from 'intergalactic/flex-box';

const Demo = () => {
  return (
    <Flex direction='column'>
      <Text tag='label' size={200} htmlFor='dropdown-menu-nested'>
        Nested dropdown menu
      </Text>
      <DropdownMenu>
        <DropdownMenu.Trigger mt={2} mr='auto' id='dropdown-menu-nested' tag={ButtonTrigger}>
          Click me
        </DropdownMenu.Trigger>
        <DropdownMenu.Menu>
          <DropdownMenu.Item>Item 1</DropdownMenu.Item>
          <DropdownMenu.Item>Item 2</DropdownMenu.Item>
          <DropdownMenu.Item>Item 3</DropdownMenu.Item>
          <DropdownMenu.Nesting>
            <DropdownMenu placement='right' interaction='hover' timeout={[0, 300]}>
              <DropdownMenu.Trigger tag={DropdownMenu.Nesting.Trigger}>
                Item 4
                <DropdownMenu.Nesting.Addon tag={ChevronRightIcon} color='icon-secondary-neutral' />
              </DropdownMenu.Trigger>
              <DropdownMenu.Menu w={120}>
                <DropdownMenu.Nesting>
                  <DropdownMenu placement='right' interaction='hover' timeout={[0, 300]}>
                    <DropdownMenu.Trigger tag={DropdownMenu.Nesting.Trigger}>
                      Item 4.1
                      <DropdownMenu.Nesting.Addon
                        tag={ChevronRightIcon}
                        color='icon-secondary-neutral'
                      />
                    </DropdownMenu.Trigger>
                    <DropdownMenu.Menu w={120}>
                      <DropdownMenu.Item>Item 4.1.1</DropdownMenu.Item>
                      <DropdownMenu.Item>Item 4.1.2</DropdownMenu.Item>
                      <DropdownMenu.Item>Item 4.1.3</DropdownMenu.Item>
                    </DropdownMenu.Menu>
                  </DropdownMenu>
                </DropdownMenu.Nesting>
                <DropdownMenu.Nesting>
                  <DropdownMenu placement='right' interaction='hover' timeout={[0, 300]}>
                    <DropdownMenu.Trigger tag={DropdownMenu.Nesting.Trigger}>
                      Item 4.2
                      <DropdownMenu.Nesting.Addon
                        tag={ChevronRightIcon}
                        color='icon-secondary-neutral'
                      />
                    </DropdownMenu.Trigger>
                    <DropdownMenu.Menu w={120}>
                      <DropdownMenu.Nesting>
                        <DropdownMenu placement='right' interaction='hover' timeout={[0, 300]}>
                          <DropdownMenu.Trigger tag={DropdownMenu.Nesting.Trigger}>
                            Item 4.2.1
                            <DropdownMenu.Nesting.Addon
                              tag={ChevronRightIcon}
                              color='icon-secondary-neutral'
                            />
                          </DropdownMenu.Trigger>
                          <DropdownMenu.Menu w={120}>
                            <DropdownMenu.Item>Item 4.2.1.1</DropdownMenu.Item>
                            <DropdownMenu.Item>Item 4.2.1.2</DropdownMenu.Item>
                            <DropdownMenu.Item>Item 4.2.1.3</DropdownMenu.Item>
                          </DropdownMenu.Menu>
                        </DropdownMenu>
                      </DropdownMenu.Nesting>
                      <DropdownMenu.Item>Item 4.2.2</DropdownMenu.Item>
                      <DropdownMenu.Item>Item 4.2.3</DropdownMenu.Item>
                    </DropdownMenu.Menu>
                  </DropdownMenu>
                </DropdownMenu.Nesting>
                <DropdownMenu.Item>Item 4.3</DropdownMenu.Item>
              </DropdownMenu.Menu>
            </DropdownMenu>
          </DropdownMenu.Nesting>
          <DropdownMenu.Item>Item 5</DropdownMenu.Item>
        </DropdownMenu.Menu>
      </DropdownMenu>
    </Flex>
  );
};

export default Demo;

Nested dropdowns with focusable elements

If you want to put focusable elements in dropdown items that also contain nesting, you need to use more complex structure with DropdownMenu.Nesting.Item.

tsx
import React from 'react';
import DropdownMenu from '@semcore/ui/dropdown-menu';
import { ButtonTrigger } from '@semcore/ui/base-trigger';
import ChevronRightIcon from '@semcore/ui/icon/ChevronRight/m';
import InputNumber from '@semcore/ui/input-number';
import NeighborLocation from '@semcore/ui/neighbor-location';
import Divider from '@semcore/ui/divider';
import { Flex, Box } from '@semcore/ui/flex-box';
import Button from '@semcore/ui/button';
import Tooltip from '@semcore/ui/tooltip';
import InfoM from '@semcore/ui/icon/Info/m';

const options = ['Item 1', 'Item 2', 'Item 3'];
const min = 1;
const max = 8;

const Demo = () => {
  return (
    <DropdownMenu>
      <DropdownMenu.Trigger tag={ButtonTrigger}>Click me</DropdownMenu.Trigger>
      <DropdownMenu.Menu>
        {options.map((item) => {
          return (
            <DropdownMenu.Nesting key={item}>
              <DropdownMenu placement='right' interaction='hover' timeout={[0, 300]}>
                <DropdownMenu.Nesting.Item>
                  <Box mr={1}>{item}</Box>
                  <Tooltip
                    mr={5}
                    tag={InfoM}
                    color='icon-secondary-neutral'
                    interactive
                    title='Test tooltip text'
                  />
                  <DropdownMenu.Trigger tag={DropdownMenu.Nesting.Trigger}>
                    <DropdownMenu.Nesting.Addon
                      tag={ChevronRightIcon}
                      color='icon-secondary-neutral'
                    />
                  </DropdownMenu.Trigger>
                </DropdownMenu.Nesting.Item>
                <DropdownMenu.Popper w={150}>
                  <DropdownMenu.List>
                    <DropdownMenu.Item>Item 4.1.1</DropdownMenu.Item>
                    <DropdownMenu.Item>Item 4.1.2</DropdownMenu.Item>
                    <DropdownMenu.Item>Item 4.1.3</DropdownMenu.Item>
                  </DropdownMenu.List>
                  <Divider my={1} />
                  <Box p={2}>
                    <NeighborLocation>
                      <InputNumber w='50%'>
                        <InputNumber.Value min={min} max={max} placeholder={min.toString()} />
                        <InputNumber.Controls />
                      </InputNumber>
                      <InputNumber w='50%'>
                        <InputNumber.Value min={min} max={max} placeholder={max.toString()} />
                        <InputNumber.Controls />
                      </InputNumber>
                    </NeighborLocation>
                    <Button w='100%' mt={1} use='primary'>
                      Apply
                    </Button>
                  </Box>
                </DropdownMenu.Popper>
              </DropdownMenu>
            </DropdownMenu.Nesting>
          );
        })}
      </DropdownMenu.Menu>
    </DropdownMenu>
  );
};

export default Demo;

export const App = () => <Demo />;
import React from 'react';
import DropdownMenu from '@semcore/ui/dropdown-menu';
import { ButtonTrigger } from '@semcore/ui/base-trigger';
import ChevronRightIcon from '@semcore/ui/icon/ChevronRight/m';
import InputNumber from '@semcore/ui/input-number';
import NeighborLocation from '@semcore/ui/neighbor-location';
import Divider from '@semcore/ui/divider';
import { Flex, Box } from '@semcore/ui/flex-box';
import Button from '@semcore/ui/button';
import Tooltip from '@semcore/ui/tooltip';
import InfoM from '@semcore/ui/icon/Info/m';

const options = ['Item 1', 'Item 2', 'Item 3'];
const min = 1;
const max = 8;

const Demo = () => {
  return (
    <DropdownMenu>
      <DropdownMenu.Trigger tag={ButtonTrigger}>Click me</DropdownMenu.Trigger>
      <DropdownMenu.Menu>
        {options.map((item) => {
          return (
            <DropdownMenu.Nesting key={item}>
              <DropdownMenu placement='right' interaction='hover' timeout={[0, 300]}>
                <DropdownMenu.Nesting.Item>
                  <Box mr={1}>{item}</Box>
                  <Tooltip
                    mr={5}
                    tag={InfoM}
                    color='icon-secondary-neutral'
                    interactive
                    title='Test tooltip text'
                  />
                  <DropdownMenu.Trigger tag={DropdownMenu.Nesting.Trigger}>
                    <DropdownMenu.Nesting.Addon
                      tag={ChevronRightIcon}
                      color='icon-secondary-neutral'
                    />
                  </DropdownMenu.Trigger>
                </DropdownMenu.Nesting.Item>
                <DropdownMenu.Popper w={150}>
                  <DropdownMenu.List>
                    <DropdownMenu.Item>Item 4.1.1</DropdownMenu.Item>
                    <DropdownMenu.Item>Item 4.1.2</DropdownMenu.Item>
                    <DropdownMenu.Item>Item 4.1.3</DropdownMenu.Item>
                  </DropdownMenu.List>
                  <Divider my={1} />
                  <Box p={2}>
                    <NeighborLocation>
                      <InputNumber w='50%'>
                        <InputNumber.Value min={min} max={max} placeholder={min.toString()} />
                        <InputNumber.Controls />
                      </InputNumber>
                      <InputNumber w='50%'>
                        <InputNumber.Value min={min} max={max} placeholder={max.toString()} />
                        <InputNumber.Controls />
                      </InputNumber>
                    </NeighborLocation>
                    <Button w='100%' mt={1} use='primary'>
                      Apply
                    </Button>
                  </Box>
                </DropdownMenu.Popper>
              </DropdownMenu>
            </DropdownMenu.Nesting>
          );
        })}
      </DropdownMenu.Menu>
    </DropdownMenu>
  );
};

export default Demo;

export const App = () => <Demo />;

Released under the MIT License.

Released under the MIT License.