ensolabs/designsystemet-elm/1.0.0

Designsystemet.Dropdown

A menu of actions or links that opens from a button.

Mirrors Dropdown from @digdir/designsystemet-react.

import Designsystemet.Dropdown as Dropdown


caseActions : Dropdown.Id
caseActions =
    Dropdown.id "case-actions"


view : Html Msg
view =
    Html.div []
        [ Dropdown.trigger caseActions [ Button.secondary ] [ Html.text "Handlinger" ]
        , Dropdown.view caseActions
            []
            [ Dropdown.heading Heading.H2 [] [ Html.text "Sak 42" ]
            , Dropdown.list []
                [ Dropdown.item [] [ Dropdown.button [ Events.onClick Archive ] [ Html.text "Arkiver" ] ]
                , Dropdown.item [] [ Dropdown.button (Dialog.showModal confirmDelete) [ Html.text "Slett" ] ]
                ]
            ]
        ]

A dropdown is a Popover with menu styling. The browser opens it from the trigger and closes it on Esc or an outside click; designsystemet-web positions it. Dropdown.Id is a separate type, so a popover's id can't open a dropdown by mistake.

React → Elm

  • <Dropdown id="x"> → Dropdown.view (Dropdown.id "x") []
  • <Dropdown.TriggerContext> → not needed: share a Dropdown.Id
  • <Dropdown.Trigger> → Dropdown.trigger id []
  • <Dropdown.Heading> (level 2 by default) → Dropdown.heading Heading.H2 []
  • <Dropdown.List> → Dropdown.list []
  • <Dropdown.Item> → Dropdown.item []
  • <Dropdown.Button> → Dropdown.button []
  • placement="top" → Dropdown.placement Placement.Top
  • open={isOpen} (controlled) → Dropdown.open model.isOpen
  • onOpen / onClose → Dropdown.onToggle

Differences from React

Like Popover, the dropdown is popover="auto", so the browser handles light dismiss, which React does in JavaScript.

Managed by designsystemet-web

As for Popover: the position styles (translate, scroll-margin-bottom, max-height, width), the arrow's --_ds-floating-arrow-* properties and data-floating. Style the dropdown with classes instead of Attr.style.

Ids

type Id

The id that links a dropdown to the buttons that open it.

id : String -> Id

Name a dropdown. The string becomes its DOM id, so it must be unique on the page.

idToString : Id -> String

The DOM id, for ports and tests.

Dropdown

view : Id -> List (Attribute msg) -> List (Html msg) -> Html msg

A <div class="ds-dropdown" popover>, by default below its trigger and aligned to its end edge.

The id always comes from the Id, so triggers keep pointing at it. An Attr.id in the attributes is ignored.

placement : Placement -> Attribute msg

Where the dropdown appears relative to its trigger. Defaults to Placement.BottomEnd.

Content

heading : Level -> List (Attribute msg) -> List (Html msg) -> Html msg

A heading for the menu or a group in it. As with Heading, the level is required. React defaults to H2, but the right level depends on the surrounding page.

Dropdown.heading Heading.H3 [] [ Html.text "Sortering" ]
list : List (Attribute msg) -> List (Html msg) -> Html msg

The <ul> of menu items. To group items, use several, each after its own heading.

item : List (Attribute msg) -> List (Html msg) -> Html msg

One <li> in a list. Put a button or a link in it.

button : List (Attribute msg) -> List (Html msg) -> Html msg

A full-width, tertiary Button for a menu item.

For a link, use Button.viewAs Html.a [ Button.tertiary, Attr.href "…" ]. The dropdown styles it the same way.

Triggers

trigger : Id -> List (Attribute msg) -> List (Html msg) -> Html msg

A Button that opens and closes the dropdown.

Dropdown.trigger userMenu [ Button.tertiary ] [ Html.text "Kari Nordmann" ]

Invokers

toggle : Id -> List (Attribute msg)

Open the dropdown if closed, close it if open. Concatenate with your own attributes on any button:

Button.icon { label = "Flere valg", icon = moreIcon }
    (Button.tertiary :: Dropdown.toggle rowMenu)
show : Id -> List (Attribute msg)

Open the dropdown, or leave it open.

hide : Id -> List (Attribute msg)

Close the dropdown, or leave it closed. On a menu item, it closes the menu when the item is chosen:

Dropdown.button (Events.onClick Archive :: Dropdown.hide caseActions)
    [ Html.text "Arkiver" ]

Events

open : Bool -> Attribute msg

Whether the dropdown is open, from your model (React's open prop). Like Popover.open, it needs the companion script and an onToggle that updates your state when the user closes it.

onToggle : (State -> msg) -> Attribute msg

Sent when the dropdown opens or closes, by the trigger, Esc, an outside click or code. See Popover.onToggle.

type State
= Open
| Closed

Whether a dropdown is showing.