mirror of
https://github.com/NoRedInk/noredink-ui.git
synced 2025-01-01 19:09:01 +03:00
Switch to FocusManager type
This commit is contained in:
parent
1ced4bebde
commit
885b457677
@ -3,7 +3,7 @@ module Nri.Ui.Modal.V9 exposing
|
||||
, Msg, update, subscriptions
|
||||
, open, close
|
||||
, info, warning
|
||||
, multipleFocusableElementView, onlyFocusableElementView
|
||||
, FocusManager(..)
|
||||
)
|
||||
|
||||
{-| Changes from V8:
|
||||
@ -23,11 +23,6 @@ module Nri.Ui.Modal.V9 exposing
|
||||
|
||||
@docs info, warning
|
||||
|
||||
|
||||
### Focusable
|
||||
|
||||
@docs multipleFocusableElementView, onlyFocusableElementView
|
||||
|
||||
-}
|
||||
|
||||
import Accessibility.Styled as Html exposing (..)
|
||||
@ -141,170 +136,53 @@ close =
|
||||
CloseModal Other
|
||||
|
||||
|
||||
{-| -}
|
||||
info :
|
||||
{ visibleTitle : Bool
|
||||
, title : String
|
||||
, wrapMsg : Msg -> msg
|
||||
}
|
||||
->
|
||||
({ viewContent : { content : List (Html msg), footer : List (Html msg) } -> Html msg
|
||||
, closeButton : List (Html.Attribute msg) -> Html msg
|
||||
}
|
||||
-> Attribute msg
|
||||
)
|
||||
-> Model
|
||||
-> Html msg
|
||||
info config getFocusable model =
|
||||
let
|
||||
appliedAttrs =
|
||||
List.foldl (\(Attribute f) acc -> f acc)
|
||||
{ visibleTitle = config.visibleTitle
|
||||
, overlayColor = Nri.Ui.Colors.Extra.withAlpha 0.9 Colors.navy
|
||||
, wrapMsg = config.wrapMsg
|
||||
, modalStyle = modalStyle
|
||||
, titleString = config.title
|
||||
, titleStyles = titleStyle Colors.navy config.visibleTitle
|
||||
, autofocusOn = Default
|
||||
, content = \_ -> text ""
|
||||
}
|
||||
[ getFocusable
|
||||
{ viewContent = viewContent config.visibleTitle
|
||||
, closeButton = closeButton config.wrapMsg
|
||||
}
|
||||
]
|
||||
in
|
||||
view config.wrapMsg config.title appliedAttrs model
|
||||
|
||||
|
||||
{-| -}
|
||||
warning :
|
||||
{ visibleTitle : Bool
|
||||
, title : String
|
||||
, wrapMsg : Msg -> msg
|
||||
}
|
||||
->
|
||||
({ viewContent : { content : List (Html msg), footer : List (Html msg) } -> Html msg
|
||||
, closeButton : List (Html.Attribute msg) -> Html msg
|
||||
}
|
||||
-> Attribute msg
|
||||
)
|
||||
-> Model
|
||||
-> Html msg
|
||||
warning config getFocusable model =
|
||||
let
|
||||
appliedAttrs =
|
||||
List.foldl (\(Attribute f) acc -> f acc)
|
||||
{ visibleTitle = config.visibleTitle
|
||||
, overlayColor = Nri.Ui.Colors.Extra.withAlpha 0.9 Colors.gray20
|
||||
, wrapMsg = config.wrapMsg
|
||||
, modalStyle = modalStyle
|
||||
, titleString = config.title
|
||||
, titleStyles = titleStyle Colors.red config.visibleTitle
|
||||
, autofocusOn = Default
|
||||
, content = \_ -> text ""
|
||||
}
|
||||
[ getFocusable
|
||||
{ viewContent = viewContent config.visibleTitle
|
||||
, closeButton = closeButton config.wrapMsg
|
||||
}
|
||||
]
|
||||
in
|
||||
view config.wrapMsg config.title appliedAttrs model
|
||||
|
||||
|
||||
|
||||
-- ATTRIBUTES
|
||||
|
||||
|
||||
type alias Config msg =
|
||||
{ visibleTitle : Bool
|
||||
, overlayColor : Color
|
||||
, wrapMsg : Msg -> msg
|
||||
, modalStyle : Style
|
||||
, titleString : String
|
||||
, titleStyles : List Style
|
||||
, autofocusOn : Autofocus
|
||||
, content :
|
||||
{ onlyFocusableElement : List (Html.Attribute msg)
|
||||
, firstFocusableElement : List (Html.Attribute msg)
|
||||
, lastFocusableElement : List (Html.Attribute msg)
|
||||
, autofocusOn : Html.Attribute msg
|
||||
}
|
||||
-> Html msg
|
||||
}
|
||||
{-| -}
|
||||
type FocusManager msg
|
||||
= MultipleFocusableElements
|
||||
({ firstFocusableElement : List (Attribute msg)
|
||||
, lastFocusableElement : List (Attribute msg)
|
||||
, autofocusElement : Attribute msg
|
||||
, closeButton : List (Attribute msg) -> Html msg
|
||||
}
|
||||
->
|
||||
{ content : List (Html msg)
|
||||
, footer : List (Html msg)
|
||||
}
|
||||
)
|
||||
| OneFocusableElement
|
||||
({ onlyFocusableElement : List (Attribute msg)
|
||||
, closeButton : List (Attribute msg) -> Html msg
|
||||
}
|
||||
->
|
||||
{ content : List (Html msg)
|
||||
, footer : List (Html msg)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
modalStyle : Style
|
||||
modalStyle : List Style
|
||||
modalStyle =
|
||||
batch
|
||||
[ -- Border
|
||||
borderRadius (px 20)
|
||||
, border3 (px 2) solid (rgb 127 0 127)
|
||||
, boxShadow5 zero (px 1) (px 10) zero (rgba 0 0 0 0.35)
|
||||
[ position relative -- Border
|
||||
, borderRadius (px 20)
|
||||
, border3 (px 2) solid (rgb 127 0 127)
|
||||
, boxShadow5 zero (px 1) (px 10) zero (rgba 0 0 0 0.35)
|
||||
|
||||
-- Spacing
|
||||
, margin2 (px 50) auto
|
||||
, padding (px 20)
|
||||
-- Spacing
|
||||
, margin2 (px 50) auto
|
||||
, padding (px 20)
|
||||
|
||||
-- Size
|
||||
, minHeight (vh 40)
|
||||
, width (px 600)
|
||||
, backgroundColor Colors.white
|
||||
-- Size
|
||||
, minHeight (vh 40)
|
||||
, width (px 600)
|
||||
, backgroundColor Colors.white
|
||||
|
||||
-- the modal should grow up to the viewport minus a 50px margin
|
||||
, maxHeight (calc (pct 100) minus (px 100))
|
||||
]
|
||||
|
||||
|
||||
{-| -}
|
||||
type Attribute msg
|
||||
= Attribute (Config msg -> Config msg)
|
||||
|
||||
|
||||
{-| -}
|
||||
multipleFocusableElementView :
|
||||
({ firstFocusableElement : List (Html.Attribute msg)
|
||||
, lastFocusableElement : List (Html.Attribute msg)
|
||||
, autofocusElement : Html.Attribute msg
|
||||
}
|
||||
-> Html msg
|
||||
)
|
||||
-> Attribute msg
|
||||
multipleFocusableElementView f =
|
||||
Attribute
|
||||
(\config ->
|
||||
{ config
|
||||
| content =
|
||||
\{ firstFocusableElement, lastFocusableElement, autofocusOn } ->
|
||||
f
|
||||
{ firstFocusableElement = firstFocusableElement
|
||||
, lastFocusableElement = lastFocusableElement
|
||||
, autofocusElement = autofocusOn
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
{-| -}
|
||||
onlyFocusableElementView :
|
||||
({ onlyFocusableElement : List (Html.Attribute msg)
|
||||
}
|
||||
-> Html msg
|
||||
)
|
||||
-> Attribute msg
|
||||
onlyFocusableElementView f =
|
||||
Attribute
|
||||
(\config ->
|
||||
{ config
|
||||
| content =
|
||||
\{ onlyFocusableElement } ->
|
||||
f
|
||||
{ onlyFocusableElement = onlyFocusableElement
|
||||
}
|
||||
, autofocusOn = Last
|
||||
}
|
||||
)
|
||||
-- the modal should grow up to the viewport minus a 50px margin
|
||||
, maxHeight (calc (pct 100) minus (px 100))
|
||||
]
|
||||
|
||||
|
||||
titleStyle : Color -> Bool -> List Style
|
||||
@ -337,13 +215,48 @@ titleStyle titleColor visibleTitle =
|
||||
-- VIEW
|
||||
|
||||
|
||||
view :
|
||||
(Msg -> msg)
|
||||
-> String
|
||||
-> Config msg
|
||||
{-| -}
|
||||
info :
|
||||
{ visibleTitle : Bool
|
||||
, title : String
|
||||
, wrapMsg : Msg -> msg
|
||||
, focusManager : FocusManager msg
|
||||
}
|
||||
-> Model
|
||||
-> Html msg
|
||||
view wrapMsg ti config model =
|
||||
info config =
|
||||
view config
|
||||
{ overlayColor = Nri.Ui.Colors.Extra.withAlpha 0.9 Colors.navy
|
||||
, titleStyles = titleStyle Colors.navy config.visibleTitle
|
||||
}
|
||||
|
||||
|
||||
{-| -}
|
||||
warning :
|
||||
{ visibleTitle : Bool
|
||||
, title : String
|
||||
, wrapMsg : Msg -> msg
|
||||
, focusManager : FocusManager msg
|
||||
}
|
||||
-> Model
|
||||
-> Html msg
|
||||
warning config =
|
||||
view config
|
||||
{ overlayColor = Nri.Ui.Colors.Extra.withAlpha 0.9 Colors.gray20
|
||||
, titleStyles = titleStyle Colors.red config.visibleTitle
|
||||
}
|
||||
|
||||
|
||||
view :
|
||||
{ visibleTitle : Bool
|
||||
, title : String
|
||||
, wrapMsg : Msg -> msg
|
||||
, focusManager : FocusManager msg
|
||||
}
|
||||
-> { overlayColor : Color, titleStyles : List Style }
|
||||
-> Model
|
||||
-> Html msg
|
||||
view config styles model =
|
||||
case model of
|
||||
Opened _ ->
|
||||
div
|
||||
@ -359,10 +272,8 @@ view wrapMsg ti config model =
|
||||
, zIndex (int 1)
|
||||
]
|
||||
]
|
||||
[ viewBackdrop config
|
||||
, div
|
||||
[ css [ position relative, config.modalStyle ] ]
|
||||
[ viewModal config ]
|
||||
[ viewBackdrop config.wrapMsg styles.overlayColor
|
||||
, div [ css modalStyle ] [ viewModal config styles ]
|
||||
, Root.node "style" [] [ Root.text "body {overflow: hidden;} " ]
|
||||
]
|
||||
|
||||
@ -370,10 +281,8 @@ view wrapMsg ti config model =
|
||||
text ""
|
||||
|
||||
|
||||
viewBackdrop :
|
||||
{ a | wrapMsg : Msg -> msg, overlayColor : Color }
|
||||
-> Html msg
|
||||
viewBackdrop config =
|
||||
viewBackdrop : (Msg -> msg) -> Color -> Html msg
|
||||
viewBackdrop wrapMsg overlayColor =
|
||||
Root.div
|
||||
-- We use Root html here in order to allow clicking to exit out of
|
||||
-- the overlay. This behavior is available to non-mouse users as
|
||||
@ -383,70 +292,58 @@ viewBackdrop config =
|
||||
[ position absolute
|
||||
, width (pct 100)
|
||||
, height (pct 100)
|
||||
, backgroundColor config.overlayColor
|
||||
, backgroundColor overlayColor
|
||||
]
|
||||
, onClick (config.wrapMsg (CloseModal OverlayClick))
|
||||
, onClick (wrapMsg (CloseModal OverlayClick))
|
||||
]
|
||||
[]
|
||||
|
||||
|
||||
viewModal : Config msg -> Html msg
|
||||
viewModal config =
|
||||
viewModal :
|
||||
{ visibleTitle : Bool
|
||||
, title : String
|
||||
, wrapMsg : Msg -> msg
|
||||
, focusManager : FocusManager msg
|
||||
}
|
||||
-> { a | titleStyles : List Style }
|
||||
-> Html msg
|
||||
viewModal config styles =
|
||||
section
|
||||
[ Role.dialog
|
||||
, Aria.labeledBy modalTitleId
|
||||
]
|
||||
[ h1 [ id modalTitleId, css config.titleStyles ] [ text config.titleString ]
|
||||
, config.content
|
||||
(case config.autofocusOn of
|
||||
Last ->
|
||||
{ onlyFocusableElement =
|
||||
[ Key.onKeyDown
|
||||
[ Key.tabBack (Focus firstId)
|
||||
, Key.tab (Focus firstId)
|
||||
]
|
||||
, id firstId
|
||||
]
|
||||
|> List.map (Attributes.map config.wrapMsg)
|
||||
, firstFocusableElement =
|
||||
[ Key.onKeyDown [ Key.tabBack (Focus autofocusId) ]
|
||||
, id firstId
|
||||
]
|
||||
|> List.map (Attributes.map config.wrapMsg)
|
||||
, lastFocusableElement =
|
||||
[ Key.onKeyDown [ Key.tab (Focus firstId) ]
|
||||
, id autofocusId
|
||||
]
|
||||
|> List.map (Attributes.map config.wrapMsg)
|
||||
, autofocusOn =
|
||||
id autofocusId
|
||||
|> Attributes.map config.wrapMsg
|
||||
}
|
||||
[ h1 [ id modalTitleId, css styles.titleStyles ] [ text config.title ]
|
||||
, viewContent config.visibleTitle <|
|
||||
case config.focusManager of
|
||||
OneFocusableElement toContentAndFooter ->
|
||||
toContentAndFooter
|
||||
{ onlyFocusableElement =
|
||||
List.map (Attributes.map config.wrapMsg)
|
||||
[ Key.onKeyDown
|
||||
[ Key.tabBack (Focus autofocusId)
|
||||
, Key.tab (Focus autofocusId)
|
||||
]
|
||||
, id autofocusId
|
||||
]
|
||||
, closeButton = closeButton config.wrapMsg
|
||||
}
|
||||
|
||||
_ ->
|
||||
{ onlyFocusableElement =
|
||||
[ Key.onKeyDown
|
||||
[ Key.tabBack (Focus firstId)
|
||||
, Key.tab (Focus firstId)
|
||||
]
|
||||
, id firstId
|
||||
]
|
||||
|> List.map (Attributes.map config.wrapMsg)
|
||||
, firstFocusableElement =
|
||||
[ Key.onKeyDown [ Key.tabBack (Focus lastId) ]
|
||||
, id firstId
|
||||
]
|
||||
|> List.map (Attributes.map config.wrapMsg)
|
||||
, lastFocusableElement =
|
||||
[ Key.onKeyDown [ Key.tab (Focus firstId) ]
|
||||
, id lastId
|
||||
]
|
||||
|> List.map (Attributes.map config.wrapMsg)
|
||||
, autofocusOn =
|
||||
id autofocusId
|
||||
|> Attributes.map config.wrapMsg
|
||||
}
|
||||
)
|
||||
MultipleFocusableElements toContentAndFooter ->
|
||||
toContentAndFooter
|
||||
{ firstFocusableElement =
|
||||
List.map (Attributes.map config.wrapMsg)
|
||||
[ Key.onKeyDown [ Key.tabBack (Focus lastId) ]
|
||||
, id firstId
|
||||
]
|
||||
, lastFocusableElement =
|
||||
List.map (Attributes.map config.wrapMsg)
|
||||
[ Key.onKeyDown [ Key.tab (Focus firstId) ]
|
||||
, id lastId
|
||||
]
|
||||
, autofocusElement =
|
||||
Attributes.map config.wrapMsg (id autofocusId)
|
||||
, closeButton = closeButton config.wrapMsg
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@ -586,7 +483,7 @@ viewFooter children =
|
||||
|
||||
|
||||
{-| -}
|
||||
closeButton : (Msg -> msg) -> List (Html.Attribute msg) -> Html msg
|
||||
closeButton : (Msg -> msg) -> List (Attribute msg) -> Html msg
|
||||
closeButton wrapMsg focusableElementAttrs =
|
||||
button
|
||||
(Widget.label "Close modal"
|
||||
|
@ -25,9 +25,28 @@ import Nri.Ui.Text.V4 as Text
|
||||
|
||||
{-| -}
|
||||
type alias State =
|
||||
{ infoModal : Modal.Model
|
||||
, warningModal : Modal.Model
|
||||
, visibleTitle : Bool
|
||||
{ state : Modal.Model
|
||||
, content : Content
|
||||
, settings : Settings
|
||||
}
|
||||
|
||||
|
||||
{-| -}
|
||||
init : State
|
||||
init =
|
||||
{ state = Modal.init
|
||||
, content = Info
|
||||
, settings = initModalSettings
|
||||
}
|
||||
|
||||
|
||||
type Content
|
||||
= Info
|
||||
| Warning
|
||||
|
||||
|
||||
type alias Settings =
|
||||
{ visibleTitle : Bool
|
||||
, showX : Bool
|
||||
, showContinue : Bool
|
||||
, showSecondary : Bool
|
||||
@ -36,12 +55,9 @@ type alias State =
|
||||
}
|
||||
|
||||
|
||||
{-| -}
|
||||
init : State
|
||||
init =
|
||||
{ infoModal = Modal.init
|
||||
, warningModal = Modal.init
|
||||
, visibleTitle = True
|
||||
initModalSettings : Settings
|
||||
initModalSettings =
|
||||
{ visibleTitle = True
|
||||
, showX = True
|
||||
, showContinue = True
|
||||
, showSecondary = True
|
||||
@ -53,7 +69,7 @@ init =
|
||||
{-| -}
|
||||
example : Example State Msg
|
||||
example =
|
||||
{ name = "Nri.Ui.Modal.V8"
|
||||
{ name = "Nri.Ui.Modal.V9"
|
||||
, categories = [ Modals ]
|
||||
, atomicDesignType = Organism
|
||||
, keyboardSupport = []
|
||||
@ -62,194 +78,169 @@ example =
|
||||
, subscriptions = subscriptions
|
||||
, view =
|
||||
\state ->
|
||||
[ viewSettings state
|
||||
[ viewSettings state.settings
|
||||
, Button.button "Launch Info Modal"
|
||||
[ Button.onClick (InfoModalMsg (Modal.open "launch-info-modal"))
|
||||
[ Button.onClick (ModalMsg (Modal.open "launch-info-modal"))
|
||||
, Button.custom [ Attributes.id "launch-info-modal" ]
|
||||
, Button.css [ Css.marginRight (Css.px 16) ]
|
||||
, Button.secondary
|
||||
, Button.medium
|
||||
]
|
||||
, Button.button "Launch Warning Modal"
|
||||
[ Button.onClick (WarningModalMsg (Modal.open "launch-warning-modal"))
|
||||
[ Button.onClick (ModalMsg (Modal.open "launch-warning-modal"))
|
||||
, Button.custom [ Attributes.id "launch-warning-modal" ]
|
||||
, Button.secondary
|
||||
, Button.medium
|
||||
]
|
||||
, let
|
||||
params =
|
||||
( state, InfoModalMsg, Button.primary )
|
||||
in
|
||||
Modal.info { title = "Modal.info", wrapMsg = InfoModalMsg, visibleTitle = state.visibleTitle }
|
||||
(getFocusable params)
|
||||
state.infoModal
|
||||
, let
|
||||
params =
|
||||
( state, WarningModalMsg, Button.danger )
|
||||
in
|
||||
Modal.warning { title = "Modal.warning", wrapMsg = WarningModalMsg, visibleTitle = state.visibleTitle }
|
||||
(getFocusable params)
|
||||
state.warningModal
|
||||
, case state.content of
|
||||
Info ->
|
||||
Modal.info
|
||||
{ title = "Modal.info"
|
||||
, wrapMsg = ModalMsg
|
||||
, visibleTitle = state.settings.visibleTitle
|
||||
, focusManager = makeFocusManager Button.primary state.settings
|
||||
}
|
||||
state.state
|
||||
|
||||
Warning ->
|
||||
Modal.warning
|
||||
{ title = "Modal.warning"
|
||||
, wrapMsg = ModalMsg
|
||||
, visibleTitle = state.settings.visibleTitle
|
||||
, focusManager = makeFocusManager Button.danger state.settings
|
||||
}
|
||||
state.state
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
--getFocusable :
|
||||
-- ( State, Modal.Msg -> Msg, Button.Attribute Msg )
|
||||
-- ->
|
||||
-- { viewContent : { content : List (Html Msg), footer : List (Html Msg) } -> Html Msg
|
||||
-- , closeButton : List (Html.Attribute Msg) -> Html Msg
|
||||
-- }
|
||||
-- -> Modal.Focusable Msg
|
||||
|
||||
|
||||
getFocusable ( state, wrapMsg, firstButtonStyle ) { viewContent, closeButton } =
|
||||
case ( state.showX, state.showContinue, state.showSecondary ) of
|
||||
makeFocusManager : Button.Attribute Msg -> Settings -> Modal.FocusManager Msg
|
||||
makeFocusManager firstButtonStyle settings =
|
||||
case ( settings.showX, settings.showContinue, settings.showSecondary ) of
|
||||
( True, True, True ) ->
|
||||
Modal.multipleFocusableElementView
|
||||
(\{ firstFocusableElement, autofocusElement, lastFocusableElement } ->
|
||||
div []
|
||||
[ closeButton firstFocusableElement
|
||||
, viewContent
|
||||
{ content = [ viewModalContent state.longContent ]
|
||||
, footer =
|
||||
[ Button.button "Continue"
|
||||
[ firstButtonStyle
|
||||
, Button.onClick ForceClose
|
||||
, Button.large
|
||||
, Button.custom [ autofocusElement ]
|
||||
]
|
||||
, ClickableText.button "Close"
|
||||
[ ClickableText.onClick ForceClose
|
||||
, ClickableText.large
|
||||
, ClickableText.custom lastFocusableElement
|
||||
, ClickableText.css [ Css.marginTop (Css.px 12) ]
|
||||
]
|
||||
]
|
||||
}
|
||||
Modal.MultipleFocusableElements <|
|
||||
\modalOptions ->
|
||||
{ content =
|
||||
[ modalOptions.closeButton modalOptions.firstFocusableElement
|
||||
, viewModalContent settings.longContent
|
||||
]
|
||||
)
|
||||
, footer =
|
||||
[ Button.button "Continue"
|
||||
[ firstButtonStyle
|
||||
, Button.onClick ForceClose
|
||||
, Button.large
|
||||
, Button.custom [ modalOptions.autofocusElement ]
|
||||
]
|
||||
, ClickableText.button "Close"
|
||||
[ ClickableText.onClick ForceClose
|
||||
, ClickableText.large
|
||||
, ClickableText.custom modalOptions.lastFocusableElement
|
||||
, ClickableText.css [ Css.marginTop (Css.px 12) ]
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
( True, False, True ) ->
|
||||
Modal.multipleFocusableElementView
|
||||
(\{ firstFocusableElement, autofocusElement, lastFocusableElement } ->
|
||||
div []
|
||||
[ closeButton firstFocusableElement
|
||||
, viewContent
|
||||
{ content = [ viewModalContent state.longContent ]
|
||||
, footer =
|
||||
[ ClickableText.button "Close"
|
||||
[ ClickableText.onClick ForceClose
|
||||
, ClickableText.large
|
||||
, ClickableText.custom (autofocusElement :: lastFocusableElement)
|
||||
, ClickableText.css [ Css.marginTop (Css.px 12) ]
|
||||
]
|
||||
]
|
||||
}
|
||||
Modal.MultipleFocusableElements <|
|
||||
\modalOptions ->
|
||||
{ content =
|
||||
[ modalOptions.closeButton modalOptions.firstFocusableElement
|
||||
, viewModalContent settings.longContent
|
||||
]
|
||||
)
|
||||
, footer =
|
||||
[ ClickableText.button "Close"
|
||||
[ ClickableText.onClick ForceClose
|
||||
, ClickableText.large
|
||||
, ClickableText.custom (modalOptions.autofocusElement :: modalOptions.lastFocusableElement)
|
||||
, ClickableText.css [ Css.marginTop (Css.px 12) ]
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
( True, False, False ) ->
|
||||
Modal.onlyFocusableElementView
|
||||
(\{ onlyFocusableElement } ->
|
||||
div []
|
||||
Modal.OneFocusableElement
|
||||
(\{ onlyFocusableElement, closeButton } ->
|
||||
{ content =
|
||||
[ closeButton onlyFocusableElement
|
||||
, viewContent
|
||||
{ content = [ viewModalContent state.longContent ]
|
||||
, footer = []
|
||||
}
|
||||
, viewModalContent settings.longContent
|
||||
]
|
||||
, footer = []
|
||||
}
|
||||
)
|
||||
|
||||
( True, True, False ) ->
|
||||
Modal.multipleFocusableElementView
|
||||
(\{ firstFocusableElement, autofocusElement, lastFocusableElement } ->
|
||||
div []
|
||||
[ closeButton firstFocusableElement
|
||||
, viewContent
|
||||
{ content = [ viewModalContent state.longContent ]
|
||||
, footer =
|
||||
[ Button.button "Continue"
|
||||
[ firstButtonStyle
|
||||
, Button.onClick ForceClose
|
||||
, Button.custom (autofocusElement :: lastFocusableElement)
|
||||
, Button.large
|
||||
]
|
||||
]
|
||||
}
|
||||
Modal.MultipleFocusableElements <|
|
||||
\modalOptions ->
|
||||
{ content =
|
||||
[ modalOptions.closeButton modalOptions.firstFocusableElement
|
||||
, viewModalContent settings.longContent
|
||||
]
|
||||
)
|
||||
, footer =
|
||||
[ Button.button "Continue"
|
||||
[ firstButtonStyle
|
||||
, Button.onClick ForceClose
|
||||
, Button.custom (modalOptions.autofocusElement :: modalOptions.lastFocusableElement)
|
||||
, Button.large
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
( False, True, True ) ->
|
||||
Modal.multipleFocusableElementView
|
||||
(\{ firstFocusableElement, autofocusElement, lastFocusableElement } ->
|
||||
div []
|
||||
[ viewContent
|
||||
{ content = [ viewModalContent state.longContent ]
|
||||
, footer =
|
||||
[ Button.button "Continue"
|
||||
[ firstButtonStyle
|
||||
, Button.onClick ForceClose
|
||||
, Button.custom (autofocusElement :: firstFocusableElement)
|
||||
, Button.large
|
||||
]
|
||||
, ClickableText.button "Close"
|
||||
[ ClickableText.onClick ForceClose
|
||||
, ClickableText.large
|
||||
, ClickableText.custom lastFocusableElement
|
||||
, ClickableText.css [ Css.marginTop (Css.px 12) ]
|
||||
]
|
||||
]
|
||||
}
|
||||
Modal.MultipleFocusableElements <|
|
||||
\modalOptions ->
|
||||
{ content = [ viewModalContent settings.longContent ]
|
||||
, footer =
|
||||
[ Button.button "Continue"
|
||||
[ firstButtonStyle
|
||||
, Button.onClick ForceClose
|
||||
, Button.custom (modalOptions.autofocusElement :: modalOptions.firstFocusableElement)
|
||||
, Button.large
|
||||
]
|
||||
, ClickableText.button "Close"
|
||||
[ ClickableText.onClick ForceClose
|
||||
, ClickableText.large
|
||||
, ClickableText.custom modalOptions.lastFocusableElement
|
||||
, ClickableText.css [ Css.marginTop (Css.px 12) ]
|
||||
]
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
( False, False, True ) ->
|
||||
Modal.onlyFocusableElementView
|
||||
Modal.OneFocusableElement
|
||||
(\{ onlyFocusableElement } ->
|
||||
div []
|
||||
[ viewContent
|
||||
{ content = [ viewModalContent state.longContent ]
|
||||
, footer =
|
||||
[ ClickableText.button "Close"
|
||||
[ ClickableText.onClick ForceClose
|
||||
, ClickableText.large
|
||||
, ClickableText.custom onlyFocusableElement
|
||||
, ClickableText.css [ Css.marginTop (Css.px 12) ]
|
||||
]
|
||||
]
|
||||
}
|
||||
{ content = [ viewModalContent settings.longContent ]
|
||||
, footer =
|
||||
[ ClickableText.button "Close"
|
||||
[ ClickableText.onClick ForceClose
|
||||
, ClickableText.large
|
||||
, ClickableText.custom onlyFocusableElement
|
||||
, ClickableText.css [ Css.marginTop (Css.px 12) ]
|
||||
]
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
( False, True, False ) ->
|
||||
Modal.onlyFocusableElementView
|
||||
Modal.OneFocusableElement
|
||||
(\{ onlyFocusableElement } ->
|
||||
div []
|
||||
[ viewContent
|
||||
{ content = [ viewModalContent state.longContent ]
|
||||
, footer =
|
||||
[ Button.button "Continue"
|
||||
[ firstButtonStyle
|
||||
, Button.onClick ForceClose
|
||||
, Button.custom onlyFocusableElement
|
||||
, Button.large
|
||||
]
|
||||
]
|
||||
}
|
||||
{ content = [ viewModalContent settings.longContent ]
|
||||
, footer =
|
||||
[ Button.button "Continue"
|
||||
[ firstButtonStyle
|
||||
, Button.onClick ForceClose
|
||||
, Button.custom onlyFocusableElement
|
||||
, Button.large
|
||||
]
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
( False, False, False ) ->
|
||||
Modal.onlyFocusableElementView
|
||||
Modal.OneFocusableElement
|
||||
(\_ ->
|
||||
div []
|
||||
[ viewContent
|
||||
{ content = [ viewModalContent state.longContent ]
|
||||
, footer = []
|
||||
}
|
||||
]
|
||||
{ content = [ viewModalContent settings.longContent ]
|
||||
, footer = []
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@ -276,13 +267,13 @@ viewModalContent longContent =
|
||||
]
|
||||
|
||||
|
||||
viewSettings : State -> Html Msg
|
||||
viewSettings state =
|
||||
viewSettings : Settings -> Html Msg
|
||||
viewSettings settings =
|
||||
div []
|
||||
[ Checkbox.viewWithLabel
|
||||
{ identifier = "visible-title"
|
||||
, label = "Visible title"
|
||||
, selected = Checkbox.selectedFromBool state.visibleTitle
|
||||
, selected = Checkbox.selectedFromBool settings.visibleTitle
|
||||
, setterMsg = SetVisibleTitle
|
||||
, disabled = False
|
||||
, theme = Checkbox.Square
|
||||
@ -290,7 +281,7 @@ viewSettings state =
|
||||
, Checkbox.viewWithLabel
|
||||
{ identifier = "show-x"
|
||||
, label = "Show X button"
|
||||
, selected = Checkbox.selectedFromBool state.showX
|
||||
, selected = Checkbox.selectedFromBool settings.showX
|
||||
, setterMsg = SetShowX
|
||||
, disabled = False
|
||||
, theme = Checkbox.Square
|
||||
@ -298,7 +289,7 @@ viewSettings state =
|
||||
, Checkbox.viewWithLabel
|
||||
{ identifier = "show-continue"
|
||||
, label = "Show main button"
|
||||
, selected = Checkbox.selectedFromBool state.showContinue
|
||||
, selected = Checkbox.selectedFromBool settings.showContinue
|
||||
, setterMsg = SetShowContinue
|
||||
, disabled = False
|
||||
, theme = Checkbox.Square
|
||||
@ -306,7 +297,7 @@ viewSettings state =
|
||||
, Checkbox.viewWithLabel
|
||||
{ identifier = "show-secondary"
|
||||
, label = "Show secondary button"
|
||||
, selected = Checkbox.selectedFromBool state.showSecondary
|
||||
, selected = Checkbox.selectedFromBool settings.showSecondary
|
||||
, setterMsg = SetShowSecondary
|
||||
, disabled = False
|
||||
, theme = Checkbox.Square
|
||||
@ -314,7 +305,7 @@ viewSettings state =
|
||||
, Checkbox.viewWithLabel
|
||||
{ identifier = "dismiss-on-click"
|
||||
, label = "Dismiss on ESC and on backdrop click"
|
||||
, selected = Checkbox.selectedFromBool state.dismissOnEscAndOverlayClick
|
||||
, selected = Checkbox.selectedFromBool settings.dismissOnEscAndOverlayClick
|
||||
, setterMsg = SetDismissOnEscAndOverlayClick
|
||||
, disabled = False
|
||||
, theme = Checkbox.Square
|
||||
@ -322,7 +313,7 @@ viewSettings state =
|
||||
, Checkbox.viewWithLabel
|
||||
{ identifier = "long-content"
|
||||
, label = "Display longer content"
|
||||
, selected = Checkbox.selectedFromBool state.longContent
|
||||
, selected = Checkbox.selectedFromBool settings.longContent
|
||||
, setterMsg = SetLongContent
|
||||
, disabled = False
|
||||
, theme = Checkbox.Square
|
||||
@ -332,8 +323,7 @@ viewSettings state =
|
||||
|
||||
{-| -}
|
||||
type Msg
|
||||
= InfoModalMsg Modal.Msg
|
||||
| WarningModalMsg Modal.Msg
|
||||
= ModalMsg Modal.Msg
|
||||
| ForceClose
|
||||
| SetVisibleTitle Bool
|
||||
| SetShowX Bool
|
||||
@ -347,55 +337,45 @@ type Msg
|
||||
update : Msg -> State -> ( State, Cmd Msg )
|
||||
update msg state =
|
||||
let
|
||||
settings =
|
||||
state.settings
|
||||
|
||||
updateConfig =
|
||||
{ dismissOnEscAndOverlayClick = state.dismissOnEscAndOverlayClick }
|
||||
{ dismissOnEscAndOverlayClick = settings.dismissOnEscAndOverlayClick }
|
||||
in
|
||||
case msg of
|
||||
InfoModalMsg modalMsg ->
|
||||
case Modal.update updateConfig modalMsg state.infoModal of
|
||||
ModalMsg modalMsg ->
|
||||
case Modal.update updateConfig modalMsg state.state of
|
||||
( newState, cmds ) ->
|
||||
( { state | infoModal = newState }
|
||||
, Cmd.map InfoModalMsg cmds
|
||||
)
|
||||
|
||||
WarningModalMsg modalMsg ->
|
||||
case Modal.update updateConfig modalMsg state.warningModal of
|
||||
( newState, cmds ) ->
|
||||
( { state | warningModal = newState }
|
||||
, Cmd.map WarningModalMsg cmds
|
||||
( { state | state = newState }
|
||||
, Cmd.map ModalMsg cmds
|
||||
)
|
||||
|
||||
ForceClose ->
|
||||
( { state
|
||||
| infoModal = Modal.init
|
||||
, warningModal = Modal.init
|
||||
}
|
||||
( { state | state = Modal.init }
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
SetVisibleTitle value ->
|
||||
( { state | visibleTitle = value }, Cmd.none )
|
||||
( { state | settings = { settings | visibleTitle = value } }, Cmd.none )
|
||||
|
||||
SetShowX value ->
|
||||
( { state | showX = value }, Cmd.none )
|
||||
( { state | settings = { settings | showX = value } }, Cmd.none )
|
||||
|
||||
SetShowContinue value ->
|
||||
( { state | showContinue = value }, Cmd.none )
|
||||
( { state | settings = { settings | showContinue = value } }, Cmd.none )
|
||||
|
||||
SetShowSecondary value ->
|
||||
( { state | showSecondary = value }, Cmd.none )
|
||||
( { state | settings = { settings | showSecondary = value } }, Cmd.none )
|
||||
|
||||
SetDismissOnEscAndOverlayClick value ->
|
||||
( { state | dismissOnEscAndOverlayClick = value }, Cmd.none )
|
||||
( { state | settings = { settings | dismissOnEscAndOverlayClick = value } }, Cmd.none )
|
||||
|
||||
SetLongContent value ->
|
||||
( { state | longContent = value }, Cmd.none )
|
||||
( { state | settings = { settings | longContent = value } }, Cmd.none )
|
||||
|
||||
|
||||
{-| -}
|
||||
subscriptions : State -> Sub Msg
|
||||
subscriptions model =
|
||||
Sub.batch
|
||||
[ Sub.map InfoModalMsg (Modal.subscriptions model.infoModal)
|
||||
, Sub.map WarningModalMsg (Modal.subscriptions model.warningModal)
|
||||
]
|
||||
Sub.map ModalMsg (Modal.subscriptions model.state)
|
||||
|
Loading…
Reference in New Issue
Block a user