Merge remote-tracking branch 'origin/master' into callout

This commit is contained in:
Brian Hicks 2019-08-20 14:30:17 -05:00
commit 9c8ef672ca
4 changed files with 909 additions and 92 deletions

View File

@ -49,6 +49,7 @@
"Nri.Ui.Modal.V4",
"Nri.Ui.Modal.V5",
"Nri.Ui.Modal.V6",
"Nri.Ui.Modal.V7",
"Nri.Ui.Outline.V2",
"Nri.Ui.Page.V2",
"Nri.Ui.Page.V3",

View File

@ -0,0 +1,381 @@
module Accessibility.Modal.Copy exposing
( Model, init, subscriptions
, update, Msg, close, open
, view
, Attribute
, multipleFocusableElementView, onlyFocusableElementView
, autofocusOnLastElement
, overlayColor, custom, titleStyles
)
{-| COPIED from <https://package.elm-lang.org/packages/tesk9/modal/latest/> for
clean monolith upgrades. Remove this and go back to using tesk9/modal when possible!
import Accessibility.Modal as Modal
import Html.Styled exposing (..)
import Html.Styled.Events exposing (onClick)
view : Html Modal.Msg
view =
Modal.view identity
"Example modal"
[ Modal.onlyFocusableElementView
(\onlyFocusableElementAttributes ->
div []
[ text "Welcome to this modal! I'm so happy to have you here with me."
, button
(onClick Modal.close :: onlyFocusableElementAttributes)
[ text "Close Modal" ]
]
)
]
modal
@docs Model, init, subscriptions
@docs update, Msg, close, open
@docs view
@docs Attribute
@docs multipleFocusableElementView, onlyFocusableElementView
@docs autofocusOnLastElement
@docs overlayColor, custom, titleStyles
-}
import Accessibility.Styled exposing (..)
import Accessibility.Styled.Aria as Aria
import Accessibility.Styled.Key as Key
import Accessibility.Styled.Role as Role
import Browser
import Browser.Dom as Dom
import Browser.Events
import Css exposing (..)
import Html.Styled as Root
import Html.Styled.Attributes as Attributes exposing (css, id)
import Html.Styled.Events exposing (onClick)
import Task
{-| -}
type Model
= Opened String
| Closed
{-| -}
init : Model
init =
Closed
type By
= EscapeKey
| OverlayClick
| Other
{-| -}
type Msg
= OpenModal String
| CloseModal By
| Focus String
| Focused (Result Dom.Error ())
{-| -}
update : { dismissOnEscAndOverlayClick : Bool } -> Msg -> Model -> ( Model, Cmd Msg )
update { dismissOnEscAndOverlayClick } msg model =
case msg of
OpenModal returnFocusTo ->
( Opened returnFocusTo
, Dom.focus autofocusId
|> Task.onError (\_ -> Dom.focus firstId)
|> Task.attempt Focused
)
CloseModal by ->
let
closeModal returnFocusTo =
( Closed, Task.attempt Focused (Dom.focus returnFocusTo) )
in
case ( model, by, dismissOnEscAndOverlayClick ) of
( Opened returnFocusTo, _, True ) ->
closeModal returnFocusTo
( Opened returnFocusTo, Other, False ) ->
closeModal returnFocusTo
_ ->
( model, Cmd.none )
Focus id ->
( model, Task.attempt Focused (Dom.focus id) )
Focused _ ->
( model, Cmd.none )
type Autofocus
= Default
| Last
type alias Config msg =
{ overlayColor : Color
, wrapMsg : Msg -> msg
, modalStyle : Style
, titleString : String
, titleStyles : List Style
, autofocusOn : Autofocus
, content :
{ onlyFocusableElement : List (Accessibility.Styled.Attribute msg)
, firstFocusableElement : List (Accessibility.Styled.Attribute msg)
, lastFocusableElement : List (Accessibility.Styled.Attribute msg)
, autofocusOn : Accessibility.Styled.Attribute msg
}
-> Html msg
}
defaults : (Msg -> msg) -> String -> Config msg
defaults wrapMsg t =
{ overlayColor = rgba 128 0 70 0.7
, wrapMsg = wrapMsg
, modalStyle =
batch
[ backgroundColor (rgb 255 255 255)
, borderRadius (px 8)
, border3 (px 2) solid (rgb 127 0 127)
, margin2 (px 80) auto
, padding (px 20)
, maxWidth (px 600)
, minHeight (vh 40)
]
, titleString = t
, titleStyles = []
, autofocusOn = Default
, content = \_ -> text ""
}
{-| -}
type Attribute msg
= Attribute (Config msg -> Config msg)
{-| -}
overlayColor : Color -> Attribute msg
overlayColor color =
Attribute (\config -> { config | overlayColor = color })
{-| -}
title : String -> Attribute msg
title t =
Attribute (\config -> { config | titleString = t })
{-| -}
titleStyles : List Style -> Attribute msg
titleStyles styles =
Attribute (\config -> { config | titleStyles = styles })
{-| -}
custom : List Style -> Attribute msg
custom styles =
Attribute (\config -> { config | modalStyle = batch styles })
{-| -}
autofocusOnLastElement : Attribute msg
autofocusOnLastElement =
Attribute (\config -> { config | autofocusOn = Last })
{-| -}
onlyFocusableElementView : (List (Accessibility.Styled.Attribute msg) -> Html msg) -> Attribute msg
onlyFocusableElementView v =
Attribute (\config -> { config | content = \{ onlyFocusableElement } -> v onlyFocusableElement })
{-| -}
multipleFocusableElementView :
({ firstFocusableElement : List (Accessibility.Styled.Attribute msg)
, lastFocusableElement : List (Accessibility.Styled.Attribute msg)
, autofocusElement : Accessibility.Styled.Attribute msg
}
-> Html msg
)
-> Attribute msg
multipleFocusableElementView v =
Attribute
(\config ->
{ config
| content =
\{ firstFocusableElement, lastFocusableElement, autofocusOn } ->
v
{ firstFocusableElement = firstFocusableElement
, lastFocusableElement = lastFocusableElement
, autofocusElement = autofocusOn
}
}
)
{-| -}
view :
(Msg -> msg)
-> String
-> List (Attribute msg)
-> Model
-> Html msg
view wrapMsg ti attributes model =
let
config =
List.foldl (\(Attribute f) acc -> f acc) (defaults wrapMsg ti) attributes
in
case model of
Opened _ ->
div
[ css
[ position fixed
, top zero
, left zero
, width (pct 100)
, height (pct 100)
]
]
[ viewBackdrop config
, div
[ css [ position relative, config.modalStyle ] ]
[ viewModal config ]
, Root.node "style" [] [ Root.text "body {overflow: hidden;} " ]
]
Closed ->
text ""
viewBackdrop :
{ a | wrapMsg : Msg -> msg, overlayColor : Color }
-> Html msg
viewBackdrop config =
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
-- well via the ESC key, so imo it's fine to have this div
-- be clickable but not focusable.
[ css
[ position absolute
, width (pct 100)
, height (pct 100)
, backgroundColor config.overlayColor
]
, onClick (config.wrapMsg (CloseModal OverlayClick))
]
[]
viewModal : Config msg -> Html msg
viewModal config =
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
}
_ ->
{ 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
}
)
]
modalTitleId : String
modalTitleId =
"modal__title"
firstId : String
firstId =
"modal__first-focusable-element"
lastId : String
lastId =
"modal__last-focusable-element"
autofocusId : String
autofocusId =
"modal__autofocus-element"
{-| Pass the id of the element that should receive focus when the modal closes.
-}
open : String -> Msg
open =
OpenModal
{-| -}
close : Msg
close =
CloseModal Other
{-| -}
subscriptions : Model -> Sub Msg
subscriptions model =
case model of
Opened _ ->
Browser.Events.onKeyDown (Key.escape (CloseModal EscapeKey))
Closed ->
Sub.none

