1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-17 09:37:02 +00:00

ui: Implement modal focus trap

This commit is contained in:
James Hillyerd
2020-03-29 16:06:30 -07:00
parent cabbdacb89
commit 4a90b37815
4 changed files with 89 additions and 17 deletions

View File

@@ -37,6 +37,7 @@ import Html.Attributes
, value
)
import Html.Events as Events
import Modal
import Route exposing (Route)
@@ -79,6 +80,8 @@ reset model =
type Msg
= ClearFlash
| ModalFocused Modal.Msg
| ModalUnfocused
| OnMailboxNameInput String
| OpenMailbox
| ShowRecent Bool
@@ -94,6 +97,15 @@ update msg model session =
, Cmd.none
)
ModalFocused message ->
( model
, Modal.updateSession message session
, Cmd.none
)
ModalUnfocused ->
( model, session, Modal.resetFocusCmd (ModalFocused >> model.mapMsg) )
OnMailboxNameInput name ->
( { model | mailboxName = name }
, session
@@ -165,7 +177,7 @@ frame { model, session, activePage, activeMailbox, modal, content } =
]
]
, div [ class "navbar-bg" ] [ text "" ]
, frameModal modal
, Modal.view (ModalUnfocused |> model.mapMsg) modal
, div [ class "page" ] (errorFlash model session.flash :: content)
, footer []
[ div [ class "footer" ]
@@ -178,18 +190,6 @@ frame { model, session, activePage, activeMailbox, modal, content } =
]
frameModal : Maybe (Html msg) -> Html msg
frameModal maybeModal =
case maybeModal of
Just modal ->
div [ class "modal-mask" ]
[ div [ class "modal well" ] [ modal ]
]
Nothing ->
text ""
errorFlash : Model msg -> Maybe Session.Flash -> Html msg
errorFlash model maybeFlash =
let

58
ui/src/Modal.elm Normal file
View File

@@ -0,0 +1,58 @@
module Modal exposing (Msg, resetFocusCmd, updateSession, view)
import Browser.Dom as Dom
import Data.Session as Session exposing (Session)
import Html exposing (Html, div, span, text)
import Html.Attributes exposing (class, id, tabindex)
import Html.Events exposing (onFocus)
import Task
type alias Msg =
Result Dom.Error ()
{-| Creates a command to focus the modal dialog.
-}
resetFocusCmd : (Msg -> msg) -> Cmd msg
resetFocusCmd resultMsg =
Task.attempt resultMsg (Dom.focus domId)
{-| Updates a Session with an error Flash if the resetFocusCmd failed.
-}
updateSession : Msg -> Session -> Session
updateSession result session =
case result of
Ok () ->
session
Err (Dom.NotFound missingDomId) ->
let
flash =
{ title = "DOM element not found"
, table = [ ( "Element ID", missingDomId ) ]
}
in
Session.showFlash flash session
view : msg -> Maybe (Html msg) -> Html msg
view unfocusedMsg maybeModal =
case maybeModal of
Just modal ->
div [ class "modal-mask" ]
[ span [ onFocus unfocusedMsg, tabindex 0 ] []
, div [ id domId, class "modal well", tabindex -1 ] [ modal ]
, span [ onFocus unfocusedMsg, tabindex 0 ] []
]
Nothing ->
text ""
{-| DOM ID of the modal dialog.
-}
domId : String
domId =
"modal-dialog"

View File

@@ -1,6 +1,7 @@
module Page.Mailbox exposing (Model, Msg, init, load, subscriptions, update, view)
import Api
import Browser.Dom as Dom
import Data.Message as Message exposing (Message)
import Data.MessageHeader exposing (MessageHeader)
import Data.Session as Session exposing (Session)
@@ -51,6 +52,7 @@ import Html.Events as Events
import HttpUtil
import Json.Decode as D
import Json.Encode as E
import Modal
import Route
import Task
import Time exposing (Posix)
@@ -174,6 +176,7 @@ type Msg
| PurgedMailbox (Result HttpUtil.Error ())
| OnSearchInput String
| Tick Posix
| ModalFocused Modal.Msg
update : Msg -> Model -> ( Model, Cmd Msg )
@@ -262,6 +265,11 @@ update msg model =
MessageBody bodyMode ->
( { model | bodyMode = bodyMode }, Cmd.none )
ModalFocused message ->
( { model | session = Modal.updateSession message model.session }
, Cmd.none
)
OnSearchInput searchInput ->
updateSearchInput model searchInput
@@ -293,13 +301,13 @@ update msg model =
( model, Cmd.none )
PurgeMailboxPrompt ->
( { model | promptPurge = True }, Cmd.none )
( { model | promptPurge = True }, Modal.resetFocusCmd ModalFocused )
PurgeMailboxCanceled ->
( { model | promptPurge = False }, Cmd.none )
PurgeMailboxConfirmed ->
updatePurge model
updateTriggerPurge model
PurgedMailbox (Ok _) ->
( model, Cmd.none )
@@ -358,8 +366,10 @@ updateMessageResult model message =
)
updatePurge : Model -> ( Model, Cmd Msg )
updatePurge model =
{-| Updates model and triggers commands to purge this mailbox.
-}
updateTriggerPurge : Model -> ( Model, Cmd Msg )
updateTriggerPurge model =
let
cmd =
Cmd.batch

View File

@@ -223,6 +223,10 @@ h3 {
padding: 10px !important;
}
.modal:focus {
outline: none;
}
/** BUTTONS */
.button-bar {