@clayui/drop-down

ClayDropDown component

Usage no npm install needed!

<script type="module">
  import clayuiDropDown from 'https://cdn.skypack.dev/@clayui/drop-down';
</script>

README


title: 'Drop Down' description: 'A dropdown menu displays a list of options for the element that triggers it.' lexiconDefinition: 'https://liferay.design/lexicon/core-components/dropdowns/' packageNpm: '@clayui/drop-down'

import { DropDown, DropDownWithItems, DropDownWithDrilldown, } from '$packages/clay-drop-down/docs/index';

Composing

DropDown's composition gives you the space to create more complex DropDowns, such as adding a form within DropDown, and creating simple DropDowns with the high-level ClayDropDownWithItems component that covers most basic Lexicon use cases.

You may want to use only the content of DropDown for other cases, such as mounting an Autocomplete, so use DropDown.Menu instead of DropDown which gives you the flexibility to only control content without a trigger.

DropDown consists of a{' '} DropDown.Menu that controls the trigger and uses it as the basis for aligning DropDown content.

Using dropdown without a trigger

You may want to create a trigger that is not necessarily in the same tree as DropDown, due to HTML markup issues, for these cases you can use <ClayDropDown.Menu />.

Using <ClayDropDown.Menu /> allows you to better control the state of DropDown but you will have to deal with visibility, focus management, and other details.

import ClayDropDown from '@clayui/drop-down';
import React, {useState, useRef} from 'react';

const Menu = ({children, hasLeftSymbols, hasRightSymbols}) => {
    const triggerElementRef = useRef(null);
    const [expand, setExpand] = useState(false);
    const menuElementRef = useRef(null);

    const handleExpand = (event) => {
        // This is not ideal for allowing you to have more than
        // one trigger for the same content but it simulates the
        // advantages of controlling `DropDown.Menu`.
        triggerElementRef.current = event.target;

        setExpand(!expand);
    };

    return (
        <div>
            <div>
                <button type="button" onClick={handleExpand}>
                    Home
                </button>
            </div>
            <div>
                <button type="button" onClick={handleExpand}>
                    Product
                </button>
            </div>

            <ClayDropDown.Menu
                active={expand}
                alignElementRef={triggerElementRef}
                hasLeftSymbols={hasLeftSymbols}
                hasRightSymbols={hasRightSymbols}
                onSetActive={() => setExpand(!expand)}
                ref={menuElementRef}
            >
                {children}
            </ClayDropDown.Menu>
        </div>
    );
};

DropDownWithItems

Allows you to create a simple DropDown, through its API you are able to create a Menu with groups of checkboxes and radios, links, buttons, search, caption, etc.

Cascading Menu

DropDownWithItems allows the possibility to create a contextual menu, the nature of the API allows the creation of more cascade menus but the Lexicon specification recommends using only one level and using DropDownWithDrilldown component.

To render a cascading menu it is necessary to set the type of the item to contextual and add to the items object that follows the same API as the other items.

const items = [
    {label: 'Folder'},
    {type: 'divider'},
    {
        items: [
            {label: 'Basic Document'},
            {label: 'Contract'},
            {label: 'Marketing Banner'},
            {label: 'Spreadsheet'},
            {label: 'Presentation'},
        ],
        label: 'Document',
        type: 'contextual',
    },
    {label: 'Shortcut'},
    {label: 'Repository'},
];

DropDownWithDrilldown

A Drilldown menu allows the user to navigate to and/or select an element from a contextual list. It can be triggered by a dropdown button.

The way the Drilldown component links the menus is done via reference, the menu needs a unique id.

const menus = {
    of23: [{title: 'First'}],
};

From the id you are able to link to another menu using the child property.

const menus = {
    of23: [{title: 'First', child: 'of09'}],
    of09: [{title: 'Three'}],
};

If you want to add separators between your menu items, it's possible to do so, by using an item that has this shape {type: 'divider'}.

const menus = {
    of23: [
        {title: 'First', child: 'of09'},
        {type: 'divider'},
        {title: 'Second'},
    ],
    of09: [{title: 'Three'}],
};
An important thing to have in mind, is that the `DropDownWithDrilldown` component, will render its menus in the order that they are specified. This means that if you specify the menus in the wrong order, the menu animation will not behave correctly.

Caveats

One caveat with the drop down menu is that it is rendered inside of a React Portal and is rendered directly to the body element. This means if you are using the menuWidth prop set to auto, it will not respect the size of the node parent of the drop down, since the menu is rendered directly to the body.