# Dropdown

```ts
import { Dropdown } from 'cx/widgets';
```



The `Dropdown` widget is commonly used in lookup fields, date fields, and menus, but it can also be used independently. It positions itself relative to a trigger element and automatically adjusts placement based on available screen space.

```tsx
import { createModel } from "cx/data";
import { Button, Dropdown, Menu, MenuItem } from "cx/widgets";

interface PageModel {
  showDropdown: boolean;
}

const m = createModel<PageModel>();

export default (
  <div>
    <Button
      onClick={(e, { store }) => {
        store.toggle(m.showDropdown);
      }}
    >
      Toggle Dropdown
    </Button>
    <Dropdown visible={m.showDropdown} arrow offset={4} placementOrder="down-right up-right" class="p-2">
      <Menu>
        <MenuItem>Option 1</MenuItem>
        <MenuItem>Option 2</MenuItem>
        <MenuItem>Option 3</MenuItem>
      </Menu>
    </Dropdown>
  </div>
);

```

By default, the dropdown positions itself relative to its previous sibling element. Use `arrow` to show a pointer and `offset` to control the distance from the trigger.

## Custom Related Element

Use `onResolveRelatedElement` to position the dropdown relative to a different element than the default previous sibling.

```tsx
import { createModel } from "cx/data";
import { Button, Dropdown } from "cx/widgets";

interface PageModel {
  showDropdown: boolean;
}

const m = createModel<PageModel>();

export default (
  <div className="p-5 border-2 border-dashed border-gray-300 rounded relative">
    <span className="absolute top-1 right-2 text-xs text-gray-400">
      Parent Container
    </span>
    <Button
      onClick={(e, { store }) => {
        store.toggle(m.showDropdown);
      }}
    >
      Toggle Parent Dropdown
    </Button>
    <Dropdown
      visible={m.showDropdown}
      arrow
      offset={10}
      placement="down"
      onResolveRelatedElement={(el) => el.parentElement!}
      style="padding: 20px; max-width: 300px"
    >
      Dropdown positioned relative to the parent container.
    </Dropdown>
  </div>
);

```

## Search Suggestions

Combine `Dropdown` with `TextField` using `trackFocus` and `focused` bindings to create search suggestion interfaces. Set `matchWidth` to make the dropdown match the input width.

```tsx
import { createModel } from "cx/data";
import { TextField, Dropdown } from "cx/widgets";

interface PageModel {
  query: string;
  showSuggestions: boolean;
}

const m = createModel<PageModel>();

export default (
  <div>
    <TextField
      value={m.query}
      focused={m.showSuggestions}
      trackFocus
      icon="search"
      placeholder="Search..."
      inputAttrs={{ autoComplete: "off" }}
    />
    <Dropdown
      visible={m.showSuggestions}
      offset={1}
      placementOrder="down-right up-right"
      style="padding: 20px;"
      matchWidth
    >
      Display search results here.
    </Dropdown>
  </div>
);

```

## Positioning

Positioning is controlled by `relatedElement` and `placement` properties. The default `relatedElement` is the element rendered prior to the dropdown. Use `onResolveRelatedElement` callback to specify a different anchor element. Placement direction is determined by available screen space and controlled by `placement` and `placementOrder` props.

## Configuration

| Property | Type | Description |
| -------- | ---- | ----------- |
| `visible` | `BooleanProp` | Controls dropdown visibility. |
| `placement` | `string` | Defines where the dropdown will be placed: `up`, `down`, `left`, `right`, or corners like `down-right`. |
| `placementOrder` | `string` | Available placement options. The dropdown picks placement to maximize visibility. Default: `"up down right left"`. |
| `offset` | `number` | Distance from the trigger element. Default: `0`. |
| `arrow` | `boolean` | Shows an arrow pointing to the trigger element. |
| `matchWidth` | `boolean` | Match the dropdown width to the trigger element. |
| `matchMaxWidth` | `boolean` | Match the dropdown max-width to the trigger element. |
| `constrain` | `boolean` | Constrain the dropdown within the viewport. |
| `closeOnScrollDistance` | `number` | Auto-close if page scrolls this distance. Default: `50`. |
| `relatedElement` | `Element` | DOM element used as anchor for positioning. |
| `onResolveRelatedElement` | `function` | Callback to resolve the related element: `(beaconEl) => Element`. |
| `autoFocus` | `boolean` | Focus first focusable element when opened. |
| `focusable` | `boolean` | Make the dropdown focusable. |
| `dismissOnFocusOut` | `boolean` | Close when focus leaves the dropdown. |