mirror of
https://github.com/NoRedInk/noredink-ui.git
synced 2024-12-24 22:21:45 +03:00
commit
8fdb6867ec
@ -1,5 +1,6 @@
|
||||
Nri.Ui.Accordion.V1,upgrade to V3
|
||||
Nri.Ui.Button.V8,upgrade to V10
|
||||
Nri.Ui.Container.V1,upgrade to V2
|
||||
Nri.Ui.Menu.V1,upgrade to V3
|
||||
Nri.Ui.Menu.V2,upgrade to V3
|
||||
Nri.Ui.Modal.V10,upgrade to V11
|
||||
|
|
1
elm.json
1
elm.json
@ -17,6 +17,7 @@
|
||||
"Nri.Ui.ClickableSvg.V2",
|
||||
"Nri.Ui.ClickableText.V3",
|
||||
"Nri.Ui.Container.V1",
|
||||
"Nri.Ui.Container.V2",
|
||||
"Nri.Ui.Colors.Extra",
|
||||
"Nri.Ui.Colors.V1",
|
||||
"Nri.Ui.Confetti.V2",
|
||||
|
@ -50,6 +50,9 @@ usages = ['styleguide-app/../src/Nri/Ui/SlideModal/V2.elm']
|
||||
hint = 'upgrade to V2'
|
||||
usages = ['styleguide-app/Examples/Tooltip.elm']
|
||||
|
||||
[forbidden."Nri.Ui.Container.V1"]
|
||||
hint = 'upgrade to V2'
|
||||
|
||||
[forbidden."Nri.Ui.Icon.V3"]
|
||||
hint = 'upgrade to V5'
|
||||
usages = ['styleguide-app/../src/Nri/Ui/Modal/V3.elm']
|
||||
|
301
src/Nri/Ui/Container/V2.elm
Normal file
301
src/Nri/Ui/Container/V2.elm
Normal file
@ -0,0 +1,301 @@
|
||||
module Nri.Ui.Container.V2 exposing
|
||||
( view, Attribute
|
||||
, paddingPx, custom, css, testId, id
|
||||
, plaintext, markdown, html
|
||||
, gray, default, disabled, invalid, pillow, buttony
|
||||
)
|
||||
|
||||
{-| Common NoRedInk Containers
|
||||
|
||||
|
||||
# Changelog
|
||||
|
||||
|
||||
## Changes from V1
|
||||
|
||||
- removes fullHeight
|
||||
- changes the API from providing many themed functions that create HTML (`alternate`, `general`, etc.) to having a single `view` helper that takes a list of attributes (including themed attributes and content attributes)
|
||||
- adds `custom`, `testId`, `id`
|
||||
- adds `plaintext` helper and `markdown` helper
|
||||
- renames themes from:
|
||||
- `alternate` -> `gray`
|
||||
- `general` -> `default`
|
||||
- `interactable` -> `pillow`
|
||||
- removes `interactableWithLabel` theme
|
||||
- adds `buttony` theme
|
||||
|
||||
|
||||
# Documentation
|
||||
|
||||
|
||||
## View
|
||||
|
||||
@docs view, Attribute
|
||||
@docs paddingPx, custom, css, testId, id
|
||||
|
||||
|
||||
## Content
|
||||
|
||||
@docs plaintext, markdown, html
|
||||
|
||||
|
||||
## Themes
|
||||
|
||||
@docs gray, default, disabled, invalid, pillow, buttony
|
||||
|
||||
-}
|
||||
|
||||
import Css exposing (..)
|
||||
import Css.Media exposing (withMedia)
|
||||
import Html.Styled as Html exposing (..)
|
||||
import Html.Styled.Attributes
|
||||
import Markdown
|
||||
import Nri.Ui
|
||||
import Nri.Ui.Colors.V1 as Colors
|
||||
import Nri.Ui.Html.Attributes.V2 as ExtraAttributes
|
||||
import Nri.Ui.MediaQuery.V1 exposing (mobile)
|
||||
import Nri.Ui.Text.V5 as Text
|
||||
|
||||
|
||||
{-| -}
|
||||
type Attribute msg
|
||||
= Attribute (Settings msg -> Settings msg)
|
||||
|
||||
|
||||
{-| PRIVATE
|
||||
-}
|
||||
type alias Settings msg =
|
||||
{ containerType : String
|
||||
, padding : Float
|
||||
, css : List Css.Style
|
||||
, content : List (Html msg)
|
||||
, attributes : List (Html.Attribute msg)
|
||||
}
|
||||
|
||||
|
||||
{-| Changes the padding inside the container border around the content.
|
||||
-}
|
||||
paddingPx : Float -> Attribute msg
|
||||
paddingPx padding =
|
||||
Attribute <| \config -> { config | padding = padding }
|
||||
|
||||
|
||||
{-| Use this helper to add custom attributes.
|
||||
|
||||
Do NOT use this helper to add css styles, as they may not be applied the way
|
||||
you want/expect if underlying styles change.
|
||||
Instead, please use the `css` helper.
|
||||
|
||||
-}
|
||||
custom : List (Html.Attribute msg) -> Attribute msg
|
||||
custom attributes =
|
||||
Attribute <|
|
||||
\config ->
|
||||
{ config
|
||||
| attributes =
|
||||
config.attributes ++ attributes
|
||||
}
|
||||
|
||||
|
||||
{-| -}
|
||||
testId : String -> Attribute msg
|
||||
testId id_ =
|
||||
custom [ ExtraAttributes.testId id_ ]
|
||||
|
||||
|
||||
{-| -}
|
||||
id : String -> Attribute msg
|
||||
id id_ =
|
||||
custom [ Html.Styled.Attributes.id id_ ]
|
||||
|
||||
|
||||
{-| -}
|
||||
css : List Css.Style -> Attribute msg
|
||||
css css_ =
|
||||
Attribute <| \config -> { config | css = config.css ++ css_ }
|
||||
|
||||
|
||||
{-| -}
|
||||
view : List (Attribute msg) -> Html msg
|
||||
view attributes =
|
||||
let
|
||||
settings : Settings msg
|
||||
settings =
|
||||
List.foldl (\(Attribute set) -> set)
|
||||
defaultSettings
|
||||
attributes
|
||||
in
|
||||
Nri.Ui.styled div
|
||||
settings.containerType
|
||||
(padding (px settings.padding) :: settings.css)
|
||||
settings.attributes
|
||||
settings.content
|
||||
|
||||
|
||||
{-| Used for the default container case.
|
||||
-}
|
||||
default : Attribute msg
|
||||
default =
|
||||
Attribute identity
|
||||
|
||||
|
||||
defaultSettings : Settings msg
|
||||
defaultSettings =
|
||||
{ containerType = "default-container"
|
||||
, padding = 20
|
||||
, css = defaultStyles
|
||||
, content = []
|
||||
, attributes = []
|
||||
}
|
||||
|
||||
|
||||
defaultStyles : List Css.Style
|
||||
defaultStyles =
|
||||
[ borderRadius (px 8)
|
||||
, border3 (px 1) solid Colors.gray92
|
||||
, boxShadow5 zero (px 1) (px 1) zero (rgba 0 0 0 0.25)
|
||||
, backgroundColor Colors.white
|
||||
]
|
||||
|
||||
|
||||
{-| Used when there are a lot of containers.
|
||||
-}
|
||||
gray : Attribute msg
|
||||
gray =
|
||||
Attribute <|
|
||||
\config ->
|
||||
{ config
|
||||
| containerType = "gray-container"
|
||||
, padding = 20
|
||||
, css = grayStyles
|
||||
}
|
||||
|
||||
|
||||
grayStyles : List Css.Style
|
||||
grayStyles =
|
||||
[ borderRadius (px 8)
|
||||
, backgroundColor Colors.gray96
|
||||
]
|
||||
|
||||
|
||||
{-| -}
|
||||
disabled : Attribute msg
|
||||
disabled =
|
||||
Attribute <|
|
||||
\config ->
|
||||
{ config
|
||||
| containerType = "disabled-container"
|
||||
, padding = 20
|
||||
, css = disabledStyles
|
||||
}
|
||||
|
||||
|
||||
disabledStyles : List Css.Style
|
||||
disabledStyles =
|
||||
[ borderRadius (px 8)
|
||||
, border3 (px 1) solid Colors.gray92
|
||||
, backgroundColor Colors.white
|
||||
, color Colors.gray45
|
||||
]
|
||||
|
||||
|
||||
{-| -}
|
||||
invalid : Attribute msg
|
||||
invalid =
|
||||
Attribute <|
|
||||
\config ->
|
||||
{ config
|
||||
| containerType = "invalid-container"
|
||||
, padding = 20
|
||||
, css = invalidStyles
|
||||
}
|
||||
|
||||
|
||||
invalidStyles : List Css.Style
|
||||
invalidStyles =
|
||||
[ borderRadius (px 8)
|
||||
, border3 (px 1) solid Colors.purpleLight
|
||||
, boxShadow5 zero (px 1) (px 1) zero Colors.purple
|
||||
, backgroundColor Colors.purpleLight
|
||||
]
|
||||
|
||||
|
||||
{-| Used for containers of interactive elements.
|
||||
-}
|
||||
pillow : Attribute msg
|
||||
pillow =
|
||||
Attribute <|
|
||||
\config ->
|
||||
{ config
|
||||
| containerType = "pillow-container"
|
||||
, padding = 40
|
||||
, css = pillowStyles
|
||||
}
|
||||
|
||||
|
||||
pillowStyles : List Style
|
||||
pillowStyles =
|
||||
[ borderRadius (px 20)
|
||||
, border3 (px 1) solid Colors.gray92
|
||||
, boxShadow5 zero (px 2) (px 4) zero (rgba 0 0 0 0.25)
|
||||
, backgroundColor Colors.white
|
||||
, withMedia [ mobile ]
|
||||
[ borderRadius (px 8)
|
||||
, padding (px 20)
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
{-| Used for clickable cards
|
||||
-}
|
||||
buttony : Attribute msg
|
||||
buttony =
|
||||
Attribute <|
|
||||
\config ->
|
||||
{ config
|
||||
| containerType = "buttony-container"
|
||||
, css = buttonyStyles
|
||||
}
|
||||
|
||||
|
||||
buttonyStyles : List Style
|
||||
buttonyStyles =
|
||||
[ borderRadius (px 20)
|
||||
, border3 (px 1) solid Colors.gray85
|
||||
, borderBottom3 (px 4) solid Colors.gray85
|
||||
, backgroundColor Colors.white
|
||||
, withMedia [ mobile ]
|
||||
[ borderRadius (px 8)
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
{-| Provide a list of custom HTML.
|
||||
-}
|
||||
html : List (Html msg) -> Attribute msg
|
||||
html content =
|
||||
Attribute <| \config -> { config | content = content }
|
||||
|
||||
|
||||
{-| Provide a plain-text string.
|
||||
-}
|
||||
plaintext : String -> Attribute msg
|
||||
plaintext content =
|
||||
Attribute <| \config -> { config | content = [ text content ] }
|
||||
|
||||
|
||||
{-| Provide a string that will be rendered as markdown.
|
||||
|
||||
Note that you may need to remove extra margin added by default
|
||||
to `p` tags by user agents.
|
||||
|
||||
-}
|
||||
markdown : String -> Attribute msg
|
||||
markdown content =
|
||||
Attribute <|
|
||||
\config ->
|
||||
{ config
|
||||
| content =
|
||||
Markdown.toHtml Nothing content
|
||||
|> List.map fromUnstyled
|
||||
}
|
43
styleguide-app/Debug/Control/Extra.elm
Normal file
43
styleguide-app/Debug/Control/Extra.elm
Normal file
@ -0,0 +1,43 @@
|
||||
module Debug.Control.Extra exposing
|
||||
( float
|
||||
, list, listItem, optionalListItem
|
||||
)
|
||||
|
||||
{-|
|
||||
|
||||
@docs float
|
||||
@docs list, listItem, optionalListItem
|
||||
|
||||
-}
|
||||
|
||||
import Debug.Control as Control exposing (Control)
|
||||
|
||||
|
||||
{-| -}
|
||||
float : Float -> Control Float
|
||||
float default =
|
||||
Control.map (String.toFloat >> Maybe.withDefault default)
|
||||
(Control.string (String.fromFloat default))
|
||||
|
||||
|
||||
{-| Use with `listItem` and `optionalListItem`
|
||||
-}
|
||||
list : Control (List a)
|
||||
list =
|
||||
Control.record []
|
||||
|
||||
|
||||
{-| -}
|
||||
listItem : String -> Control a -> Control (List a) -> Control (List a)
|
||||
listItem name accessor accumulator =
|
||||
Control.field name
|
||||
(Control.map List.singleton accessor)
|
||||
(Control.map (++) accumulator)
|
||||
|
||||
|
||||
{-| -}
|
||||
optionalListItem : String -> Control a -> Control (List a) -> Control (List a)
|
||||
optionalListItem name accessor accumulator =
|
||||
Control.field name
|
||||
(Control.map (List.singleton >> List.filterMap identity) (Control.maybe False accessor))
|
||||
(Control.map (++) accumulator)
|
@ -9,6 +9,7 @@ module Examples.Balloon exposing (example, State, Msg)
|
||||
import Category exposing (Category(..))
|
||||
import Css
|
||||
import Debug.Control as Control exposing (Control)
|
||||
import Debug.Control.Extra as ControlExtra
|
||||
import Example exposing (Example)
|
||||
import Examples.IconExamples as IconExamples
|
||||
import Html.Styled exposing (Html, div, fromUnstyled, text)
|
||||
@ -83,12 +84,12 @@ widthOptions =
|
||||
[ ( "px"
|
||||
, Control.map
|
||||
(\w -> ( "Balloon.widthPx " ++ String.fromFloat w, Balloon.widthPx w ))
|
||||
(controlFloat 50)
|
||||
(ControlExtra.float 50)
|
||||
)
|
||||
, ( "%"
|
||||
, Control.map
|
||||
(\w -> ( "Balloon.widthPct " ++ String.fromFloat w, Balloon.widthPct w ))
|
||||
(controlFloat 50)
|
||||
(ControlExtra.float 50)
|
||||
)
|
||||
]
|
||||
|
||||
@ -97,13 +98,7 @@ paddingOptions : Control ( String, Balloon.Attribute )
|
||||
paddingOptions =
|
||||
Control.map
|
||||
(\w -> ( "Balloon.paddingPx " ++ String.fromFloat w, Balloon.paddingPx w ))
|
||||
(controlFloat 10)
|
||||
|
||||
|
||||
controlFloat : Float -> Control Float
|
||||
controlFloat default =
|
||||
Control.map (String.toFloat >> Maybe.withDefault default)
|
||||
(Control.string (String.fromFloat default))
|
||||
(ControlExtra.float 10)
|
||||
|
||||
|
||||
{-| -}
|
||||
|
@ -8,23 +8,27 @@ module Examples.Container exposing (Msg, State, example)
|
||||
|
||||
import Category exposing (Category(..))
|
||||
import Css
|
||||
import Debug.Control as Control exposing (Control)
|
||||
import Debug.Control.Extra as ControlExtra
|
||||
import Example exposing (Example)
|
||||
import Html.Styled as Html
|
||||
import Html.Styled as Html exposing (Html)
|
||||
import Html.Styled.Attributes exposing (css)
|
||||
import Html.Styled.Events exposing (onClick)
|
||||
import KeyboardSupport exposing (Direction(..), Key(..))
|
||||
import Nri.Ui.Button.V10 as Button
|
||||
import Nri.Ui.Colors.V1 as Colors
|
||||
import Nri.Ui.Container.V1 as Container
|
||||
import Nri.Ui.Container.V2 as Container
|
||||
import Nri.Ui.Heading.V2 as Heading
|
||||
import Nri.Ui.Svg.V1 as Svg
|
||||
import Nri.Ui.Text.V5 as Text
|
||||
import Nri.Ui.UiIcon.V1 as UiIcon
|
||||
|
||||
|
||||
{-| -}
|
||||
example : Example State Msg
|
||||
example =
|
||||
{ name = "Container"
|
||||
, version = 1
|
||||
, version = 2
|
||||
, categories = [ Layout ]
|
||||
, keyboardSupport = []
|
||||
, state = init
|
||||
@ -32,52 +36,147 @@ example =
|
||||
, subscriptions = \_ -> Sub.none
|
||||
, view =
|
||||
\state ->
|
||||
[ Heading.h3 [ Heading.css [ Css.marginTop (Css.px 8) ] ]
|
||||
[ Html.text "General Container" ]
|
||||
, Html.text "Used for the general container case."
|
||||
, Container.general [] (Html.text "Content, content...")
|
||||
, Heading.h3 [ Heading.css [ Css.marginTop (Css.px 8) ] ]
|
||||
[ Html.text "Alternate Container" ]
|
||||
, Html.text "Used when there are a lot of containers."
|
||||
, Container.alternate [] (Html.text "Content, content...")
|
||||
, Heading.h3 [ Heading.css [ Css.marginTop (Css.px 8) ] ]
|
||||
[ Html.text "Interactable Container" ]
|
||||
, Html.text "Usually used for larger containers with many elements inside."
|
||||
, Container.interactable [] (Html.text "Content, content...")
|
||||
, Heading.h3 [ Heading.css [ Css.marginTop (Css.px 8) ] ]
|
||||
[ Html.text "Disabled Container" ]
|
||||
, Html.text "Used to indicate content is locked/inaccessible"
|
||||
, Container.disabled [] (Html.text "Content, content...")
|
||||
, Heading.h3 [ Heading.css [ Css.marginTop (Css.px 8) ] ]
|
||||
[ Html.text "Invalid Container" ]
|
||||
, Html.text "Used to indicate content is invalid"
|
||||
, Container.invalid [] (Html.text "Content, content...")
|
||||
, Heading.h3 [ Heading.css [ Css.marginTop (Css.px 8) ] ]
|
||||
[ Html.text "Interactable container with a label" ]
|
||||
, Html.text "Used for helpful tidbits."
|
||||
, Container.interactableWithLabel "The label" <|
|
||||
Html.text "Content, content..."
|
||||
let
|
||||
attributes =
|
||||
Control.currentValue state.control
|
||||
in
|
||||
[ Control.view UpdateControl state.control
|
||||
|> Html.fromUnstyled
|
||||
, viewExample
|
||||
{ name = "Default Container"
|
||||
, description = "Your go-to container."
|
||||
}
|
||||
(Container.default :: attributes)
|
||||
, viewExample
|
||||
{ name = "Gray Container"
|
||||
, description = "A container that doesn’t draw too much attention to itself."
|
||||
}
|
||||
(Container.gray :: attributes)
|
||||
, viewExample
|
||||
{ name = "Pillow Container"
|
||||
, description = "When you want something big and soft."
|
||||
}
|
||||
(Container.pillow :: attributes)
|
||||
, viewExample
|
||||
{ name = "Buttony Container"
|
||||
, description = "Used for clickable button card things."
|
||||
}
|
||||
(Container.buttony :: attributes)
|
||||
, viewExample
|
||||
{ name = "Disabled Container"
|
||||
, description = "Used to indicate content is locked/inaccessible"
|
||||
}
|
||||
(Container.disabled :: attributes)
|
||||
, viewExample
|
||||
{ name = "Invalid Container"
|
||||
, description = "Used to indicate content is invalid"
|
||||
}
|
||||
(Container.invalid :: attributes)
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
viewExample : { name : String, description : String } -> List (Container.Attribute msg) -> Html msg
|
||||
viewExample { name, description } attributes =
|
||||
Html.section
|
||||
[ css
|
||||
[ Css.marginTop (Css.px 20)
|
||||
]
|
||||
]
|
||||
[ Heading.h3 [] [ Html.text name ]
|
||||
, Html.text description
|
||||
, Container.view attributes
|
||||
]
|
||||
|
||||
|
||||
{-| -}
|
||||
type alias State =
|
||||
{ control : Control (List (Container.Attribute Msg))
|
||||
}
|
||||
|
||||
|
||||
{-| -}
|
||||
init : State
|
||||
init =
|
||||
{}
|
||||
{ control =
|
||||
ControlExtra.list
|
||||
|> ControlExtra.optionalListItem "paddingPx" controlPaddingPx
|
||||
|> ControlExtra.optionalListItem "css" controlCss
|
||||
|> ControlExtra.listItem "content" controlContent
|
||||
}
|
||||
|
||||
|
||||
controlPaddingPx : Control (Container.Attribute msg)
|
||||
controlPaddingPx =
|
||||
Control.map Container.paddingPx (ControlExtra.float 20)
|
||||
|
||||
|
||||
controlCss : Control (Container.Attribute msg)
|
||||
controlCss =
|
||||
Control.map Container.css
|
||||
(Control.value
|
||||
[ Css.minHeight (Css.px 100)
|
||||
, Css.hover [ Css.backgroundColor Colors.glacier ]
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
controlContent : Control (Container.Attribute msg)
|
||||
controlContent =
|
||||
Control.choice
|
||||
[ ( "plain text (short)"
|
||||
, Control.string "Content, content..."
|
||||
|> Control.map Container.plaintext
|
||||
)
|
||||
, ( "plain text (long)"
|
||||
, Control.stringTextarea romeoAndJulietQuotation
|
||||
|> Control.map Container.plaintext
|
||||
)
|
||||
, ( "markdown"
|
||||
, Control.string romeoAndJulietQuotation
|
||||
|> Control.map Container.markdown
|
||||
)
|
||||
, ( "HTML (short)"
|
||||
, Control.value
|
||||
(Container.html
|
||||
[ UiIcon.footsteps
|
||||
|> Svg.withHeight (Css.px 200)
|
||||
|> Svg.withColor Colors.grassland
|
||||
|> Svg.toHtml
|
||||
]
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
romeoAndJulietQuotation : String
|
||||
romeoAndJulietQuotation =
|
||||
"""
|
||||
Two households, both alike in dignity,
|
||||
In fair Verona, where we lay our scene,
|
||||
From ancient grudge break to new mutiny,
|
||||
Where civil blood makes civil hands unclean.
|
||||
From forth the fatal loins of these two foes
|
||||
A pair of star-cross’d lovers take their life;
|
||||
Whose misadventured piteous overthrows
|
||||
Do with their death bury their parents’ strife.
|
||||
The fearful passage of their death-mark’d love,
|
||||
And the continuance of their parents’ rage,
|
||||
Which, but their children’s end, nought could remove,
|
||||
Is now the two hours’ traffic of our stage;
|
||||
The which if you with patient ears attend,
|
||||
What here shall miss, our toil shall strive to mend.
|
||||
"""
|
||||
|
||||
|
||||
{-| -}
|
||||
type alias State =
|
||||
{}
|
||||
|
||||
|
||||
{-| -}
|
||||
type alias Msg =
|
||||
()
|
||||
type Msg
|
||||
= UpdateControl (Control (List (Container.Attribute Msg)))
|
||||
|
||||
|
||||
{-| -}
|
||||
update : Msg -> State -> ( State, Cmd Msg )
|
||||
update msg state =
|
||||
( state, Cmd.none )
|
||||
case msg of
|
||||
UpdateControl newControl ->
|
||||
( { state | control = newControl }, Cmd.none )
|
||||
|
@ -13,6 +13,7 @@
|
||||
"Nri.Ui.ClickableSvg.V2",
|
||||
"Nri.Ui.ClickableText.V3",
|
||||
"Nri.Ui.Container.V1",
|
||||
"Nri.Ui.Container.V2",
|
||||
"Nri.Ui.Colors.Extra",
|
||||
"Nri.Ui.Colors.V1",
|
||||
"Nri.Ui.Confetti.V2",
|
||||
|
Loading…
Reference in New Issue
Block a user