Created
May 26, 2019 00:27
-
-
Save kyasu1/6641af49b22e097cf149907bcc18018e to your computer and use it in GitHub Desktop.
a dropdown in @elmlang that opens when you either click or tab into it and closes when you click again or click outside
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- https://twitter.com/unsoundscapes/status/1132405048338780161 | |
| -- https://ellie-app.com/5DBFLkbVVCwa1 | |
| module Main exposing (main) | |
| import Browser | |
| import Html exposing (Html, button, div, text) | |
| import Html.Attributes exposing (class) | |
| import Html.Events exposing (on, onClick, onFocus) | |
| import Json.Decode as Decode exposing (Decoder, Value) | |
| type alias Model = | |
| { expand : Bool, justFocused : Bool } | |
| initialModel : Model | |
| initialModel = | |
| { expand = False, justFocused = False } | |
| type Msg | |
| = Toggle | |
| | Collapse | |
| | Focus | |
| update : Msg -> Model -> Model | |
| update msg model = | |
| case msg of | |
| Collapse -> | |
| { expand = False, justFocused = False } | |
| Focus -> | |
| if not model.expand then | |
| { justFocused = True, expand = True } | |
| else | |
| model | |
| Toggle -> | |
| if not model.justFocused then | |
| { model | expand = not model.expand } | |
| else | |
| { model | justFocused = False } | |
| view : Model -> Html Msg | |
| view { expand } = | |
| div [ class "dropdown", on "focusout" onFocusout ] | |
| [ button | |
| [ onClick Toggle | |
| , onFocus Focus | |
| ] | |
| [ text "toggle" ] | |
| , div [] | |
| (if expand then | |
| [ div [] [ button [] [ text "item1" ] ] | |
| , div [] [ button [] [ text "item2" ] ] | |
| , div [] [ button [] [ text "item3" ] ] | |
| , div [] [ button [] [ text "item4" ] ] | |
| ] | |
| else | |
| [] | |
| ) | |
| ] | |
| main : Program () Model Msg | |
| main = | |
| Browser.sandbox | |
| { init = initialModel | |
| , view = view | |
| , update = update | |
| } | |
| onFocusout : Decoder Msg | |
| onFocusout = | |
| Decode.field "relatedTarget" outsideDropdown | |
| |> Decode.andThen | |
| (\outside -> | |
| if outside then | |
| Decode.succeed Collapse | |
| else | |
| Decode.fail "inside the dropdown" | |
| ) | |
| outsideDropdown : Decoder Bool | |
| outsideDropdown = | |
| Decode.oneOf | |
| [ Decode.andThen | |
| (\id -> | |
| if id == "dropdown" then | |
| Decode.succeed False | |
| else | |
| Decode.fail "continue" | |
| ) | |
| (Decode.field "className" Decode.string) | |
| , Decode.lazy (\_ -> Decode.field "parentNode" outsideDropdown) | |
| , Decode.succeed True | |
| ] | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment