# Dropdown

> ComboBox — a button with an arrow that opens a list for single selection.

Source: https://crossfly.dev/docs/ui/widgets/dropdown — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Dropdown

`Dropdown` is a **ComboBox**-style component: a button with text + arrow (`expand_more`) that, when tapped, opens a `ListViewWindow` with the list of items, positioned above or below depending on available space. After selection, the button text shows the chosen item. While nothing is selected, it displays the **placeholder**.

> 🟡 · **Package:** `dev.crossfly.ui` · **Extends:** `Button` · **Style:** `DropdownStyle`

## When to use
- **Single** choice from a medium-sized list of options, saving screen space.
- When the selected value should remain visible after the choice.

## When NOT to use
- For 2–3 options that are always visible → use [`option`](/docs/ui/widgets/option) in a [`group`](/docs/ui/widgets/group).

## Appearance
Text on the left; the arrow is positioned according to `DropdownStyle.iconPosition`: `START` (flush against the left edge), `CENTER` (next to the text, `Button`'s default `TEXT_AT_LEFT` layout) or `END` (flush against the right edge). The popup opens as a white window with rounded corners that closes when tapping outside (`canMove(false).canHide(true)`).

## Complete example (copy, paste and run)
```java
package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;

/** Runnable main screen. Point the launcher (classname) and run: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      Label saida = new Label("Nada selecionado");
      add(LAY_AUTO, saida);

      String[] itens = {"One", "Two", "Three", "Four", "Five"};
      Dropdown cb = new Dropdown("Selecione...", itens);
      // onSelect fires after confirming the choice in the popup
      cb.onSelect(e -> saida.setText("Escolhido: " + cb.getSelectedText()
                                     + " (idx " + cb.getSelectedIndex() + ")"));
      add(LAY_AUTO, cb);
   }
}
```

> The snippets below show **only the core** (what goes inside `onShow()`). To run them, place them in the `MainWindow` skeleton above.

## Basic usage
```java
String[] itens = {"One", "Two", "Three", "Four", "Five"};
Dropdown cb = new Dropdown("Selecione...", itens);
cb.onSelect(e -> {
   String escolhido = cb.getSelectedText();
   System.out.println("escolhido: " + escolhido);
});
container.add(.95f, cb);
```

## Constructors
| Constructor | Description |
|---|---|
| `Dropdown(String placeholder, String[] items)` | Placeholder + items. |
| `Dropdown(String[] items)` | Items with default placeholder `"Select..."`. |

## Properties and customization
| Property / method | Type | Default | What it does |
|---|---|---|---|
| `onSelect(Action)` | `Dropdown` (fluent) | — | Callback when a selection is confirmed. |
| `popupHeightRatio(float)` | `Dropdown` (fluent) | `0.4` | Popup height (0..1 of the screen), used when the ideal height is not measured. |
| `popupWidthRatio(float)` | `Dropdown` (fluent) | `-1` | Popup width (0..1 of the screen); negative = width of the Dropdown itself. |
| `getSelectedIndex()` | `int` | `-1` | Index of the current item (or `-1`). |
| `getSelectedText()` | `String` | `null` | Text of the current item (or `null`). |
| `setSelectedIndex(int)` | `Dropdown` (fluent) | — | Selects programmatically; invalid index (e.g. `-1`) → returns to the placeholder. |

## Callbacks and events
| Callback | When it fires |
|---|---|
| `onSelect(Action)` | **After** confirming a selection in the popup. Use `getSelectedText()`/`getSelectedIndex()` inside it. |

`onTouchUp` is inherited from `Button` and schedules `openPopup()` via `onUI(...)`.

## States
- **placeholder**: no item selected (`selectedIndex == -1`); displays the placeholder text.
- **selected**: `selectedIndex >= 0`; displays the item text.
- **pressed**: inherited from `Button` (press fade).

### Programmatic selection and clearing back to the placeholder
```java
String[] numeros = {"One", "Two", "Three"};
Dropdown cb = new Dropdown("", numeros);
cb.onSelect(e -> System.out.println("idx: " + cb.getSelectedIndex()));
container.add(.95f, cb);

cb.setSelectedIndex(1);   // selects "Two" programmatically
cb.setSelectedIndex(-1);  // clears: back to the placeholder
```

## Best practices
- Read the choice via `getSelectedText()`/`getSelectedIndex()` inside `onSelect`.
- Use `setSelectedIndex(-1)` to "reset" the field to the placeholder (e.g. on a "Clear" button).

## Common mistakes
- Passing a null `items`: the constructor handles it (`new String[0]`), but the popup **does not open** if the list is empty.
- Expecting multi-selection: `Dropdown` is single choice; for multiple, use `ListView` `MULTIPLE`.

## See also
- Area guide: [`ui/`](/docs/ui) · Recipes: [`cookbook/`](/docs/cookbook)
- Concept (windows and popups): [`concepts/`](/docs/concepts)
- Related components: [`option`](/docs/ui/widgets/option) · [`group`](/docs/ui/widgets/group)
