Dropdown & ComboBox
Dropdown selection with ComboBox and ListBoxItem
Namespace: Beep.Skia.Controls — Inherits: ComboBox → MaterialControl → SkiaComponent
Table of Contents
Overview
The ComboBox control combines an MD3-styled text field with a popup Dropdown list of selectable items, all rendered with SkiaSharp. When the user clicks the field or presses the dropdown arrow, the Dropdown overlay opens below (or above, if insufficient space) displaying the available items. The selected item is shown in the field with its text and optional icon. The dropdown closes on selection, outside click, or Escape key.
The Dropdown is an overlay component managed by OverlayManager. It renders with MD3 elevation shadow and a surface background. Items are rendered with hover and selection state layers. An animated chevron icon on the field indicates the open/closed state.
ComboBox Properties
| Property | Type | Description |
|---|---|---|
Items |
List<ComboBoxItem> |
The collection of selectable items displayed in the dropdown. |
SelectedIndex |
int |
Zero-based index of the selected item. -1 when no item is selected. Setting this updates the displayed text in the field. |
SelectedItem |
ComboBoxItem |
Read-only. The currently selected ComboBoxItem instance, or null. |
IsOpen |
bool |
Read-only. Indicates whether the dropdown popup is currently visible. |
Placeholder |
string |
Text displayed in the field when no item is selected. Rendered in OnSurfaceVariant color. Default is "Select...". |
FieldStyle |
TextFieldStyle |
Enum: Filled (default) or Outlined. Controls the visual style of the combo box field. |
IsEditable |
bool |
When true, the user can type in the field to filter items. The dropdown shows only items whose text contains the typed substring (case-insensitive). Default is false. |
MaxDropdownHeight |
float |
Maximum height of the dropdown popup. If the total item height exceeds this, the dropdown becomes scrollable. Default is 300f. |
DropdownItemHeight |
float |
Height of each item row in the dropdown. Default is 48f per MD3 list item spec. |
Dropdown Properties
The Dropdown is the popup list rendered when the ComboBox opens. While typically managed automatically, it can also be used standalone or customized:
| Property | Type | Description |
|---|---|---|
IsOpen |
bool |
Controls visibility of the dropdown overlay. Setting to true registers with OverlayManager and begins the open animation. |
OpenAnimation |
AnimationType |
The animation played when the dropdown opens. Default is a vertical expand with fade (AnimationType.ExpandDown). Duration is typically 150–200ms. |
CloseAnimation |
AnimationType |
The animation played when the dropdown closes. Default is AnimationType.CollapseUp. |
Elevation |
int |
Material elevation shadow level. Default is 3. |
CornerRadius |
float |
Corner rounding for the dropdown surface. Default is 4f. |
DropDirection |
DropDirection |
Enum: Auto (default), Down, or Up. Auto opens below unless there is insufficient space, in which case it opens above. |
ComboBoxItem Model
| Property | Type | Description |
|---|---|---|
Text |
string |
The display text for this item. Rendered using BodyLarge typography. |
Value |
object |
Arbitrary value associated with the item. Typically a string, integer, or enum. Used for programmatic lookup when SelectedItem changes. |
Icon |
SKPath |
Optional vector icon displayed before the text in the dropdown list. Not shown in the collapsed field. |
IsEnabled |
bool |
When false, the item is greyed out and not selectable. Default is true. |
Tooltip |
string |
Optional tooltip text shown on hover when the dropdown is open. |
Code Example
Basic ComboBox
var fontCombo = new ComboBox
{
Placeholder = "Select a font...",
FieldStyle = TextFieldStyle.Outlined,
X = 40,
Y = 40,
Width = 280,
Height = 56,
Items = new List<ComboBoxItem>
{
new() { Text = "Inter", Value = "Inter" },
new() { Text = "Roboto", Value = "Roboto" },
new() { Text = "Source Sans Pro", Value = "SourceSansPro" },
new() { Text = "Open Sans", Value = "OpenSans" },
new() { Text = "Fira Code", Value = "FiraCode" },
new() { Text = "JetBrains Mono", Value = "JetBrainsMono" }
}
};
fontCombo.Initialize();
fontCombo.SelectedIndexChanged += (s, idx) =>
{
var item = fontCombo.SelectedItem;
Console.WriteLine($"Selected: {item.Text} ({item.Value})");
};
drawingManager.AddComponent(fontCombo);
drawingManager.RequestRedraw();
Editable ComboBox with Filtering
var countryCombo = new ComboBox
{
Placeholder = "Search countries...",
IsEditable = true,
FieldStyle = TextFieldStyle.Filled,
X = 40,
Y = 120,
Width = 300,
Height = 56,
Items = new List<ComboBoxItem>
{
new() { Text = "Argentina", Value = "AR" },
new() { Text = "Australia", Value = "AU" },
new() { Text = "Brazil", Value = "BR" },
new() { Text = "Canada", Value = "CA" },
new() { Text = "France", Value = "FR" },
new() { Text = "Germany", Value = "DE" },
new() { Text = "India", Value = "IN" },
new() { Text = "Japan", Value = "JP" },
new() { Text = "Mexico", Value = "MX" },
new() { Text = "Netherlands", Value = "NL" },
new() { Text = "Spain", Value = "ES" },
new() { Text = "United Kingdom", Value = "UK" },
new() { Text = "United States", Value = "US" }
}
};
countryCombo.Initialize();
drawingManager.AddComponent(countryCombo);
Programmatic Selection
themeCombo.SelectedIndex = 1;
var targetItem = themeCombo.Items
.FirstOrDefault(i => i.Value?.ToString() == "Dark");
if (targetItem != null)
themeCombo.SelectedIndex = themeCombo.Items.IndexOf(targetItem);
themeCombo.OpenDropdown();
themeCombo.CloseDropdown();
ComboBox with Icons
var sizeIcon = SKPath.ParseSvgPathData(
"M3 3h18v2H3V3zm0 4h14v2H3V7zm0 4h18v2H3v-2zm0 4h12v2H3v-2z");
var sizeCombo = new ComboBox
{
Placeholder = "Text Size",
X = 40, Y = 200,
Width = 200, Height = 56,
Items = new List<ComboBoxItem>
{
new() { Text = "Small", Value = 12f, Icon = sizeIcon },
new() { Text = "Medium", Value = 16f, Icon = sizeIcon },
new() { Text = "Large", Value = 20f, Icon = sizeIcon },
new() { Text = "Extra Large", Value = 24f, Icon = sizeIcon }
}
};
sizeCombo.Initialize();
sizeCombo.SelectedIndex = 1;
drawingManager.AddComponent(sizeCombo);
Note
The Dropdown overlay is positioned relative to the ComboBox's location on the canvas. It does not account for window bounds automatically — use DropDirection.Auto and ensure the ComboBox is placed with enough vertical space. For window-edge detection, listen to OverlayManager.BoundsChanged.