352
src/Nri/Ui/Modal/V7.elm Normal file
View File

@ -0,0 +1,352 @@
module Nri.Ui.Modal.V7 exposing
( Model, init
, Msg, update, subscriptions
, open, close
, info, warning
, viewContent, viewFooter
, Attribute
, multipleFocusableElementView, onlyFocusableElementView
, autofocusOnLastElement
, closeButton
)
{-| Changes from V6:
- Modal starts a new stacking context, to prevent non-normal-flow elements from showing through the backdrop
- Scrollable content shows a shadow
```
import Html.Styled exposing (..)
import Nri.Ui.Button.V9 as Button
import Nri.Ui.Modal.V7 as Modal
type Msg
= ModalMsg Modal.Msg
| DoSomthing
view : Modal.Model -> Html Msg
view state =
Modal.info
{ title = "Modal Header"
, visibleTitle = True
, wrapMsg = ModalMsg
}
[ Modal.onlyFocusableElementView
(\{ onlyFocusableElement } ->
div []
[ Modal.viewContent [ text "Content goes here!" ]
, Modal.viewFooter
[ Button.button "Continue"
[ Button.primary
, Button.onClick DoSomthing
, Button.custom onlyFocusableElement
]
, text "`onlyFocusableElement` will trap the focus on the 'Continue' button."
]
]
)
]
state
subscriptions : Modal.Model -> Sub Msg
subscriptions state =
Modal.subscriptions state
view init
--> text "" -- a closed modal
```
## State and updates
@docs Model, init
@docs Msg, update, subscriptions
@docs open, close
## Views
### Modals
@docs info, warning
### View containers
@docs viewContent, viewFooter
### Attributes
@docs Attribute
@docs multipleFocusableElementView, onlyFocusableElementView
@docs autofocusOnLastElement
## X icon
@docs closeButton
-}
import Accessibility.Modal.Copy as Modal
import Accessibility.Style
import Accessibility.Styled as Html exposing (..)
import Accessibility.Styled.Widget as Widget
import Color
import Color.Transparent
import Css
import Css.Global
import Html as Root
import Html.Attributes exposing (style)
import Html.Styled.Attributes as Attributes exposing (css)
import Html.Styled.Events exposing (onClick)
import Nri.Ui
import Nri.Ui.Colors.Extra
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Fonts.V1 as Fonts
import Nri.Ui.SpriteSheet
import Nri.Ui.Svg.V1
{-| -}
type alias Model =
Modal.Model
{-| -}
init : Model
init =
Modal.init
{-| -}
type alias Msg =
Modal.Msg
{-| Include the subscription if you want the modal to dismiss on `Esc`.
-}
subscriptions : Model -> Sub Msg
subscriptions =
Modal.subscriptions
{-| -}
update : { dismissOnEscAndOverlayClick : Bool } -> Msg -> Model -> ( Model, Cmd Msg )
update config msg model =
Modal.update config msg model
{-| -}
close : Msg
close =
Modal.close
{-| Pass the id of the element that focus should return to when the modal closes.
-}
open : String -> Msg
open =
Modal.open
{-| -}
info :
{ visibleTitle : Bool
, title : String
, wrapMsg : Msg -> msg
}
-> List (Modal.Attribute msg)
-> Model
-> Html msg
info config model =
view { overlayColor = Colors.navy, titleColor = Colors.navy } config model
{-| -}
warning :
{ visibleTitle : Bool
, title : String
, wrapMsg : Msg -> msg
}
-> List (Modal.Attribute msg)
-> Model
-> Html msg
warning config model =
view { overlayColor = Colors.gray20, titleColor = Colors.red } config model
{-| -}
type alias Attribute msg =
Modal.Attribute msg
{-| -}
autofocusOnLastElement : Modal.Attribute msg
autofocusOnLastElement =
Modal.autofocusOnLastElement
{-| -}
multipleFocusableElementView :
({ firstFocusableElement : List (Html.Attribute msg)
, lastFocusableElement : List (Html.Attribute msg)
, autofocusElement : Html.Attribute msg
}
-> Html msg
)
-> Modal.Attribute msg
multipleFocusableElementView =
Modal.multipleFocusableElementView
{-| -}
onlyFocusableElementView : (List (Html.Attribute msg) -> Html msg) -> Modal.Attribute msg
onlyFocusableElementView =
Modal.onlyFocusableElementView
view :
{ overlayColor : Css.Color, titleColor : Css.Color }
->
{ visibleTitle : Bool
, title : String
, wrapMsg : Msg -> msg
}
-> List (Modal.Attribute msg)
-> Model
-> Html msg
view { overlayColor, titleColor } config attributes model =
Modal.view config.wrapMsg
config.title
([ Modal.overlayColor (Nri.Ui.Colors.Extra.withAlpha 0.9 overlayColor)
, Modal.titleStyles
(if config.visibleTitle then
titleStyles titleColor
else
invisibleTitleStyles
)
, Modal.custom modalStyles
]
++ attributes
)
model
|> List.singleton
|> div [ css [ Css.position Css.relative, Css.zIndex (Css.int 1) ] ]
modalStyles : List Css.Style
modalStyles =
[ Css.property "width" "600px"
, Css.property "padding" "40px 0 40px 0"
, Css.property "margin" "75px auto"
, Css.property "background-color" ((Color.toRGBString << Nri.Ui.Colors.Extra.fromCssColor) Colors.white)
, Css.property "border-radius" "20px"
, Css.property "box-shadow" "0 1px 10px 0 rgba(0, 0, 0, 0.35)"
, Css.property "position" "relative" -- required for closeButtonContainer
]
titleStyles : Css.Color -> List Css.Style
titleStyles color =
[ Fonts.baseFont
, Css.property "font-weight" "700"
, Css.property "line-height" "27px"
, Css.property "margin" "0 49px"
, Css.property "font-size" "20px"
, Css.property "text-align" "center"
, Css.property "color" ((Color.toRGBString << Nri.Ui.Colors.Extra.fromCssColor) color)
]
invisibleTitleStyles : List Css.Style
invisibleTitleStyles =
[ Css.property "property" "clip rect(1px, 1px, 1px, 1px)"
, Css.property "position" "absolute"
, Css.property "height" "1px"
, Css.property "width" "1px"
, Css.property "overflow" "hidden"
, Css.property "margin" "-1px"
, Css.property "padding" "0"
, Css.property "border" "0"
]
{-| -}
viewContent : List (Html msg) -> Html msg
viewContent =
Nri.Ui.styled div
"modal-content"
[ Css.overflowY Css.auto
, Css.minHeight (Css.px 150)
, Css.maxHeight (Css.calc (Css.vh 100) Css.minus (Css.px 360))
, Css.padding2 (Css.px 30) (Css.px 40)
, Css.width (Css.pct 100)
, Css.boxSizing Css.borderBox
-- Shadows for indicating that the content is scrollable
, Css.property "background"
"""
/* TOP shadow */
top linear-gradient(to top, rgb(255, 255, 255), rgb(255, 255, 255)) local,
top linear-gradient(to top, rgba(255, 255, 255, 0), rgba(0, 0, 0, 0.15)) scroll,
/* BOTTOM shadow */
bottom linear-gradient(to bottom, rgb(255, 255, 255), rgb(255, 255, 255)) local,
bottom linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(0, 0, 0, 0.15)) scroll
"""
, Css.backgroundSize2 (Css.pct 100) (Css.px 10)
, Css.backgroundRepeat Css.noRepeat
]
[]
{-| -}
viewFooter : List (Html msg) -> Html msg
viewFooter =
Nri.Ui.styled div
"modal-footer"
[ Css.alignItems Css.center
, Css.displayFlex
, Css.flexDirection Css.column
, Css.flexGrow (Css.int 2)
, Css.flexWrap Css.noWrap
, Css.margin4 (Css.px 20) Css.zero Css.zero Css.zero
, Css.width (Css.pct 100)
]
[]
--BUTTONS
{-| -}
closeButton : (Msg -> msg) -> List (Html.Attribute msg) -> Html msg
closeButton wrapMsg focusableElementAttrs =
Nri.Ui.styled button
"close-button-container"
[ Css.position Css.absolute
, Css.top Css.zero
, Css.right Css.zero
, Css.padding (Css.px 25)
, Css.borderWidth Css.zero
, Css.width (Css.px 75)
, Css.backgroundColor Css.transparent
, Css.cursor Css.pointer
, Css.color Colors.azure
, Css.hover [ Css.color Colors.azureDark ]
, Css.property "transition" "color 0.1s"
]
(Widget.label "Close modal"
:: Attributes.map wrapMsg (onClick Modal.close)
:: focusableElementAttrs
)
[ Nri.Ui.Svg.V1.toHtml Nri.Ui.SpriteSheet.xSvg
]

