mirror of
https://github.com/NoRedInk/noredink-ui.git
synced 2024-11-24 17:02:51 +03:00
commit
aece305611
5
elm.json
5
elm.json
@ -41,6 +41,7 @@
|
||||
"Nri.Ui.Modal.V2",
|
||||
"Nri.Ui.Modal.V3",
|
||||
"Nri.Ui.Modal.V4",
|
||||
"Nri.Ui.Modal.V5",
|
||||
"Nri.Ui.Outline.V2",
|
||||
"Nri.Ui.Page.V2",
|
||||
"Nri.Ui.Page.V3",
|
||||
@ -73,15 +74,17 @@
|
||||
"elm-version": "0.19.0 <= v < 0.20.0",
|
||||
"dependencies": {
|
||||
"avh4/elm-color": "1.0.0 <= v < 2.0.0",
|
||||
"elm/browser": "1.0.1 <= v < 2.0.0",
|
||||
"elm/core": "1.0.0 <= v < 2.0.0",
|
||||
"elm/html": "1.0.0 <= v < 2.0.0",
|
||||
"elm/json": "1.0.0 <= v < 2.0.0",
|
||||
"elm/regex": "1.0.0 <= v < 2.0.0",
|
||||
"elm/svg": "1.0.1 <= v < 2.0.0",
|
||||
"lukewestby/accessible-html-with-css-temp-19": "1.0.0 <= v < 2.0.0",
|
||||
"tesk9/accessible-html-with-css": "2.1.1 <= v < 3.0.0",
|
||||
"pablohirafuji/elm-markdown": "2.0.5 <= v < 3.0.0",
|
||||
"rtfeldman/elm-css": "16.0.0 <= v < 17.0.0",
|
||||
"tesk9/accessible-html": "4.0.0 <= v < 5.0.0",
|
||||
"tesk9/modal": "5.0.1 <= v < 6.0.0",
|
||||
"wernerdegroot/listzipper": "3.1.1 <= v < 4.0.0"
|
||||
},
|
||||
"test-dependencies": {
|
||||
|
@ -73,7 +73,6 @@ import Nri.Ui.AssetPath as AssetPath exposing (Asset)
|
||||
import Nri.Ui.Colors.Extra as ColorsExtra
|
||||
import Nri.Ui.Colors.V1 as Colors
|
||||
import Nri.Ui.Fonts.V1
|
||||
import Nri.Ui.Icon.V4 as Icon exposing (IconType)
|
||||
import Nri.Ui.Svg.V1 as NriSvg exposing (Svg)
|
||||
import Svg
|
||||
import Svg.Attributes
|
||||
|
@ -209,7 +209,6 @@ viewEnabledLabel model labelView icon =
|
||||
, css
|
||||
[ positioning
|
||||
, textStyle
|
||||
, outline none
|
||||
, cursor pointer
|
||||
]
|
||||
]
|
||||
|
421
src/Nri/Ui/Modal/V5.elm
Normal file
421
src/Nri/Ui/Modal/V5.elm
Normal file
@ -0,0 +1,421 @@
|
||||
module Nri.Ui.Modal.V5 exposing
|
||||
( Model, init
|
||||
, Msg, update, subscriptions
|
||||
, info, warning, FocusableElementAttrs
|
||||
, viewContent, viewFooter
|
||||
, launchButton, closeButton
|
||||
, primaryButton, secondaryButton, dangerButton
|
||||
)
|
||||
|
||||
{-| Changes from V4:
|
||||
|
||||
- Remove dependence on Assets
|
||||
- Adds keyboard support (escape key to exit, tabs contained within the modal)
|
||||
|
||||
These changes have required major API changes. Be sure to wire up subscriptions!
|
||||
|
||||
import Html.Styled exposing (..)
|
||||
import Nri.Ui.Modal.V5 as Modal
|
||||
|
||||
view : Modal.State -> Html Msg
|
||||
view state =
|
||||
Modal.info
|
||||
{ title = { title = "Modal Header", visibleTitle = True }
|
||||
, wrapMsg = ModalMsg
|
||||
, content =
|
||||
\{ onlyFocusableElement } ->
|
||||
div []
|
||||
[ Modal.viewContent [ text "Content goes here!" ]
|
||||
, Modal.viewFooter
|
||||
[ Modal.primaryButton DoSomething "Continue" onlyFocusableElement
|
||||
, text "`onlyFocusableElement` will trap the focus on the 'Continue' button."
|
||||
]
|
||||
]
|
||||
}
|
||||
state
|
||||
|
||||
subscriptions : Modal.State -> Sub Msg
|
||||
subscriptions state =
|
||||
Modal.subscriptions state
|
||||
|
||||
|
||||
## State and updates
|
||||
|
||||
@docs Model, init
|
||||
@docs Msg, update, subscriptions
|
||||
|
||||
|
||||
## Views
|
||||
|
||||
|
||||
### Modals
|
||||
|
||||
@docs info, warning, FocusableElementAttrs
|
||||
|
||||
|
||||
### View containers
|
||||
|
||||
@docs viewContent, viewFooter
|
||||
|
||||
|
||||
### Buttons
|
||||
|
||||
@docs launchButton, closeButton
|
||||
@docs primaryButton, secondaryButton, dangerButton
|
||||
|
||||
-}
|
||||
|
||||
import Accessibility.Modal as Modal
|
||||
import Accessibility.Style
|
||||
import Accessibility.Styled as Html exposing (..)
|
||||
import Accessibility.Styled.Style
|
||||
import Accessibility.Styled.Widget as Widget
|
||||
import Color
|
||||
import Css
|
||||
import Css.Global
|
||||
import Html as Root
|
||||
import Html.Attributes exposing (style)
|
||||
import Html.Styled.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
|
||||
|
||||
|
||||
{-| -}
|
||||
type alias FocusableElementAttrs msg =
|
||||
{ onlyFocusableElement : List (Root.Attribute msg)
|
||||
, firstFocusableElement : List (Root.Attribute msg)
|
||||
, lastFocusableElement : List (Root.Attribute msg)
|
||||
}
|
||||
|
||||
|
||||
{-| -}
|
||||
info :
|
||||
{ title : { visibleTitle : Bool, title : String }
|
||||
, content : FocusableElementAttrs msg -> Html msg
|
||||
, wrapMsg : Msg -> msg
|
||||
}
|
||||
-> Model
|
||||
-> Html msg
|
||||
info config model =
|
||||
Modal.view
|
||||
{ overlayColor = toOverlayColor Colors.navy
|
||||
, wrapMsg = config.wrapMsg
|
||||
, modalAttributes = modalStyles
|
||||
, title = viewTitle Colors.navy config.title
|
||||
, content = config.content >> toUnstyled
|
||||
}
|
||||
model
|
||||
|> fromUnstyled
|
||||
|
||||
|
||||
{-| -}
|
||||
warning :
|
||||
{ title : { visibleTitle : Bool, title : String }
|
||||
, content : FocusableElementAttrs msg -> Html msg
|
||||
, wrapMsg : Msg -> msg
|
||||
}
|
||||
-> Model
|
||||
-> Html msg
|
||||
warning config model =
|
||||
Modal.view
|
||||
{ overlayColor = toOverlayColor Colors.gray20
|
||||
, wrapMsg = config.wrapMsg
|
||||
, modalAttributes = modalStyles
|
||||
, title = viewTitle Colors.red config.title
|
||||
, content = config.content >> toUnstyled
|
||||
}
|
||||
model
|
||||
|> fromUnstyled
|
||||
|
||||
|
||||
toOverlayColor : Css.Color -> String
|
||||
toOverlayColor color =
|
||||
toCssString (Nri.Ui.Colors.Extra.withAlpha 0.9 color)
|
||||
|
||||
|
||||
modalStyles : List (Root.Attribute Never)
|
||||
modalStyles =
|
||||
[ style "width" "600px"
|
||||
, style "max-height" "calc(100vh - 100px)"
|
||||
, style "padding" "40px 0 40px 0"
|
||||
, style "margin" "75px auto"
|
||||
, style "background-color" (toCssString Colors.white)
|
||||
, style "border-radius" "20px"
|
||||
, style "box-shadow" "0 1px 10px 0 rgba(0, 0, 0, 0.35)"
|
||||
, style "position" "relative" -- required for closeButtonContainer
|
||||
]
|
||||
|
||||
|
||||
{-| -}
|
||||
viewTitle : Css.Color -> { visibleTitle : Bool, title : String } -> ( String, List (Root.Attribute Never) )
|
||||
viewTitle color { visibleTitle, title } =
|
||||
( title
|
||||
, if visibleTitle then
|
||||
[ style "font-weight" "700"
|
||||
, style "line-height" "27px"
|
||||
, style "margin" "0 49px"
|
||||
, style "font-size" "20px"
|
||||
, style "text-align" "center"
|
||||
, style "color" (toCssString color)
|
||||
]
|
||||
|
||||
else
|
||||
Accessibility.Style.invisible
|
||||
)
|
||||
|
||||
|
||||
toCssString : Css.Color -> String
|
||||
toCssString =
|
||||
Color.toCssString << Nri.Ui.Colors.Extra.toCoreColor
|
||||
|
||||
|
||||
{-| -}
|
||||
viewContent : List (Html msg) -> Html msg
|
||||
viewContent =
|
||||
Nri.Ui.styled div
|
||||
"modal-content"
|
||||
[ Css.overflowY Css.auto
|
||||
, Css.padding2 (Css.px 30) (Css.px 40)
|
||||
, Css.width (Css.pct 100)
|
||||
, Css.minHeight (Css.px 150)
|
||||
, Css.boxSizing Css.borderBox
|
||||
]
|
||||
[]
|
||||
|
||||
|
||||
{-| -}
|
||||
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
|
||||
|
||||
|
||||
{-| -}
|
||||
launchButton : (Msg -> msg) -> List Css.Style -> String -> Html msg
|
||||
launchButton wrapMsg styles label =
|
||||
button
|
||||
(css styles
|
||||
:: List.map Html.Styled.Attributes.fromUnstyled
|
||||
(Modal.openOnClick wrapMsg (String.replace " " "-" label))
|
||||
)
|
||||
[ text label ]
|
||||
|
||||
|
||||
{-| -}
|
||||
closeButton : (Msg -> msg) -> List (Root.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"
|
||||
:: Html.Styled.Attributes.map wrapMsg (onClick Modal.close)
|
||||
:: List.map Html.Styled.Attributes.fromUnstyled focusableElementAttrs
|
||||
)
|
||||
[ Nri.Ui.Svg.V1.toHtml Nri.Ui.SpriteSheet.xSvg
|
||||
]
|
||||
|
||||
|
||||
{-| -}
|
||||
primaryButton : msg -> String -> List (Root.Attribute msg) -> Html msg
|
||||
primaryButton msg label focusableElementAttrs =
|
||||
Nri.Ui.styled button
|
||||
"modal__primary-button"
|
||||
[ buttonStyle, colorStyle PrimaryColors, sizeStyle ]
|
||||
(onClick msg :: List.map Html.Styled.Attributes.fromUnstyled focusableElementAttrs)
|
||||
[ text label ]
|
||||
|
||||
|
||||
{-| -}
|
||||
secondaryButton : msg -> String -> List (Root.Attribute msg) -> Html msg
|
||||
secondaryButton msg label focusableElementAttrs =
|
||||
Nri.Ui.styled button
|
||||
"modal__secondary-button"
|
||||
[ buttonStyle
|
||||
, colorStyle SecondaryColors
|
||||
, Css.fontSize (Css.px 20)
|
||||
, Css.marginTop (Css.px 30)
|
||||
]
|
||||
(onClick msg :: List.map Html.Styled.Attributes.fromUnstyled focusableElementAttrs)
|
||||
[ text label ]
|
||||
|
||||
|
||||
{-| -}
|
||||
dangerButton : msg -> String -> List (Root.Attribute msg) -> Html msg
|
||||
dangerButton msg label focusableElementAttrs =
|
||||
Nri.Ui.styled button
|
||||
"modal__warning-button"
|
||||
[ buttonStyle, colorStyle DangerColors, sizeStyle ]
|
||||
(onClick msg :: List.map Html.Styled.Attributes.fromUnstyled focusableElementAttrs)
|
||||
[ text label ]
|
||||
|
||||
|
||||
buttonStyle : Css.Style
|
||||
buttonStyle =
|
||||
Css.batch
|
||||
[ Css.cursor Css.pointer
|
||||
, -- Specifying the font can and should go away after bootstrap is removed from application.css
|
||||
Fonts.baseFont
|
||||
, Css.textOverflow Css.ellipsis
|
||||
, Css.overflow Css.hidden
|
||||
, Css.textDecoration Css.none
|
||||
, Css.backgroundImage Css.none
|
||||
, Css.textShadow Css.none
|
||||
, Css.property "transition" "background-color 0.2s, color 0.2s, box-shadow 0.2s, border 0.2s, border-width 0s"
|
||||
, Css.boxShadow Css.none
|
||||
, Css.border Css.zero
|
||||
, Css.marginBottom Css.zero
|
||||
, Css.hover [ Css.textDecoration Css.none ]
|
||||
, Css.display Css.inlineFlex
|
||||
, Css.alignItems Css.center
|
||||
, Css.justifyContent Css.center
|
||||
]
|
||||
|
||||
|
||||
type ColorPalette
|
||||
= PrimaryColors
|
||||
| SecondaryColors
|
||||
| DangerColors
|
||||
|
||||
|
||||
colorStyle : ColorPalette -> Css.Style
|
||||
colorStyle colorPalette =
|
||||
let
|
||||
config =
|
||||
case colorPalette of
|
||||
PrimaryColors ->
|
||||
{ background = Colors.azure
|
||||
, hover = Colors.azureDark
|
||||
, text = Colors.white
|
||||
, shadow = Colors.azureDark
|
||||
}
|
||||
|
||||
SecondaryColors ->
|
||||
{ background = Colors.white
|
||||
, hover = Colors.white
|
||||
, text = Colors.azure
|
||||
, shadow = Colors.white
|
||||
}
|
||||
|
||||
DangerColors ->
|
||||
{ background = Colors.red
|
||||
, hover = Colors.redDark
|
||||
, text = Colors.white
|
||||
, shadow = Colors.redDark
|
||||
}
|
||||
in
|
||||
Css.batch
|
||||
[ Css.color config.text
|
||||
, Css.backgroundColor config.background
|
||||
, Css.fontWeight (Css.int 700)
|
||||
, Css.textAlign Css.center
|
||||
, Css.borderStyle Css.none
|
||||
, Css.borderBottomStyle Css.solid
|
||||
, Css.borderBottomColor config.shadow
|
||||
, Css.fontStyle Css.normal
|
||||
, Css.hover
|
||||
[ Css.color config.text
|
||||
, Css.backgroundColor config.hover
|
||||
, Css.disabled [ Css.backgroundColor config.background ]
|
||||
]
|
||||
, Css.visited [ Css.color config.text ]
|
||||
]
|
||||
|
||||
|
||||
sizeStyle : Css.Style
|
||||
sizeStyle =
|
||||
let
|
||||
config =
|
||||
{ fontSize = 20
|
||||
, height = 56
|
||||
, imageHeight = 20
|
||||
, shadowHeight = 4
|
||||
, minWidth = 200
|
||||
}
|
||||
|
||||
sizingAttributes =
|
||||
let
|
||||
verticalPaddingPx =
|
||||
2
|
||||
in
|
||||
[ Css.minHeight (Css.px config.height)
|
||||
, Css.paddingTop (Css.px verticalPaddingPx)
|
||||
, Css.paddingBottom (Css.px verticalPaddingPx)
|
||||
]
|
||||
|
||||
widthAttributes =
|
||||
[ Css.paddingLeft (Css.px 16)
|
||||
, Css.paddingRight (Css.px 16)
|
||||
, Css.minWidth (Css.px 230)
|
||||
]
|
||||
|
||||
lineHeightPx =
|
||||
22
|
||||
in
|
||||
Css.batch
|
||||
[ Css.fontSize (Css.px config.fontSize)
|
||||
, Css.borderRadius (Css.px 8)
|
||||
, Css.lineHeight (Css.px lineHeightPx)
|
||||
, Css.boxSizing Css.borderBox
|
||||
, Css.borderWidth (Css.px 1)
|
||||
, Css.borderBottomWidth (Css.px config.shadowHeight)
|
||||
, Css.batch sizingAttributes
|
||||
, Css.batch widthAttributes
|
||||
]
|
@ -1,232 +1,224 @@
|
||||
module Examples.Modal exposing (Msg, State, example, init, update)
|
||||
module Examples.Modal exposing (Msg, State, example, init, update, subscriptions)
|
||||
|
||||
{-|
|
||||
|
||||
@docs Msg, State, example, init, update
|
||||
@docs Msg, State, example, init, update, subscriptions
|
||||
|
||||
-}
|
||||
|
||||
import Accessibility.Styled as Html exposing (Html, div, h3, p, text)
|
||||
import Assets
|
||||
import Accessibility.Styled as Html exposing (Html, div, h3, h4, p, text)
|
||||
import Css exposing (..)
|
||||
import Css.Global
|
||||
import Html as Root
|
||||
import Html.Styled.Attributes exposing (css)
|
||||
import ModuleExample exposing (Category(..), ModuleExample)
|
||||
import Nri.Ui.Button.V5 as Button
|
||||
import Nri.Ui.Checkbox.V5 as Checkbox
|
||||
import Nri.Ui.Colors.V1 as Colors
|
||||
import Nri.Ui.Modal.V4 as Modal
|
||||
|
||||
|
||||
{-| -}
|
||||
type Msg
|
||||
= DismissModal
|
||||
| ShowModal ModalType
|
||||
import Nri.Ui.Modal.V5 as Modal
|
||||
|
||||
|
||||
{-| -}
|
||||
type alias State =
|
||||
{ modal : Maybe ModalType }
|
||||
|
||||
|
||||
{-| -}
|
||||
example : (Msg -> msg) -> State -> ModuleExample msg
|
||||
example parentMessage state =
|
||||
{ name = "Nri.Ui.Modal.V3"
|
||||
, category = Modals
|
||||
, content =
|
||||
[ case state.modal of
|
||||
Just modal ->
|
||||
viewModal modal
|
||||
|
||||
Nothing ->
|
||||
text ""
|
||||
, viewButtons
|
||||
]
|
||||
|> List.map (Html.map parentMessage)
|
||||
{ infoModal : Modal.Model
|
||||
, warningModal : Modal.Model
|
||||
, visibleTitle : Bool
|
||||
, showX : Bool
|
||||
, showContinue : Bool
|
||||
, showSecondary : Bool
|
||||
, dismissOnEscAndOverlayClick : Bool
|
||||
}
|
||||
|
||||
|
||||
{-| -}
|
||||
init : State
|
||||
init =
|
||||
{ modal = Nothing }
|
||||
{ infoModal = Modal.init
|
||||
, warningModal = Modal.init
|
||||
, visibleTitle = True
|
||||
, showX = True
|
||||
, showContinue = True
|
||||
, showSecondary = False
|
||||
, dismissOnEscAndOverlayClick = True
|
||||
}
|
||||
|
||||
|
||||
{-| -}
|
||||
example : (Msg -> msg) -> State -> ModuleExample msg
|
||||
example parentMessage state =
|
||||
{ name = "Nri.Ui.Modal.V5"
|
||||
, category = Modals
|
||||
, content =
|
||||
[ Modal.launchButton InfoModalMsg [] "Launch Info Modal"
|
||||
, Modal.launchButton WarningModalMsg [] "Launch Warning Modal"
|
||||
, Modal.info
|
||||
{ title = { title = "Modal.info", visibleTitle = state.visibleTitle }
|
||||
, wrapMsg = InfoModalMsg
|
||||
, content =
|
||||
viewContent state
|
||||
InfoModalMsg
|
||||
(Modal.primaryButton ForceClose "Continue")
|
||||
(Modal.secondaryButton ForceClose "Close")
|
||||
}
|
||||
state.infoModal
|
||||
, Modal.warning
|
||||
{ title = { title = "Modal.warning", visibleTitle = state.visibleTitle }
|
||||
, wrapMsg = WarningModalMsg
|
||||
, content =
|
||||
viewContent state
|
||||
WarningModalMsg
|
||||
(Modal.dangerButton ForceClose "Continue")
|
||||
(Modal.secondaryButton ForceClose "Close")
|
||||
}
|
||||
state.warningModal
|
||||
]
|
||||
|> List.map (Html.map parentMessage)
|
||||
}
|
||||
|
||||
|
||||
viewContent :
|
||||
State
|
||||
-> (Modal.Msg -> Msg)
|
||||
-> (List (Root.Attribute Msg) -> Html Msg)
|
||||
-> (List (Root.Attribute Msg) -> Html Msg)
|
||||
-> Modal.FocusableElementAttrs Msg
|
||||
-> Html Msg
|
||||
viewContent state wrapMsg primaryButton secondaryButton focusableElementAttrs =
|
||||
div []
|
||||
[ if state.showX then
|
||||
Modal.closeButton wrapMsg focusableElementAttrs.firstFocusableElement
|
||||
|
||||
else
|
||||
text ""
|
||||
, Modal.viewContent [ viewSettings state ]
|
||||
, if state.showContinue && state.showSecondary then
|
||||
Modal.viewFooter
|
||||
[ primaryButton []
|
||||
, secondaryButton focusableElementAttrs.lastFocusableElement
|
||||
]
|
||||
|
||||
else if state.showContinue then
|
||||
Modal.viewFooter
|
||||
[ primaryButton focusableElementAttrs.lastFocusableElement
|
||||
]
|
||||
|
||||
else if state.showSecondary then
|
||||
Modal.viewFooter
|
||||
[ secondaryButton focusableElementAttrs.lastFocusableElement
|
||||
]
|
||||
|
||||
else
|
||||
text ""
|
||||
]
|
||||
|
||||
|
||||
viewSettings : State -> Html Msg
|
||||
viewSettings state =
|
||||
div []
|
||||
[ Checkbox.viewWithLabel
|
||||
{ identifier = "visible-title"
|
||||
, label = "Visible title"
|
||||
, selected = Checkbox.selectedFromBool state.visibleTitle
|
||||
, setterMsg = SetVisibleTitle
|
||||
, disabled = False
|
||||
, theme = Checkbox.Square
|
||||
}
|
||||
, Checkbox.viewWithLabel
|
||||
{ identifier = "show-x"
|
||||
, label = "Show X button"
|
||||
, selected = Checkbox.selectedFromBool state.showX
|
||||
, setterMsg = SetShowX
|
||||
, disabled = False
|
||||
, theme = Checkbox.Square
|
||||
}
|
||||
, Checkbox.viewWithLabel
|
||||
{ identifier = "show-continue"
|
||||
, label = "Show main button"
|
||||
, selected = Checkbox.selectedFromBool state.showContinue
|
||||
, setterMsg = SetShowContinue
|
||||
, disabled = False
|
||||
, theme = Checkbox.Square
|
||||
}
|
||||
, Checkbox.viewWithLabel
|
||||
{ identifier = "show-secondary"
|
||||
, label = "Show secondary button"
|
||||
, selected = Checkbox.selectedFromBool state.showSecondary
|
||||
, setterMsg = SetShowSecondary
|
||||
, disabled = False
|
||||
, theme = Checkbox.Square
|
||||
}
|
||||
, Checkbox.viewWithLabel
|
||||
{ identifier = "dismiss-on-click"
|
||||
, label = "Dismiss on ESC and on backdrop click"
|
||||
, selected = Checkbox.selectedFromBool state.dismissOnEscAndOverlayClick
|
||||
, setterMsg = SetDismissOnEscAndOverlayClick
|
||||
, disabled = False
|
||||
, theme = Checkbox.Square
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
{-| -}
|
||||
type Msg
|
||||
= InfoModalMsg Modal.Msg
|
||||
| WarningModalMsg Modal.Msg
|
||||
| ForceClose
|
||||
| SetVisibleTitle Bool
|
||||
| SetShowX Bool
|
||||
| SetShowContinue Bool
|
||||
| SetShowSecondary Bool
|
||||
| SetDismissOnEscAndOverlayClick Bool
|
||||
|
||||
|
||||
{-| -}
|
||||
update : Msg -> State -> ( State, Cmd Msg )
|
||||
update msg state =
|
||||
let
|
||||
updateConfig =
|
||||
{ dismissOnEscAndOverlayClick = state.dismissOnEscAndOverlayClick }
|
||||
in
|
||||
case msg of
|
||||
DismissModal ->
|
||||
( { state | modal = Nothing }, Cmd.none )
|
||||
InfoModalMsg modalMsg ->
|
||||
case Modal.update updateConfig modalMsg state.infoModal of
|
||||
( newState, cmds ) ->
|
||||
( { state | infoModal = newState }
|
||||
, Cmd.map InfoModalMsg cmds
|
||||
)
|
||||
|
||||
ShowModal modalType ->
|
||||
( { state | modal = Just modalType }, Cmd.none )
|
||||
WarningModalMsg modalMsg ->
|
||||
case Modal.update updateConfig modalMsg state.warningModal of
|
||||
( newState, cmds ) ->
|
||||
( { state | warningModal = newState }
|
||||
, Cmd.map WarningModalMsg cmds
|
||||
)
|
||||
|
||||
ForceClose ->
|
||||
( { state
|
||||
| infoModal = Modal.init
|
||||
, warningModal = Modal.init
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
SetVisibleTitle value ->
|
||||
( { state | visibleTitle = value }, Cmd.none )
|
||||
|
||||
SetShowX value ->
|
||||
( { state | showX = value }, Cmd.none )
|
||||
|
||||
SetShowContinue value ->
|
||||
( { state | showContinue = value }, Cmd.none )
|
||||
|
||||
SetShowSecondary value ->
|
||||
( { state | showSecondary = value }, Cmd.none )
|
||||
|
||||
SetDismissOnEscAndOverlayClick value ->
|
||||
( { state | dismissOnEscAndOverlayClick = value }, Cmd.none )
|
||||
|
||||
|
||||
|
||||
-- INTERNAL
|
||||
|
||||
|
||||
type ModalType
|
||||
= InfoModal
|
||||
| WarningModal
|
||||
| NoButtonModal
|
||||
| NoDismissModal
|
||||
| OnlyXDismissModal
|
||||
| NoHeading
|
||||
| ScrolledContentModal
|
||||
|
||||
|
||||
viewButtons : Html Msg
|
||||
viewButtons =
|
||||
[ ( "Info Modal", "Modal.info", InfoModal )
|
||||
, ( "Warning Modal", "Modal.warning", WarningModal )
|
||||
, ( "No Button Modal", "Modal.info { ... footerContent = [] ... }", NoButtonModal )
|
||||
, ( "No Dismiss Modal", "Modal.info { ... onDismiss = NotDismissible ... }", NoDismissModal )
|
||||
, ( "Only X-Dismiss Modal", "Modal.info { ... onDismiss = WithOnlyX ... }", OnlyXDismissModal )
|
||||
, ( "No Heading", "Modal.info { ... visibleTitle = False ... }", NoHeading )
|
||||
, ( "Scrolled Content"
|
||||
, "Modal.info { content = Html.text 'so much stuff' }"
|
||||
, ScrolledContentModal
|
||||
)
|
||||
]
|
||||
|> List.map modalLaunchButton
|
||||
|> div []
|
||||
|
||||
|
||||
modalLaunchButton : ( String, String, ModalType ) -> Html Msg
|
||||
modalLaunchButton ( label, details, modalType ) =
|
||||
div []
|
||||
[ h3 [] [ text label ]
|
||||
, p [] [ text details ]
|
||||
, Button.button
|
||||
{ onClick = ShowModal modalType
|
||||
, size = Button.Small
|
||||
, style = Button.Secondary
|
||||
, width = Button.WidthUnbounded
|
||||
}
|
||||
{ label = label
|
||||
, state = Button.Enabled
|
||||
, icon = Nothing
|
||||
}
|
||||
{-| -}
|
||||
subscriptions : State -> Sub Msg
|
||||
subscriptions model =
|
||||
Sub.batch
|
||||
[ Sub.map InfoModalMsg (Modal.subscriptions model.infoModal)
|
||||
, Sub.map WarningModalMsg (Modal.subscriptions model.warningModal)
|
||||
]
|
||||
|
||||
|
||||
viewModal : ModalType -> Html Msg
|
||||
viewModal modal =
|
||||
case modal of
|
||||
InfoModal ->
|
||||
Modal.info Assets.assets
|
||||
{ title = "Info Modal"
|
||||
, visibleTitle = True
|
||||
, content = text "This is where the content goes!"
|
||||
, onDismiss = Modal.WithBackgroundOrX DismissModal
|
||||
, width = Nothing
|
||||
, footerContent =
|
||||
[ modalFooterButton "Primary" Button.Primary
|
||||
, modalFooterButton "Cancel" Button.Borderless
|
||||
]
|
||||
}
|
||||
|
||||
WarningModal ->
|
||||
Modal.warning Assets.assets
|
||||
{ title = "Warning Modal"
|
||||
, visibleTitle = True
|
||||
, content = text "This is where the content goes!"
|
||||
, onDismiss = Modal.WithBackgroundOrX DismissModal
|
||||
, width = Nothing
|
||||
, footerContent =
|
||||
[ modalFooterButton "Primary" Button.Danger
|
||||
, modalFooterButton "Cancel" Button.Borderless
|
||||
]
|
||||
}
|
||||
|
||||
NoButtonModal ->
|
||||
Modal.info Assets.assets
|
||||
{ title = "No Buttons"
|
||||
, visibleTitle = True
|
||||
, content = text "This is where the content goes!"
|
||||
, onDismiss = Modal.WithBackgroundOrX DismissModal
|
||||
, width = Nothing
|
||||
, footerContent = []
|
||||
}
|
||||
|
||||
NoDismissModal ->
|
||||
Modal.info Assets.assets
|
||||
{ title = "No Dismiss"
|
||||
, visibleTitle = True
|
||||
, content = text "This is where the content goes!"
|
||||
, onDismiss = Modal.NotDismissible
|
||||
, width = Nothing
|
||||
, footerContent =
|
||||
[ modalFooterButton "Primary" Button.Primary
|
||||
, modalFooterButton "Cancel" Button.Borderless
|
||||
]
|
||||
}
|
||||
|
||||
OnlyXDismissModal ->
|
||||
Modal.info Assets.assets
|
||||
{ title = "Only X-Dismiss"
|
||||
, visibleTitle = True
|
||||
, content = text "This is where the content goes!"
|
||||
, onDismiss = Modal.WithOnlyX DismissModal
|
||||
, width = Nothing
|
||||
, footerContent =
|
||||
[ modalFooterButton "Primary" Button.Primary
|
||||
, modalFooterButton "Cancel" Button.Borderless
|
||||
]
|
||||
}
|
||||
|
||||
NoHeading ->
|
||||
Modal.info Assets.assets
|
||||
{ title = "Hidden title"
|
||||
, onDismiss = Modal.WithBackgroundOrX DismissModal
|
||||
, visibleTitle = False
|
||||
, footerContent = []
|
||||
, width = Nothing
|
||||
, content =
|
||||
div
|
||||
[ css
|
||||
[ width (pct 100)
|
||||
, height (px 200)
|
||||
, backgroundColor Colors.gray75
|
||||
, border3 (px 1) dashed Colors.gray20
|
||||
]
|
||||
]
|
||||
[ text "Imagine an image" ]
|
||||
}
|
||||
|
||||
ScrolledContentModal ->
|
||||
Modal.info Assets.assets
|
||||
{ title = "Scrolled Content"
|
||||
, onDismiss = Modal.WithBackgroundOrX DismissModal
|
||||
, visibleTitle = True
|
||||
, footerContent = [ modalFooterButton "Primary" Button.Primary ]
|
||||
, width = Nothing
|
||||
, content =
|
||||
div []
|
||||
[ text "\nIt was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way – in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.\n\n\nIt was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way – in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.\n\nIt was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way – in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.\n "
|
||||
, div
|
||||
[ css
|
||||
[ width (pct 100)
|
||||
, height (px 200)
|
||||
, backgroundColor Colors.gray75
|
||||
, border3 (px 1) dashed Colors.gray20
|
||||
]
|
||||
]
|
||||
[ text "Imagine an image" ]
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
modalFooterButton : String -> Button.ButtonStyle -> Html Msg
|
||||
modalFooterButton label style =
|
||||
Button.button
|
||||
{ onClick = DismissModal
|
||||
, size = Button.Large
|
||||
, style = style
|
||||
, width = Button.WidthExact 230
|
||||
}
|
||||
{ label = label
|
||||
, state = Button.Enabled
|
||||
, icon = Nothing
|
||||
}
|
||||
|
@ -233,7 +233,8 @@ update outsideMsg moduleStates =
|
||||
subscriptions : ModuleStates -> Sub Msg
|
||||
subscriptions moduleStates =
|
||||
Sub.batch
|
||||
[]
|
||||
[ Sub.map ModalExampleMsg (Examples.Modal.subscriptions moduleStates.modalExampleState)
|
||||
]
|
||||
|
||||
|
||||
{-| A container with a visually-apparent size for demonstrating how style guide components
|
||||
|
@ -18,10 +18,11 @@
|
||||
"elm/svg": "1.0.1",
|
||||
"elm/url": "1.0.0",
|
||||
"elm-community/string-extra": "4.0.1",
|
||||
"lukewestby/accessible-html-with-css-temp-19": "1.0.0",
|
||||
"tesk9/accessible-html-with-css": "2.1.1",
|
||||
"pablohirafuji/elm-markdown": "2.0.5",
|
||||
"rtfeldman/elm-css": "16.0.0",
|
||||
"tesk9/accessible-html": "4.0.0",
|
||||
"tesk9/modal": "5.0.1",
|
||||
"wernerdegroot/listzipper": "3.2.0"
|
||||
},
|
||||
"indirect": {
|
||||
@ -35,4 +36,4 @@
|
||||
"direct": {},
|
||||
"indirect": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user