# DropdownButton

A Dropdown with a labelled, button-like trigger instead of an input field.

## Default

Source: CoreAI.

With no `value`/`selectedOptions`, `DropdownButton` renders just its
`label` (e.g. `Sort by`) instead of a `label: value` pair — it reads like a
menu trigger until an option is picked. Pass `clearable` if users should be
able to return to this unselected state after choosing a value.

[Download source](/coreai-design-system/source/examples/components-button-dropdownbutton--default.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { DropdownButton } from "@coreai-ds/react-components";
import { Option } from "@coreai-ds/react-components";

// `DropdownButton` renders a `Dropdown` with a button-style trigger and a
// required inline `label`.
const sortOptions = ['Newest', 'Oldest', 'Most popular', 'Trending'];

/**
 * With no `value`/`selectedOptions`, `DropdownButton` renders just its
 * `label` (e.g. `Sort by`) instead of a `label: value` pair — it reads like a
 * menu trigger until an option is picked. Pass `clearable` if users should be
 * able to return to this unselected state after choosing a value.
 */
export const Default = (): JSXElement => (<DropdownButton label="Sort by" clearable onOptionSelect={() => undefined}>
    {sortOptions.map((option) => (<Option key={option}>{option}</Option>))}
  </DropdownButton>);

export default Default;
```

## API

Generated CoreAI prop summaries, not replacement type declarations. Most native DOM/event and ARIA props are omitted. `?` means optional; JSDoc shows defaults, deprecations, and conditional requirements. Defaults assume the standard CoreAI provider.

### DropdownButton API

A `Dropdown` rendered as a button with a required inline `label`.

```ts
interface DropdownButtonProps {
  /**
   * A button can have its content and borders styled for greater emphasis or to be subtle.
   * - 'secondary' (default): Gives emphasis to the button in such a way that it indicates a secondary action.
   * - 'primary': Emphasizes the button as a primary action.
   * - 'outline': Removes background styling.
   * - 'subtle': Minimizes emphasis to blend into the background until hovered or focused.
   * - 'transparent': Removes background and border styling.
   * @default 'secondary'
   */
  appearance?: "outline" | "subtle" | "secondary" | "primary" | "transparent";

  as?: "button";

  children?: any;

  className?: string;

  /**
   * If set, the combobox will show an icon to clear the current value.
   */
  clearable?: boolean;

  /**
   * The dropdown clear icon
   */
  clearButton?: WithSlotShorthandValue<{ as?: "button"; } & Omit<Omit<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & { ref?: ((instance: HTMLButtonElement | null) => void) | RefObject<HTMLButtonElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  /**
   * The default open state when open is uncontrolled
   */
  defaultOpen?: boolean;

  /**
   * For an uncontrolled component, sets the initial selection.
   * If this is set, the `defaultValue` prop MUST also be set.
   */
  defaultSelectedOptions?: string[];

  /**
   * The default value displayed in the trigger input or button when the combobox's value is uncontrolled
   */
  defaultValue?: string | (readonly string[] & string);

  /**
   * Disable auto-focusing on the first item when mounting.
   * @default false
   */
  disableAutoFocus?: boolean;

  /**
   * A button can show that it cannot be interacted with.
   * @default false
   */
  disabled?: boolean;

  /**
   * The dropdown arrow icon
   */
  expandIcon?: WithSlotShorthandValue<{ as?: "span"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & { ref?: ((instance: HTMLSpanElement | null) => void) | RefObject<HTMLSpanElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  /**
   * Render the combobox's popup inline in the DOM.
   * This has accessibility benefits, particularly for touch screen readers.
   */
  inlinePopup?: boolean;

  /**
   * Optional inline label rendered inside the control, before the value.
   */
  label?: string;

  /**
   * The dropdown listbox slot
   */
  listbox?: WithSlotShorthandValue<Omit<ListboxSlots, "root"> & Omit<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }, "ref"> & SelectionProps & { disableAutoFocus?: boolean | undefined; } & RefAttributes<HTMLDivElement>> | null | undefined;

  /**
   * Where the portal children are mounted on DOM
   * @default a new element on document.body without any styling
   */
  mountNode?: HTMLElement | { element?: HTMLElement | null; className?: string; } | null | undefined;

  /**
   * Sets the selection type to multiselect.
   * Set this to true for multiselect, even if fully controlling selection state.
   * This enables styles and accessibility properties to be set.
   * @default false
   */
  multiselect?: boolean;

  onActiveOptionChange?: EventHandler<ActiveOptionChangeData>;

  /**
   * Callback when the open/closed state of the dropdown changes
   */
  onOpenChange?: ((e: ComboboxBaseOpenEvents, data: ComboboxBaseOpenChangeData) => void);

  /**
   * Callback when an option is selected
   */
  onOptionSelect?: ((event: SelectionEvents, data: OptionOnSelectData) => void);

  /**
   * Sets the open/closed state of the dropdown.
   * Use together with onOpenChange to fully control the dropdown's visibility
   */
  open?: boolean;

  /**
   * If set, the placeholder will show when no value is selected
   */
  placeholder?: string;

  /**
   * Configure the positioning of the combobox dropdown.
   * Please refer to the [positioning documentation](https://react.fluentui.dev/?path=/docs/concepts-developer-positioning-components--default#anchor-to-target)
   * for more details.
   */
  positioning?: PositioningShorthand;

  ref?: Ref<HTMLButtonElement>;

  /**
   * The root dropdown slot
   */
  root?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;

  /**
   * An array of selected option keys.
   * Use this with `onOptionSelect` to directly control the selected option(s)
   * If this is set, the `value` prop MUST also be controlled.
   */
  selectedOptions?: string[];

  /**
   * A button can be rounded, circular, or square.
   * @default 'rounded'
   */
  shape?: "circular" | "rounded" | "square";

  /**
   * Controls the size of the combobox faceplate
   * A button supports different sizes.
   * @default 'medium'
   * 'medium'
   */
  size?: "small" | "medium" | "large";

  style?: CSSProperties;

  /**
   * The value displayed by the Combobox.
   * Use this with `onOptionSelect` to directly control the displayed value string
   */
  value?: string | (readonly string[] & string);
}
```

## Implementation

CoreAI 0.12.0; Fluent 9.74.9.

[Setup and dependencies](/coreai-design-system/guides/Package.md).

Import components from `@coreai-ds/react-components`. CoreAI guidance above takes precedence over API demonstration examples.

## Appearance

Source: CoreAI.

[Download source](/coreai-design-system/source/examples/components-button-dropdownbutton--appearance.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import * as React from 'react';
import { DropdownButton } from "@coreai-ds/react-components";
import { Option } from "@coreai-ds/react-components";

const appearances = ['secondary', 'primary', 'outline', 'subtle', 'transparent'] as const;

const sortOptions = ['Newest', 'Oldest', 'Most popular', 'Trending'];

export const Appearance = () => {
    const [sort, setSort] = React.useState('Newest');
    const styles = /* css */ `
    .dropdown-button-appearance-example {
      display: flex;
      flex-direction: column;
      column-gap: var(--spacingHorizontalXXL);
      row-gap: var(--spacingVerticalL);
      align-items: flex-start;
      padding: var(--spacingVerticalL);
    }

    .dropdown-button-appearance-example__column {
      display: flex;
      flex-direction: column;
      row-gap: var(--spacingVerticalS);
      align-items: flex-start;
    }

    .dropdown-button-appearance-example__heading {
      margin: 0;
      font-size: var(--fontSizeBase200);
      color: var(--colorNeutralForeground3);
    }
  `;
    return (<>
      <style>{styles}</style>
      <div className="dropdown-button-appearance-example">
        {appearances.map((appearance) => (<div key={appearance} className="dropdown-button-appearance-example__column">
            <p className="dropdown-button-appearance-example__heading">{appearance}</p>
            <DropdownButton appearance={appearance} label="Sort by" value={sort} selectedOptions={[sort]} onOptionSelect={(_event, data) => setSort(data.optionValue ?? sort)}>
              {sortOptions.map((option) => (<Option key={option}>{option}</Option>))}
            </DropdownButton>
          </div>))}
      </div>
    </>);
};

export default Appearance;
```

## Disabled

Source: CoreAI.

[Download source](/coreai-design-system/source/examples/components-button-dropdownbutton--disabled.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { DropdownButton } from "@coreai-ds/react-components";
import { Option } from "@coreai-ds/react-components";
import * as React from 'react';

const appearances = ['secondary', 'primary', 'outline', 'subtle', 'transparent'] as const;

const sortOptions = ['Newest', 'Oldest', 'Most popular', 'Trending'];

export const Disabled = () => {
    const styles = /* css */ `
    .dropdown-button-disabled-example {
      display: flex;
      flex-direction: column;
      column-gap: var(--spacingHorizontalXXL);
      row-gap: var(--spacingVerticalL);
      align-items: flex-start;
      padding: var(--spacingVerticalL);
    }

    .dropdown-button-disabled-example__column {
      display: flex;
      flex-direction: column;
      row-gap: var(--spacingVerticalS);
      align-items: flex-start;
    }

    .dropdown-button-disabled-example__heading {
      margin: 0;
      font-size: var(--fontSizeBase200);
      color: var(--colorNeutralForeground3);
    }
  `;
    return (<>
      <style>{styles}</style>
      <div className="dropdown-button-disabled-example">
        {appearances.map((appearance) => (<div key={appearance} className="dropdown-button-disabled-example__column">
            <p className="dropdown-button-disabled-example__heading">{appearance}</p>
            <DropdownButton appearance={appearance} label="Sort by" disabled value="Newest" selectedOptions={['Newest']} onOptionSelect={() => undefined}>
              {sortOptions.map((option) => (<Option key={option}>{option}</Option>))}
            </DropdownButton>
          </div>))}
      </div>
    </>);
};

export default Disabled;
```

## Shape

Source: CoreAI.

[Download source](/coreai-design-system/source/examples/components-button-dropdownbutton--shape.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import * as React from 'react';
import { DropdownButton } from "@coreai-ds/react-components";
import { Option } from "@coreai-ds/react-components";

const shapes = ['rounded', 'circular', 'square'] as const;

const sortOptions = ['Newest', 'Oldest', 'Most popular', 'Trending'];

export const Shape = () => {
    const [sort, setSort] = React.useState('Newest');
    const styles = /* css */ `
    .dropdown-button-shape-example {
      display: flex;
      flex-direction: column;
      column-gap: var(--spacingHorizontalXXL);
      row-gap: var(--spacingVerticalL);
      align-items: flex-start;
      padding: var(--spacingVerticalL);
    }

    .dropdown-button-shape-example__column {
      display: flex;
      flex-direction: column;
      row-gap: var(--spacingVerticalS);
      align-items: flex-start;
    }

    .dropdown-button-shape-example__heading {
      margin: 0;
      font-size: var(--fontSizeBase200);
      color: var(--colorNeutralForeground3);
    }
  `;
    return (<>
      <style>{styles}</style>
      <div className="dropdown-button-shape-example">
        {shapes.map((shape) => (<div key={shape} className="dropdown-button-shape-example__column">
            <p className="dropdown-button-shape-example__heading">{shape}</p>
            <DropdownButton shape={shape} label="Sort by" value={sort} selectedOptions={[sort]} onOptionSelect={(_event, data) => setSort(data.optionValue ?? sort)}>
              {sortOptions.map((option) => (<Option key={option}>{option}</Option>))}
            </DropdownButton>
          </div>))}
      </div>
    </>);
};

export default Shape;
```

## Size

Source: CoreAI.

[Download source](/coreai-design-system/source/examples/components-button-dropdownbutton--size.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import * as React from 'react';
import { DropdownButton } from "@coreai-ds/react-components";
import { Option } from "@coreai-ds/react-components";

const sizes = ['small', 'medium', 'large'] as const;

const sortOptions = ['Newest', 'Oldest', 'Most popular', 'Trending'];

export const Size = () => {
    const [sort, setSort] = React.useState('Newest');
    const styles = /* css */ `
    .dropdown-button-size-example {
      display: flex;
      flex-direction: column;
      column-gap: var(--spacingHorizontalXXL);
      row-gap: var(--spacingVerticalL);
      align-items: flex-start;
      padding: var(--spacingVerticalL);
    }

    .dropdown-button-size-example__column {
      display: flex;
      flex-direction: column;
      row-gap: var(--spacingVerticalS);
      align-items: flex-start;
    }

    .dropdown-button-size-example__heading {
      margin: 0;
      font-size: var(--fontSizeBase200);
      color: var(--colorNeutralForeground3);
    }
  `;
    return (<>
      <style>{styles}</style>
      <div className="dropdown-button-size-example">
        {sizes.map((size) => (<div key={size} className="dropdown-button-size-example__column">
            <p className="dropdown-button-size-example__heading">{size}</p>
            <DropdownButton size={size} label="Sort by" value={sort} selectedOptions={[sort]} onOptionSelect={(_event, data) => setSort(data.optionValue ?? sort)}>
              {sortOptions.map((option) => (<Option key={option}>{option}</Option>))}
            </DropdownButton>
          </div>))}
      </div>
    </>);
};

export default Size;
```

## Variants

Source: CoreAI.

[Download source](/coreai-design-system/source/examples/components-button-dropdownbutton--variants.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import * as React from 'react';
import { DropdownButton } from "@coreai-ds/react-components";
import { Option } from "@coreai-ds/react-components";

const sortOptions = ['Newest', 'Oldest', 'Most popular', 'Trending'];

const filterOptions = ['All', 'Active', 'Archived'];

export const Variants = () => {
    const [sort, setSort] = React.useState('Newest');
    const [filter, setFilter] = React.useState('All');
    const styles = /* css */ `
    .dropdown-button-variants-example {
      display: flex;
      flex-direction: column;
      column-gap: var(--spacingHorizontalXXL);
      row-gap: var(--spacingVerticalL);
      align-items: flex-start;
      padding: var(--spacingVerticalL);
    }

    .dropdown-button-variants-example__column {
      display: flex;
      flex-direction: column;
      row-gap: var(--spacingVerticalS);
      align-items: flex-start;
    }

    .dropdown-button-variants-example__heading {
      margin: 0;
      font-size: var(--fontSizeBase200);
      color: var(--colorNeutralForeground3);
    }
  `;
    return (<>
      <style>{styles}</style>
      <div className="dropdown-button-variants-example">
        <div className="dropdown-button-variants-example__column">
          <p className="dropdown-button-variants-example__heading">default</p>
          <DropdownButton label="Sort by" value={sort} selectedOptions={[sort]} onOptionSelect={(_event, data) => setSort(data.optionValue ?? sort)}>
            {sortOptions.map((option) => (<Option key={option}>{option}</Option>))}
          </DropdownButton>
        </div>

        <div className="dropdown-button-variants-example__column">
          <p className="dropdown-button-variants-example__heading">subtle</p>
          <DropdownButton appearance="subtle" label="Filter" value={filter} selectedOptions={[filter]} onOptionSelect={(_event, data) => setFilter(data.optionValue ?? filter)}>
            {filterOptions.map((option) => (<Option key={option}>{option}</Option>))}
          </DropdownButton>
        </div>

        <div className="dropdown-button-variants-example__column">
          <p className="dropdown-button-variants-example__heading">
            label only (no value/placeholder)
          </p>
          <DropdownButton label="Sort by" clearable onOptionSelect={() => undefined}>
            {sortOptions.map((option) => (<Option key={option}>{option}</Option>))}
          </DropdownButton>
        </div>

        <div className="dropdown-button-variants-example__column">
          <p className="dropdown-button-variants-example__heading">disabled</p>
          <DropdownButton label="Sort by" disabled onOptionSelect={() => undefined}>
            {sortOptions.map((option) => (<Option key={option}>{option}</Option>))}
          </DropdownButton>
        </div>
      </div>
    </>);
};

export default Variants;
```