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'}],
};
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.