blob: a3637222b189ffac7b2dbb1768ce7f689d8a4a72 [file] [log] [blame]
-- Copyright 2020 The Fuchsia Authors. All rights reserved.
-- Use of this source code is governed by a BSD-style license that can be
-- found in the LICENSE file.
module Window exposing
( Model
, Msg(..)
, init
, isAbsent
, subscriptions
, update
, view
)
{-| This module implements modal windows.
A modal window is a window placed on top of the main app content (which is
dimmed and disabled). The user can dismiss the window by clicking anywhere
outside it, or pressing Escape or Return.
-}
import Browser.Events
import Html exposing (Html)
import Html.Attributes as Attributes
import Html.Events as Events
import Json.Decode as Decode
------------- MODEL ------------------------------------------------------------
type alias Model a =
Maybe a
init : Model a
init =
Nothing
isAbsent : Model a -> Bool
isAbsent model =
case model of
Just _ ->
False
Nothing ->
True
------------- UPDATE -----------------------------------------------------------
type Msg a
= NoOp
| Show a
| Hide
update : Msg a -> Model a -> Model a
update msg model =
case msg of
NoOp ->
model
Show window ->
Just window
Hide ->
Nothing
------------- SUBSCRIPTIONS ----------------------------------------------------
subscriptions : Model a -> Sub (Msg a)
subscriptions model =
case model of
Just _ ->
Browser.Events.onKeyDown keyDownEvent
_ ->
Sub.none
keyDownEvent : Decode.Decoder (Msg a)
keyDownEvent =
Decode.field "key" Decode.string
|> Decode.map
(\key ->
-- For the Help window, catching Enter here is redundant because
-- the focus will still be on the button, and pressing enter
-- again will click it and hide the window. But for the Settings
-- window it is needed since focus might be on a form input. The
-- toggle behavior on the button is still useful so that
-- spacebar hides the window when the button is still focused.
if key == "Enter" || key == "Escape" then
Hide
else
NoOp
)
------------- VIEW -------------------------------------------------------------
view : (a -> Html msg) -> (Msg a -> msg) -> Model a -> Html msg
view windowView toMsg model =
case model of
Nothing ->
Html.text ""
Just window ->
Html.div
[ Attributes.class "modal-container"
, Events.onClick (toMsg Hide)
]
[ Html.div
[ Attributes.id modalBoxId
, Attributes.class "modal-box"
-- Prevent clicking the box itself from hiding it.
, Events.stopPropagationOn "click"
(Decode.succeed ( toMsg NoOp, True ))
]
[ windowView window ]
]
modalBoxId : String
modalBoxId =
"ModalBox"