WIIIIIIIPP implement one of the use cases to use new FocusTrap API

This commit is contained in:
Juan Edi 2020-09-04 19:36:22 -03:00
parent a3d2ab6e4b
commit ba9929ac3a
3 changed files with 97 additions and 9 deletions

View File

@ -1,6 +1,7 @@
module Nri.Ui.FocusTrap.V1 exposing
( first, last
, only
, FocusTrap(..), toAttribute
)
{-| Create a focus trap.
@ -20,6 +21,46 @@ import Json.Decode as Decode exposing (Decoder)
import Task
type FocusTrap
= MultipleElements { firstId : String, lastId : String }
toAttribute : (String -> msg) -> FocusTrap -> Html.Attribute msg
toAttribute focus trap =
case trap of
MultipleElements { firstId, lastId } ->
Events.custom "keydown"
(Decode.andThen
(\( elementId, keyCode, shiftKey ) ->
if keyCode == 9 then
if elementId == firstId && shiftKey then
Decode.succeed
{ message = focus lastId
, preventDefault = True
, stopPropagation = False
}
else if elementId == lastId && not shiftKey then
Decode.succeed
{ message = focus firstId
, preventDefault = True
, stopPropagation = False
}
else
Decode.fail "No need to intercept the key press"
else
Decode.fail "No need to intercept the key press"
)
(Decode.map3 (\id keyCode shiftKey -> ( id, keyCode, shiftKey ))
(Decode.at [ "target", "id" ] Decode.string)
(Decode.field "keyCode" Decode.int)
(Decode.field "shiftKey" Decode.bool)
)
)
{-| -}
only : { focusSelf : msg } -> List (Html.Attribute msg)
only { focusSelf } =

View File

@ -5,6 +5,7 @@ module Nri.Ui.Modal.V11 exposing
, Attribute
, info, warning
, showTitle, hideTitle
, focusTrap
, custom, css
, isOpen
)
@ -23,7 +24,7 @@ import Browser.Dom as Dom
import Html.Styled exposing (..)
import Html.Styled.Attributes exposing (id)
import Html.Styled.Events as Events
import Nri.Ui.FocusTrap.V1 as FocusTrap
import Nri.Ui.FocusTrap.V1 as FocusTrap exposing (FocusTrap)
import Nri.Ui.Modal.V11 as Modal
import Task
@ -179,6 +180,7 @@ view model =
@docs Attribute
@docs info, warning
@docs showTitle, hideTitle
@docs focusTrap
@docs custom, css
@ -205,6 +207,7 @@ import Html.Styled.Events as Events exposing (onClick)
import Json.Decode as Decode exposing (Decoder)
import Nri.Ui.Colors.Extra
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.FocusTrap.V1 as FocusTrap exposing (FocusTrap)
import Nri.Ui.Fonts.V1 as Fonts
import Nri.Ui.SpriteSheet
import Nri.Ui.Svg.V1
@ -326,6 +329,11 @@ showTitle =
Attribute (\attrs -> { attrs | visibleTitle = True })
focusTrap : FocusTrap -> Attribute
focusTrap trap =
Attribute (\attrs -> { attrs | focusTrap = Just trap })
{-| -}
hideTitle : Attribute
hideTitle =
@ -385,6 +393,7 @@ type alias Attributes =
, visibleTitle : Bool
, customStyles : List Style
, customAttributes : List (Html.Attribute Never)
, focusTrap : Maybe FocusTrap
}
@ -395,6 +404,7 @@ defaultAttributes =
, visibleTitle = True
, customStyles = []
, customAttributes = []
, focusTrap = Nothing
}
@ -477,6 +487,7 @@ titleStyles color visibleTitle =
view :
{ title : String
, wrapMsg : Msg -> msg
, focus : String -> msg
, content : List (Html msg)
, footer : List (Html msg)
}
@ -515,7 +526,17 @@ view config attrsList model =
, Root.node "style" [] [ Root.text "body {overflow: hidden;} " ]
]
|> List.singleton
|> div [ Attrs.css [ Css.position Css.relative, Css.zIndex (Css.int 1) ] ]
|> Root.div
(List.concat
[ case attrs.focusTrap of
Nothing ->
[]
Just trap_ ->
[ FocusTrap.toAttribute config.focus trap_ ]
, [ Attrs.css [ Css.position Css.relative, Css.zIndex (Css.int 1) ] ]
]
)
Closed ->
text ""

View File

@ -20,7 +20,7 @@ import Nri.Ui.Button.V10 as Button
import Nri.Ui.Checkbox.V5 as Checkbox
import Nri.Ui.ClickableText.V3 as ClickableText
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.FocusTrap.V1 as FocusTrap
import Nri.Ui.FocusTrap.V1 as FocusTrap exposing (FocusTrap(..))
import Nri.Ui.Modal.V11 as Modal
import Nri.Ui.Text.V4 as Text
import Task
@ -138,8 +138,27 @@ example =
|> Html.fromUnstyled
]
, launchModalButton settings
, Modal.view (modalSettings settings)
(Control.currentValue state.attributes)
, let
{ title, wrapMsg, content, footer, focusTrap } =
modalSettings settings
in
Modal.view
{ title = title
, wrapMsg = wrapMsg
, content = content
, footer = footer
, focus = Focus
}
(List.concatMap identity
[ case focusTrap of
Nothing ->
[]
Just focusTrap_ ->
[ Modal.focusTrap focusTrap_ ]
, Control.currentValue state.attributes
]
)
state.state
]
}
@ -188,6 +207,7 @@ modalSettings :
, wrapMsg : Modal.Msg -> Msg
, content : List (Html Msg)
, footer : List (Html Msg)
, focusTrap : Maybe FocusTrap
}
modalSettings settings =
let
@ -196,21 +216,27 @@ modalSettings settings =
, wrapMsg = ModalMsg
, content = []
, footer = []
, focusTrap = Nothing
}
in
case ( settings.showX, settings.showContinue, settings.showSecondary ) of
( True, True, True ) ->
{ default
| content =
[ Modal.closeButton CloseModal <|
FocusTrap.first { focusLastId = Focus closeClickableTextId }
[ Modal.closeButton CloseModal []
, viewModalContent settings.content
]
, footer =
[ continueButton []
, closeClickableText <|
FocusTrap.last { focusFirstId = Focus Modal.closeButtonId }
, closeClickableText []
]
, focusTrap =
Just
(FocusTrap.MultipleElements
{ firstId = Modal.closeButtonId
, lastId = closeClickableTextId
}
)
}
( True, False, True ) ->