mirror of
https://github.com/NoRedInk/noredink-ui.git
synced 2024-11-28 10:17:49 +03:00
Merge branch 'master' into ink-james--premium-checkbox
This commit is contained in:
commit
743f270fec
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "5.15.0",
|
||||
"version": "5.16.0",
|
||||
"summary": "UI Widgets we use at NRI",
|
||||
"repository": "https://github.com/NoRedInk/noredink-ui.git",
|
||||
"license": "BSD3",
|
||||
@ -30,6 +30,7 @@
|
||||
"Nri.Ui.InputStyles",
|
||||
"Nri.Ui.Modal.V1",
|
||||
"Nri.Ui.Modal.V2",
|
||||
"Nri.Ui.Modal.V3",
|
||||
"Nri.Ui.Outline.V1",
|
||||
"Nri.Ui.Page.V1",
|
||||
"Nri.Ui.Palette.V1",
|
||||
|
245
src/Nri/Ui/Modal/V3.elm
Normal file
245
src/Nri/Ui/Modal/V3.elm
Normal file
@ -0,0 +1,245 @@
|
||||
module Nri.Ui.Modal.V3
|
||||
exposing
|
||||
( Model
|
||||
, info
|
||||
, warning
|
||||
)
|
||||
|
||||
{-| Changes from V2:
|
||||
|
||||
- Add assets for close button
|
||||
|
||||
@docs Model
|
||||
@docs info
|
||||
@docs warning
|
||||
|
||||
-}
|
||||
|
||||
import Accessibility.Styled as Html exposing (..)
|
||||
import Accessibility.Styled.Role as Role
|
||||
import Accessibility.Styled.Widget as Widget
|
||||
import Css
|
||||
import Css.Foreign exposing (Snippet, body, children, descendants, everything, selector)
|
||||
import Html.Styled
|
||||
import Html.Styled.Events exposing (onClick)
|
||||
import Nri.Ui
|
||||
import Nri.Ui.AssetPath exposing (Asset(..))
|
||||
import Nri.Ui.Colors.Extra
|
||||
import Nri.Ui.Colors.V1
|
||||
import Nri.Ui.Fonts.V1 as Fonts
|
||||
import Nri.Ui.Icon.V3 as Icon
|
||||
|
||||
|
||||
{-|
|
||||
|
||||
- `onDismiss`: If `Nothing`, the modal will not be dismissable
|
||||
- `visibleTitle`: If `False`, the title will still be used for screen readers
|
||||
- `content`: This will be placed in a `width:100%` div in the main area of the modal
|
||||
- `footerContent`: The optional items here will be stacked below the main content area and center-aligned.
|
||||
Commonly you will either give a list of Nri.Ui.Buttons,
|
||||
or an empty list.
|
||||
|
||||
-}
|
||||
type alias Model msg =
|
||||
{ title : String
|
||||
, visibleTitle : Bool
|
||||
, content : Html msg
|
||||
, footerContent : List (Html msg)
|
||||
, onDismiss : Maybe msg
|
||||
, width : Maybe Int
|
||||
}
|
||||
|
||||
|
||||
type alias Assets r =
|
||||
{ r | icons_xBlue_svg : Asset }
|
||||
|
||||
|
||||
type ModalType
|
||||
= Info
|
||||
| Warning
|
||||
|
||||
|
||||
{-| -}
|
||||
info : Assets r -> Model msg -> Html msg
|
||||
info assets =
|
||||
view assets Info
|
||||
|
||||
|
||||
{-| -}
|
||||
warning : Assets r -> Model msg -> Html msg
|
||||
warning assets =
|
||||
view assets Warning
|
||||
|
||||
|
||||
view : Assets r -> ModalType -> Model msg -> Html msg
|
||||
view assets modalType { title, visibleTitle, content, onDismiss, footerContent, width } =
|
||||
Nri.Ui.styled div
|
||||
"modal-backdrop-container"
|
||||
((case modalType of
|
||||
Info ->
|
||||
Css.backgroundColor (Nri.Ui.Colors.Extra.withAlpha 0.9 Nri.Ui.Colors.V1.navy)
|
||||
|
||||
Warning ->
|
||||
Css.backgroundColor (Nri.Ui.Colors.Extra.withAlpha 0.9 Nri.Ui.Colors.V1.gray20)
|
||||
)
|
||||
:: [ Css.height (Css.vh 100)
|
||||
, Css.left Css.zero
|
||||
, Css.overflow Css.hidden
|
||||
, Css.position Css.fixed
|
||||
, Css.top Css.zero
|
||||
, Css.width (Css.pct 100)
|
||||
, Css.zIndex (Css.int 200)
|
||||
, Css.displayFlex
|
||||
, Css.alignItems Css.center
|
||||
, Css.justifyContent Css.center
|
||||
]
|
||||
)
|
||||
[ Role.dialog
|
||||
, Widget.label title
|
||||
, Widget.modal True
|
||||
]
|
||||
[ Nri.Ui.styled Html.Styled.div
|
||||
"modal-click-catcher"
|
||||
[ Css.bottom Css.zero
|
||||
, Css.left Css.zero
|
||||
, Css.position Css.absolute
|
||||
, Css.right Css.zero
|
||||
, Css.top Css.zero
|
||||
]
|
||||
(case onDismiss of
|
||||
Nothing ->
|
||||
[]
|
||||
|
||||
Just msg ->
|
||||
[ onClick msg ]
|
||||
)
|
||||
[]
|
||||
, Nri.Ui.styled div
|
||||
"modal-container"
|
||||
[ Css.width (Css.px 600)
|
||||
, Css.maxHeight <| Css.calc (Css.vh 100) Css.minus (Css.px 100)
|
||||
, Css.padding4 (Css.px 35) Css.zero (Css.px 25) Css.zero
|
||||
, Css.margin2 (Css.px 75) Css.auto
|
||||
, Css.backgroundColor Nri.Ui.Colors.V1.white
|
||||
, Css.borderRadius (Css.px 20)
|
||||
, Css.property "box-shadow" "0 1px 10px 0 rgba(0, 0, 0, 0.35)"
|
||||
, Css.position Css.relative -- required for closeButtonContainer
|
||||
, Css.displayFlex
|
||||
, Css.alignItems Css.center
|
||||
, Css.flexDirection Css.column
|
||||
, Css.flexWrap Css.noWrap
|
||||
, Fonts.baseFont
|
||||
]
|
||||
[]
|
||||
[ -- This global <style> node sets overflow to hidden on the body element,
|
||||
-- thereby preventing the page from scrolling behind the backdrop when the modal is
|
||||
-- open (and this node is present on the page).
|
||||
Css.Foreign.global
|
||||
[ Css.Foreign.body
|
||||
[ Css.overflow Css.hidden ]
|
||||
]
|
||||
, case onDismiss of
|
||||
Just msg ->
|
||||
closeButton assets msg
|
||||
|
||||
Nothing ->
|
||||
text ""
|
||||
, if visibleTitle then
|
||||
viewHeader modalType title
|
||||
else
|
||||
text ""
|
||||
, viewContent modalType content
|
||||
, viewFooter footerContent
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
closeButton : Assets r -> msg -> Html msg
|
||||
closeButton assets msg =
|
||||
Nri.Ui.styled div
|
||||
"close-button-container"
|
||||
[ Css.position Css.absolute
|
||||
, Css.top Css.zero
|
||||
, Css.right Css.zero
|
||||
, Css.padding (Css.px 25)
|
||||
]
|
||||
[]
|
||||
[ Icon.button
|
||||
{ alt = "Close"
|
||||
, msg = msg
|
||||
, icon = Icon.close assets
|
||||
, disabled = False
|
||||
, size = Icon.Medium
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
viewHeader : ModalType -> String -> Html msg
|
||||
viewHeader modalType title =
|
||||
Nri.Ui.styled Html.h3
|
||||
"modal-header"
|
||||
((case modalType of
|
||||
Info ->
|
||||
Css.color Nri.Ui.Colors.V1.navy
|
||||
|
||||
Warning ->
|
||||
Css.color Nri.Ui.Colors.V1.red
|
||||
)
|
||||
:: [ Css.fontWeight (Css.int 700)
|
||||
, Css.lineHeight (Css.px 27)
|
||||
, Css.margin2 Css.zero (Css.px 65)
|
||||
, Css.fontSize (Css.px 20)
|
||||
, Fonts.baseFont
|
||||
]
|
||||
)
|
||||
[]
|
||||
[ Html.text title
|
||||
]
|
||||
|
||||
|
||||
viewContent : ModalType -> Html msg -> Html msg
|
||||
viewContent modalType content =
|
||||
Nri.Ui.styled div
|
||||
"modal-content"
|
||||
[ Css.overflowY Css.scroll
|
||||
, Css.padding2 (Css.px 30) (Css.px 45)
|
||||
, Css.width (Css.pct 100)
|
||||
, Css.minHeight (Css.px 150)
|
||||
, Css.boxSizing Css.borderBox
|
||||
]
|
||||
[]
|
||||
[ content ]
|
||||
|
||||
|
||||
viewFooter : List (Html msg) -> Html msg
|
||||
viewFooter footerContent =
|
||||
case footerContent of
|
||||
[] ->
|
||||
Html.text ""
|
||||
|
||||
_ ->
|
||||
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)
|
||||
]
|
||||
[]
|
||||
(List.map
|
||||
(\x ->
|
||||
Nri.Ui.styled div
|
||||
"modal-footer-item"
|
||||
[ Css.margin4 (Css.px 10) Css.zero Css.zero Css.zero
|
||||
, Css.firstChild
|
||||
[ Css.margin Css.zero
|
||||
]
|
||||
]
|
||||
[]
|
||||
[ x ]
|
||||
)
|
||||
footerContent
|
||||
)
|
@ -82,32 +82,15 @@ custom { header, view, width } =
|
||||
{-| Displays a table of data without a header row
|
||||
-}
|
||||
viewWithoutHeader : List (Column data msg) -> List data -> Html msg
|
||||
viewWithoutHeader columns data =
|
||||
table [] <|
|
||||
List.map (viewRow columns) data
|
||||
viewWithoutHeader columns =
|
||||
tableWithoutHeader [] columns (viewRow columns)
|
||||
|
||||
|
||||
{-| Displays a table of data based on the provided column definitions
|
||||
-}
|
||||
view : List (Column data msg) -> List data -> Html msg
|
||||
view columns data =
|
||||
tableWithHeader [] columns <|
|
||||
List.map (viewRow columns) data
|
||||
|
||||
|
||||
viewHeaders : List (Column data msg) -> Html msg
|
||||
viewHeaders columns =
|
||||
tr
|
||||
[ css headersStyles ]
|
||||
(List.map viewRowHeader columns)
|
||||
|
||||
|
||||
viewRowHeader : Column data msg -> Html msg
|
||||
viewRowHeader (Column header _ width) =
|
||||
th
|
||||
[ css (width :: headerStyles)
|
||||
]
|
||||
[ header ]
|
||||
view columns =
|
||||
tableWithHeader [] columns (viewRow columns)
|
||||
|
||||
|
||||
viewRow : List (Column data msg) -> data -> Html msg
|
||||
@ -135,16 +118,14 @@ data is on its way and what it will look like when it arrives.
|
||||
-}
|
||||
viewLoading : List (Column data msg) -> Html msg
|
||||
viewLoading columns =
|
||||
tableWithHeader loadingTableStyles columns <|
|
||||
List.map (viewLoadingRow columns) (List.range 0 8)
|
||||
tableWithHeader loadingTableStyles columns (viewLoadingRow columns) (List.range 0 8)
|
||||
|
||||
|
||||
{-| Display the loading table without a header row
|
||||
-}
|
||||
viewLoadingWithoutHeader : List (Column data msg) -> Html msg
|
||||
viewLoadingWithoutHeader columns =
|
||||
table loadingTableStyles <|
|
||||
List.map (viewLoadingRow columns) (List.range 0 8)
|
||||
tableWithoutHeader loadingTableStyles columns (viewLoadingRow columns) (List.range 0 8)
|
||||
|
||||
|
||||
viewLoadingRow : List (Column data msg) -> Int -> Html msg
|
||||
@ -173,14 +154,45 @@ stylesLoadingColumn rowIndex colIndex width =
|
||||
-- HELP
|
||||
|
||||
|
||||
tableWithoutHeader : List Style -> List (Column data msg) -> (a -> Html msg) -> List a -> Html msg
|
||||
tableWithoutHeader styles columns toRow data =
|
||||
table styles
|
||||
[ tableBody toRow data
|
||||
]
|
||||
|
||||
|
||||
tableWithHeader : List Style -> List (Column data msg) -> (a -> Html msg) -> List a -> Html msg
|
||||
tableWithHeader styles columns toRow data =
|
||||
table styles
|
||||
[ tableHeader columns
|
||||
, tableBody toRow data
|
||||
]
|
||||
|
||||
|
||||
table : List Style -> List (Html msg) -> Html msg
|
||||
table styles =
|
||||
Html.table [ css (styles ++ tableStyles) ]
|
||||
|
||||
|
||||
tableWithHeader : List Style -> List (Column data msg) -> List (Html msg) -> Html msg
|
||||
tableWithHeader styles columns rows =
|
||||
table styles (viewHeaders columns :: rows)
|
||||
tableHeader : List (Column data msg) -> Html msg
|
||||
tableHeader columns =
|
||||
thead []
|
||||
[ tr [ css headersStyles ]
|
||||
(List.map tableRowHeader columns)
|
||||
]
|
||||
|
||||
|
||||
tableRowHeader : Column data msg -> Html msg
|
||||
tableRowHeader (Column header _ width) =
|
||||
th
|
||||
[ css (width :: headerStyles)
|
||||
]
|
||||
[ header ]
|
||||
|
||||
|
||||
tableBody : (a -> Html msg) -> List a -> Html msg
|
||||
tableBody toRow items =
|
||||
tbody [] (List.map toRow items)
|
||||
|
||||
|
||||
|
||||
|
@ -7,13 +7,14 @@ module Examples.Modal exposing (Msg, State, example, init, update)
|
||||
-}
|
||||
|
||||
import Accessibility.Styled as Html exposing (Html, div, h3, p, text)
|
||||
import Assets
|
||||
import Css exposing (..)
|
||||
import Html.Styled
|
||||
import Html.Styled.Attributes exposing (css)
|
||||
import ModuleExample exposing (Category(..), ModuleExample)
|
||||
import Nri.Ui.Button.V3 as Button
|
||||
import Nri.Ui.Colors.V1 as Colors
|
||||
import Nri.Ui.Modal.V2 as Modal
|
||||
import Nri.Ui.Modal.V3 as Modal
|
||||
|
||||
|
||||
{-| -}
|
||||
@ -30,7 +31,7 @@ type alias State =
|
||||
{-| -}
|
||||
example : (Msg -> msg) -> State -> ModuleExample msg
|
||||
example parentMessage state =
|
||||
{ filename = "Nri.Ui.Modal.V2.elm"
|
||||
{ filename = "Nri.Ui.Modal.V3.elm"
|
||||
, category = Modals
|
||||
, content =
|
||||
[ case state.modal of
|
||||
@ -114,7 +115,7 @@ viewModal : ModalType -> Html Msg
|
||||
viewModal modal =
|
||||
case modal of
|
||||
InfoModal ->
|
||||
Modal.info
|
||||
Modal.info Assets.assets
|
||||
{ title = "Info Modal"
|
||||
, visibleTitle = True
|
||||
, content = text "This is where the content goes!"
|
||||
@ -127,7 +128,7 @@ viewModal modal =
|
||||
}
|
||||
|
||||
WarningModal ->
|
||||
Modal.warning
|
||||
Modal.warning Assets.assets
|
||||
{ title = "Warning Modal"
|
||||
, visibleTitle = True
|
||||
, content = text "This is where the content goes!"
|
||||
@ -140,7 +141,7 @@ viewModal modal =
|
||||
}
|
||||
|
||||
NoButtonModal ->
|
||||
Modal.info
|
||||
Modal.info Assets.assets
|
||||
{ title = "No Buttons"
|
||||
, visibleTitle = True
|
||||
, content = text "This is where the content goes!"
|
||||
@ -150,7 +151,7 @@ viewModal modal =
|
||||
}
|
||||
|
||||
NoDismissModal ->
|
||||
Modal.info
|
||||
Modal.info Assets.assets
|
||||
{ title = "No Dismiss"
|
||||
, visibleTitle = True
|
||||
, content = text "This is where the content goes!"
|
||||
@ -163,7 +164,7 @@ viewModal modal =
|
||||
}
|
||||
|
||||
NoHeading ->
|
||||
Modal.info
|
||||
Modal.info Assets.assets
|
||||
{ title = "Hidden title"
|
||||
, onDismiss = Just DismissModal
|
||||
, visibleTitle = False
|
||||
@ -182,7 +183,7 @@ viewModal modal =
|
||||
}
|
||||
|
||||
ScrolledContentModal ->
|
||||
Modal.info
|
||||
Modal.info Assets.assets
|
||||
{ title = "Scrolled Content"
|
||||
, onDismiss = Just DismissModal
|
||||
, visibleTitle = True
|
||||
|
Loading…
Reference in New Issue
Block a user