Dropdown
Dropdowns expose additional content that "drops down" in a panel.
Dropdowns consist of a trigger and a panel. By default, activating the trigger will expose the panel and interacting outside of the panel will close it.
Dropdowns are designed to work well with dropdown items to provide a list of options the user can select from. However, dropdowns can also be used in lower-level applications. The API gives you complete control over showing, hiding, and positioning the panel.
Dropdown( _.slots.trigger( Button(_.withCaret := true)("View") ))( DropdownItem( _.slots.icon(Icon(_.name := "scissors")()) )("Cut"), DropdownItem( _.slots.icon(Icon(_.name := "copy")()) )("Copy"), DropdownItem( _.slots.icon(Icon(_.name := "paste")()) )("Paste"), Divider()(), DropdownItem( _.slots.submenu(DropdownItem(_.value := "show-all-images")("Show All Images")), _.slots.submenu(DropdownItem(_.value := "show-thumbnails")("Show Thumbnails")) )("Show images"), Divider()(), DropdownItem( _.`type`.checkbox, _.checked := true )("Emoji Shortcuts"), DropdownItem( _.`type`.checkbox, _.checked := true )("Word Wrap"), Divider()(), DropdownItem( _.variant.danger, _.slots.icon(Icon(_.name := "trash")()) )("Delete"))Examples
Getting the Selected Item
When an item is selected, the wa-select event will be emitted by the dropdown. You can inspect event.detail.item to get a reference to the selected item. If you've provided a value for each dropdown item, it will be available in event.detail.item.value.
Dropdown( _.onSelect.map(_.detail.item.value.toOption) --> Observer[Option[String]](println), _.slots.trigger( Button(_.withCaret := true)("View") ))( DropdownItem(_.value := "full-screen")("Enter full screen"), DropdownItem(_.value := "actual")("Actual size"), DropdownItem(_.value := "zoom-in")("Zoom in"), DropdownItem(_.value := "zoom-out")("Zoom out"))To keep the dropdown open after selection, call event.preventDefault() in the wa-select event's callback.
Showing Icons
Use the icon slot to add icons to dropdown items. This works best with icon elements.
Dropdown( _.slots.trigger( Button(_.withCaret := true)("Edit") ))( DropdownItem(_.value := "cut", _.slots.icon(Icon(_.name := "scissors")()))("Cut"), DropdownItem(_.value := "copy", _.slots.icon(Icon(_.name := "copy")()))("Copy"), DropdownItem(_.value := "paste", _.slots.icon(Icon(_.name := "paste")()))("Paste"), DropdownItem(_.value := "delete", _.slots.icon(Icon(_.name := "trash")()))("Delete"))Showing Labels & Dividers
Use any heading, e.g. <h1>-<h6> to add labels and the <wa-divider> element for separators.
Dropdown( _.slots.trigger( Button(_.withCaret := true)("Device") ))( h3("Type"), DropdownItem(_.value := "phone")("Phone"), DropdownItem(_.value := "tablet")("Tablet"), DropdownItem(_.value := "desktop")("Desktop"), Divider()(), DropdownItem(_.value := "more")("More options..."))Showing Details
Use the details slot to display details, such as keyboard shortcuts, inside dropdown items.
Dropdown( _.slots.trigger( Button(_.withCaret := true)("Message") ))( DropdownItem( _.value := "reply", _.slots.details(span("⌘R")) )("Reply"), DropdownItem( _.value := "forward", _.slots.details(span("⌘F")) )("Forward"), DropdownItem( _.value := "move", _.slots.details(span("⌘M")) )("Move"), Divider()(), DropdownItem( _.value := "archive", _.slots.details(span("⌘A")) )("Archive"), DropdownItem( _.value := "delete", _.slots.details(span("Del")) )("Delete"))Checkable Items
You can turn a dropdown item into a checkable option by setting type="checkbox". Add the checked attribute to make it checked initially. When clicked, the item's checked state will toggle and the dropdown will close. You can cancel the wa-select event if you want to keep it open instead.
Dropdown( _.onSelect.map { event => event.detail.item.`type`.toOption match { case Some("checkbox") => println(event.detail.item.value.toOption) println(event.detail.item.checked.toOption) case _ => println(event.detail.item.value.toOption) } } --> Observer.empty, _.slots.trigger( Button(_.withCaret := true)("View") ))( DropdownItem(_.`type`.checkbox, _.value := "canvas", _.checked := true)("Show canvas"), DropdownItem(_.`type`.checkbox, _.value := "grid", _.checked := true)("Show grid"), DropdownItem(_.`type`.checkbox, _.value := "source")("Show source"), Divider()(), DropdownItem(_.value := "preferences")("Preferences…"))When a checkable option exists anywhere in the dropdown, all items will receive additional padding so they align properly.
Destructive Items
Add variant="danger" to any dropdown item to highlight that it's a dangerous action.
Dropdown( _.slots.trigger( Button(_.withCaret := true)("Project") ))( DropdownItem( _.value := "share", _.slots.icon( Icon(_.name := "share")() ) )("Share"), DropdownItem( _.value := "preferences", _.slots.icon( Icon(_.name := "gear")() ) )("Preferences"), Divider()(), h3("Danger zone"), DropdownItem( _.value := "archive", _.slots.icon( Icon(_.name := "archive")() ) )("Archive"), DropdownItem( _.value := "delete", _.variant := "danger", _.slots.icon( Icon(_.name := "trash")() ) )("Delete"))Placement
The preferred placement of the dropdown can be set with the placement attribute. Note that the actual position may vary to ensure the panel remains in the viewport.
Dropdown( _.slots.trigger( Button( _.withCaret := true, _.slots.end( Icon(_.name := "chevron-right")() ) )("File formats") ))( DropdownItem(_.value := "pdf")("PDF Document"), DropdownItem(_.value := "docx")("Word Document"), DropdownItem(_.value := "xlsx")("Excel Spreadsheet"), DropdownItem(_.value := "pptx")("PowerPoint Presentation"), DropdownItem(_.value := "txt")("Plain Text"), DropdownItem(_.value := "json")("JSON File"))Distance
The distance from the panel to the trigger can be customized using the distance attribute. This value is specified in pixels.
Dropdown( _.distance := 30.0, _.slots.trigger( Button(_.withCaret := true)("Edit") ))( DropdownItem()("Cut"), DropdownItem()("Copy"), DropdownItem()("Paste"), Divider()(), DropdownItem()("Find"), DropdownItem()("Replace"))Offset
The offset of the panel along the trigger can be customized using the skidding attribute. This value is specified in pixels.
Dropdown( _.skidding := 30.0, _.slots.trigger( Button(_.withCaret := true)("Edit") ))( DropdownItem()("Cut"), DropdownItem()("Copy"), DropdownItem()("Paste"), Divider()(), DropdownItem()("Find"), DropdownItem()("Replace"))Submenus
To create submenus, nest dropdown items inside of a dropdown item and assign slot="submenu" to each one. You can also add dividers as needed.
Dropdown( _.slots.trigger( Button(_.withCaret := true)("Export") ))( DropdownItem( _.slots.submenu(DropdownItem(_.value := "pdf")("PDF")), _.slots.submenu(DropdownItem(_.value := "docx")("Word Document")) )("Documents"), DropdownItem( _.slots.submenu( DropdownItem( _.slots.submenu(DropdownItem(_.value := "xlsx")("Excel (.xlsx)")), _.slots.submenu(DropdownItem(_.value := "xls")("Excel 97-2003 (.xls)")), _.slots.submenu(DropdownItem(_.value := "csv")("CSV (.csv)")) )("Excel Formats") ), _.slots.submenu( DropdownItem( _.slots.submenu(DropdownItem(_.value := "ods")("OpenDocument (.ods)")), _.slots.submenu(DropdownItem(_.value := "tsv")("Tab-separated (.tsv)")), _.slots.submenu(DropdownItem(_.value := "json")("JSON (.json)")) )("Other Formats") ), _.slots.submenu(DropdownItem(_.value := "numbers")("Apple Numbers")) )("Spreadsheets"), Divider()(), DropdownItem( _.slots.submenu(DropdownItem(_.`type`.checkbox, _.value := "compress")("Compress files")), _.slots.submenu( DropdownItem(_.`type`.checkbox, _.checked := true, _.value := "metadata")("Include metadata") ), _.slots.submenu(DropdownItem(_.`type`.checkbox, _.value := "password")("Password protect")) )("Options"))Dropdown items that have a submenu will not dispatch the wa-select event. However, items inside the submenu will, unless they also have a submenu.
As a UX best practice, avoid using more than one level of submenu when possible.
Disabling Items
Add the disabled attribute to any dropdown item to disable it.
Dropdown( _.slots.trigger( Button(_.withCaret := true)("Payment method") ))( DropdownItem(_.value := "cash")("Cash"), DropdownItem(_.value := "check", _.disabled := true)("Personal check"), DropdownItem(_.value := "credit")("Credit card"), DropdownItem(_.value := "gift-card")("Gift card"))