mirror of
https://github.com/NoRedInk/noredink-ui.git
synced 2024-12-01 00:34:27 +03:00
WIIIIIIIPP implement one of the use cases to use new FocusTrap API
This commit is contained in:
parent
a3d2ab6e4b
commit
ba9929ac3a
@ -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 } =
|
||||
|
@ -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 ""
|
||||
|
@ -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 ) ->
|
||||
|
Loading…
Reference in New Issue
Block a user