View File

@ -6,7 +6,7 @@ module Examples.Modal exposing (Msg, State, example, init, update, subscriptions
-}
import Accessibility.Styled as Html exposing (Html, div, h3, h4, p, text)
import Accessibility.Styled as Html exposing (Html, div, h3, h4, p, span, text)
import Css exposing (..)
import Css.Global
import Html as Root
@ -14,8 +14,10 @@ import Html.Styled.Attributes exposing (css)
import ModuleExample exposing (Category(..), ModuleExample)
import Nri.Ui.Button.V9 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.Modal.V6 as Modal
import Nri.Ui.Modal.V7 as Modal
import Nri.Ui.Text.V4 as Text
{-| -}
@ -27,6 +29,7 @@ type alias State =
, showContinue : Bool
, showSecondary : Bool
, dismissOnEscAndOverlayClick : Bool
, longContent : Bool
}
@ -38,18 +41,20 @@ init =
, visibleTitle = True
, showX = True
, showContinue = True
, showSecondary = False
, showSecondary = True
, dismissOnEscAndOverlayClick = True
, longContent = True
}
{-| -}
example : (Msg -> msg) -> State -> ModuleExample msg
example parentMessage state =
{ name = "Nri.Ui.Modal.V6"
{ name = "Nri.Ui.Modal.V7"
, category = Modals
, content =
[ Button.button "Launch Info Modal"
[ viewSettings state
, Button.button "Launch Info Modal"
[ Button.onClick (InfoModalMsg (Modal.open "launch-info-modal"))
, Button.custom
[ Html.Styled.Attributes.id "launch-info-modal"
@ -68,23 +73,15 @@ example parentMessage state =
{ title = "Modal.info"
, visibleTitle = state.visibleTitle
, wrapMsg = InfoModalMsg
, content =
viewContent state
InfoModalMsg
Button.primary
Button.secondary
}
(viewContent state InfoModalMsg Button.primary)
state.infoModal
, Modal.warning
{ title = "Modal.warning"
, visibleTitle = state.visibleTitle
, wrapMsg = WarningModalMsg
, content =
viewContent state
WarningModalMsg
Button.danger
Button.secondary
}
(viewContent state WarningModalMsg Button.danger)
state.warningModal
]
|> List.map (Html.map parentMessage)
@ -95,105 +92,179 @@ viewContent :
State
-> (Modal.Msg -> Msg)
-> Button.Attribute Msg
-> Button.Attribute Msg
-> Modal.FocusableElementAttrs Msg
-> Html Msg
viewContent state wrapMsg firstButtonStyle secondButtonStyle focusableElementAttrs =
-> List (Modal.Attribute Msg)
viewContent state wrapMsg firstButtonStyle =
case ( state.showX, state.showContinue, state.showSecondary ) of
( True, True, True ) ->
div []
[ Modal.closeButton wrapMsg focusableElementAttrs.firstFocusableElement
, Modal.viewContent [ viewSettings state ]
, Modal.viewFooter
[ Button.button "Continue"
[ firstButtonStyle
, Button.onClick ForceClose
[ Modal.multipleFocusableElementView
(\focusableElementAttrs ->
div []
[ Modal.closeButton wrapMsg focusableElementAttrs.firstFocusableElement
, Modal.viewContent [ viewModalContent state.longContent ]
, Modal.viewFooter
[ Button.button "Continue"
[ firstButtonStyle
, Button.onClick ForceClose
, Button.large
, Button.custom [ focusableElementAttrs.autofocusElement ]
]
, ClickableText.button "Close"
[ ClickableText.onClick ForceClose
, ClickableText.large
, ClickableText.custom
(css [ Css.marginTop (Css.px 20) ]
:: focusableElementAttrs.lastFocusableElement
)
]
]
]
, Button.button "Close"
[ secondButtonStyle
, Button.onClick ForceClose
, Button.custom focusableElementAttrs.lastFocusableElement
]
]
]
)
]
( True, False, True ) ->
div []
[ Modal.closeButton wrapMsg focusableElementAttrs.firstFocusableElement
, Modal.viewContent [ viewSettings state ]
, Modal.viewFooter
[ Button.button "Close"
[ secondButtonStyle
, Button.onClick ForceClose
, Button.custom focusableElementAttrs.lastFocusableElement
[ Modal.multipleFocusableElementView
(\focusableElementAttrs ->
div []
[ Modal.closeButton wrapMsg focusableElementAttrs.firstFocusableElement
, Modal.viewContent [ viewModalContent state.longContent ]
, Modal.viewFooter
[ ClickableText.button "Close"
[ ClickableText.onClick ForceClose
, ClickableText.large
, ClickableText.custom
(css [ Css.marginTop (Css.px 20) ]
:: focusableElementAttrs.lastFocusableElement
)
]
]
]
]
]
)
]
( True, False, False ) ->
div []
[ Modal.closeButton wrapMsg focusableElementAttrs.firstFocusableElement
, Modal.viewContent [ viewSettings state ]
]
[ Modal.multipleFocusableElementView
(\focusableElementAttrs ->
div []
[ Modal.closeButton wrapMsg focusableElementAttrs.firstFocusableElement
, Modal.viewContent [ viewModalContent state.longContent ]
]
)
]
( True, True, False ) ->
div []
[ Modal.closeButton wrapMsg focusableElementAttrs.firstFocusableElement
, Modal.viewContent [ viewSettings state ]
, Modal.viewFooter
[ Button.button "Continue"
[ firstButtonStyle
, Button.onClick ForceClose
, Button.custom focusableElementAttrs.lastFocusableElement
[ Modal.autofocusOnLastElement
, Modal.multipleFocusableElementView
(\focusableElementAttrs ->
div []
[ Modal.closeButton wrapMsg focusableElementAttrs.firstFocusableElement
, Modal.viewContent [ viewModalContent state.longContent ]
, Modal.viewFooter
[ Button.button "Continue"
[ firstButtonStyle
, Button.onClick ForceClose
, Button.custom focusableElementAttrs.lastFocusableElement
, Button.large
]
]
]
]
]
)
]
( False, True, True ) ->
div []
[ Modal.viewContent [ viewSettings state ]
, Modal.viewFooter
[ Button.button "Continue"
[ firstButtonStyle
, Button.onClick ForceClose
, Button.custom focusableElementAttrs.firstFocusableElement
[ Modal.multipleFocusableElementView
(\focusableElementAttrs ->
div []
[ Modal.viewContent [ viewModalContent state.longContent ]
, Modal.viewFooter
[ Button.button "Continue"
[ firstButtonStyle
, Button.onClick ForceClose
, Button.custom focusableElementAttrs.firstFocusableElement
, Button.large
]
, ClickableText.button "Close"
[ ClickableText.onClick ForceClose
, ClickableText.large
, ClickableText.custom
(css [ Css.marginTop (Css.px 20) ]
:: focusableElementAttrs.lastFocusableElement
)
]
]
]
, Button.button "Close"
[ secondButtonStyle
, Button.onClick ForceClose
, Button.custom focusableElementAttrs.lastFocusableElement
]
]
]
)
]
( False, False, True ) ->
div []
[ Modal.viewContent [ viewSettings state ]
, Modal.viewFooter
[ Button.button "Close"
[ secondButtonStyle
, Button.onClick ForceClose
, Button.custom focusableElementAttrs.lastFocusableElement
[ Modal.autofocusOnLastElement
, Modal.multipleFocusableElementView
(\focusableElementAttrs ->
div []
[ Modal.viewContent [ viewModalContent state.longContent ]
, Modal.viewFooter
[ ClickableText.button "Close"
[ ClickableText.onClick ForceClose
, ClickableText.large
, ClickableText.custom
(css
[ Css.marginTop
(Css.px 20)
]
:: focusableElementAttrs.lastFocusableElement
)
]
]
]
]
]
)
]
( False, True, False ) ->
div []
[ Modal.viewContent [ viewSettings state ]
, Modal.viewFooter
[ Button.button "Continue"
[ firstButtonStyle
, Button.onClick ForceClose
, Button.custom focusableElementAttrs.lastFocusableElement
[ Modal.autofocusOnLastElement
, Modal.multipleFocusableElementView
(\focusableElementAttrs ->
div []
[ Modal.viewContent [ viewModalContent state.longContent ]
, Modal.viewFooter
[ Button.button "Continue"
[ firstButtonStyle
, Button.onClick ForceClose
, Button.custom [ focusableElementAttrs.autofocusElement ]
, Button.large
]
]
]
]
]
)
]
( False, False, False ) ->
div []
[ Modal.viewContent [ viewSettings state ]
]
[ Modal.multipleFocusableElementView
(\focusableElementAttrs ->
div []
[ Modal.viewContent [ viewModalContent state.longContent ]
]
)
]
viewModalContent : Bool -> Html msg
viewModalContent longContent =
Text.mediumBody
[ span [ css [ whiteSpace preLine ] ]
[ if longContent then
"""
Soufflé pastry chocolate cake danish muffin. Candy wafer pastry ice cream cheesecake toffee cookie cake carrot cake. Macaroon pie jujubes gummies cookie pie. Gummi bears brownie pastry carrot cake cotton candy. Jelly-o sweet roll biscuit cake soufflé lemon drops tiramisu marshmallow macaroon. Chocolate jelly halvah marzipan macaroon cupcake sweet cheesecake carrot cake.
Sesame snaps pastry muffin cookie. Powder powder sweet roll toffee cake icing. Chocolate cake sweet roll gingerbread icing chupa chups sweet roll sesame snaps. Chocolate croissant chupa chups jelly beans toffee. Jujubes sweet wafer marshmallow halvah jelly. Liquorice sesame snaps sweet.
Tootsie roll icing jelly danish ice cream tiramisu sweet roll. Fruitcake ice cream dragée. Bear claw sugar plum sweet jelly beans bonbon dragée tart. Gingerbread chocolate sweet. Apple pie danish toffee sugar plum jelly beans donut. Chocolate cake croissant caramels chocolate bar. Jelly beans caramels toffee chocolate cake liquorice. Toffee pie sugar plum cookie toffee muffin. Marzipan marshmallow marzipan liquorice tiramisu.
"""
|> text
else
"Ice cream tootsie roll donut sweet cookie liquorice sweet donut. Sugar plum danish apple pie sesame snaps chocolate bar biscuit. Caramels macaroon jelly gummies sweet tootsie roll tiramisu apple pie. Dessert chocolate bar lemon drops dragée jelly powder cheesecake chocolate."
|> text
]
]
viewSettings : State -> Html Msg
@ -239,6 +310,14 @@ viewSettings state =
, disabled = False
, theme = Checkbox.Square
}
, Checkbox.viewWithLabel
{ identifier = "long-content"
, label = "Display longer content"
, selected = Checkbox.selectedFromBool state.longContent
, setterMsg = SetLongContent
, disabled = False
, theme = Checkbox.Square
}
]
@ -252,6 +331,7 @@ type Msg
| SetShowContinue Bool
| SetShowSecondary Bool
| SetDismissOnEscAndOverlayClick Bool
| SetLongContent Bool
{-| -}
@ -299,6 +379,9 @@ update msg state =
SetDismissOnEscAndOverlayClick value ->
( { state | dismissOnEscAndOverlayClick = value }, Cmd.none )
SetLongContent value ->
( { state | longContent = value }, Cmd.none )
{-| -}
subscriptions : State -> Sub Msg