From 1de4dd062a2c5479859186edde578defcf6c4f31 Mon Sep 17 00:00:00 2001 From: Tessa Kelly Date: Mon, 25 Nov 2019 17:38:07 -0800 Subject: [PATCH 1/7] Begins adding examples for svgs --- styleguide-app/Examples/Svg.elm | 84 +++++++++++++++++++++++++++++++++ styleguide-app/NriModules.elm | 14 ++++++ 2 files changed, 98 insertions(+) create mode 100644 styleguide-app/Examples/Svg.elm diff --git a/styleguide-app/Examples/Svg.elm b/styleguide-app/Examples/Svg.elm new file mode 100644 index 00000000..5e42f887 --- /dev/null +++ b/styleguide-app/Examples/Svg.elm @@ -0,0 +1,84 @@ +module Examples.Svg exposing + ( Msg + , State + , example + , init + , update + ) + +{-| + +@docs Msg +@docs State +@docs example +@docs init +@docs update + +-} + +import Color exposing (Color) +import Examples.IconExamples as IconExamples +import Html.Styled as Html +import Html.Styled.Attributes as Attributes +import Html.Styled.Events as Events +import ModuleExample exposing (Category(..), ModuleExample) +import Nri.Ui.Colors.Extra exposing (fromCssColor, toCssColor) +import Nri.Ui.Colors.V1 as Colors +import Nri.Ui.Heading.V2 as Heading +import Nri.Ui.Select.V6 as Select +import Nri.Ui.Svg.V1 as Svg +import Nri.Ui.UiIcon.V1 as UiIcon + + +{-| -} +type Msg + = SetColor (Result String Color) + + +{-| -} +type alias State = + { color : Color + } + + +{-| -} +example : (Msg -> msg) -> State -> ModuleExample msg +example parentMessage state = + { name = "Nri.Ui.Svg.V1" + , category = Icons + , content = + [ Html.label [] + [ Html.text "Color: " + , Html.input + [ Attributes.type_ "color" + , Attributes.value (Color.toHex state.color) + , Events.onInput (SetColor << Color.fromHex) + ] + [] + |> Html.map parentMessage + ] + , UiIcon.newspaper + |> Svg.withColor (toCssColor state.color) + |> Svg.toHtml + ] + } + + +{-| -} +init : State +init = + { color = fromCssColor Colors.blue + } + + +{-| -} +update : Msg -> State -> ( State, Cmd Msg ) +update msg state = + case msg of + SetColor (Ok color) -> + ( { state | color = color } + , Cmd.none + ) + + SetColor (Err err) -> + ( state, Cmd.none ) diff --git a/styleguide-app/NriModules.elm b/styleguide-app/NriModules.elm index 0f63072f..d40215d6 100644 --- a/styleguide-app/NriModules.elm +++ b/styleguide-app/NriModules.elm @@ -24,6 +24,7 @@ import Examples.Select import Examples.Slide import Examples.SlideModal import Examples.SortableTable +import Examples.Svg import Examples.Table import Examples.Tabs import Examples.Text @@ -55,6 +56,7 @@ type alias ModuleStates = , slideModalExampleState : Examples.SlideModal.State , slideExampleState : Examples.Slide.State , sortableTableState : Examples.SortableTable.State + , svgState : Examples.Svg.State , tabsExampleState : Examples.Tabs.Tab , tooltipExampleState : Examples.Tooltip.State } @@ -78,6 +80,7 @@ init = , slideModalExampleState = Examples.SlideModal.init , slideExampleState = Examples.Slide.init , sortableTableState = Examples.SortableTable.init + , svgState = Examples.Svg.init , tabsExampleState = Examples.Tabs.First , tooltipExampleState = Examples.Tooltip.init } @@ -101,6 +104,7 @@ type Msg | SlideModalExampleMsg Examples.SlideModal.Msg | SlideExampleMsg Examples.Slide.Msg | SortableTableMsg Examples.SortableTable.Msg + | SvgMsg Examples.Svg.Msg | TabsExampleMsg Examples.Tabs.Tab | TooltipExampleMsg Examples.Tooltip.Msg | NoOp @@ -184,6 +188,15 @@ update outsideMsg moduleStates = in ( moduleStates, Cmd.none ) + SvgMsg msg -> + let + ( svgState, cmd ) = + Examples.Svg.update msg moduleStates.svgState + in + ( { moduleStates | svgState = svgState } + , Cmd.map SvgMsg cmd + ) + TableExampleMsg msg -> let ( tableExampleState, cmd ) = @@ -321,6 +334,7 @@ nriThemedModules model = , Examples.Slide.example SlideExampleMsg model.slideExampleState , Examples.SlideModal.example SlideModalExampleMsg model.slideModalExampleState , Examples.SortableTable.example SortableTableMsg model.sortableTableState + , Examples.Svg.example SvgMsg model.svgState , Examples.Table.example TableExampleMsg model.tableExampleState , Examples.Tabs.example TabsExampleMsg model.tabsExampleState , Examples.Text.example From f3999886b09bfa04f4159726b7f39c4aec52ef63 Mon Sep 17 00:00:00 2001 From: Tessa Kelly Date: Mon, 25 Nov 2019 17:58:50 -0800 Subject: [PATCH 2/7] Demo height and width controls --- src/Nri/Ui/Svg/V1.elm | 78 +++++++++++++++++++++++----- styleguide-app/Examples/Svg.elm | 92 +++++++++++++++++++++++++++------ 2 files changed, 141 insertions(+), 29 deletions(-) diff --git a/src/Nri/Ui/Svg/V1.elm b/src/Nri/Ui/Svg/V1.elm index c218ba62..4402ec14 100644 --- a/src/Nri/Ui/Svg/V1.elm +++ b/src/Nri/Ui/Svg/V1.elm @@ -1,13 +1,13 @@ module Nri.Ui.Svg.V1 exposing ( Svg - , withColor + , withColor, withLabel, withWidth, withHeight , fromHtml, toHtml ) {-| @docs Svg -@docs withColor +@docs withColor, withLabel, withWidth, withHeight @docs fromHtml, toHtml -} @@ -17,26 +17,78 @@ import Html.Styled as Html exposing (Html) import Html.Styled.Attributes as Attributes -{-| -} +{-| Opaque type describing a non-interactable Html element. +-} type Svg - = Svg (Html Never) - - -{-| -} -withColor : Color -> Svg -> Svg -withColor color (Svg svg) = - Svg (Html.span [ Attributes.css [ Css.color color ] ] [ svg ]) + = Svg + { icon : Html Never + , color : Maybe Color + , width : Maybe Css.Px + , height : Maybe Css.Px + , label : Maybe String + } {-| Tag html as being an svg. -} fromHtml : Html Never -> Svg -fromHtml = +fromHtml icon = Svg + { icon = icon + , color = Nothing + , height = Nothing + , width = Nothing + , label = Nothing + } + + +{-| -} +withColor : Color -> Svg -> Svg +withColor color (Svg record) = + Svg { record | color = Just color } + + +{-| -} +withLabel : String -> Svg -> Svg +withLabel label (Svg record) = + Svg { record | label = Just label } + + +{-| -} +withWidth : Css.Px -> Svg -> Svg +withWidth width (Svg record) = + Svg { record | width = Just width } + + +{-| -} +withHeight : Css.Px -> Svg -> Svg +withHeight height (Svg record) = + Svg { record | height = Just height } {-| Render an svg. -} toHtml : Svg -> Html msg -toHtml (Svg svg) = - Html.map never svg +toHtml (Svg record) = + let + css = + List.filterMap identity + [ Maybe.map Css.color record.color + , Maybe.map Css.width record.width + , Maybe.map Css.height record.height + ] + in + case css of + x :: xs -> + Html.div + [ Attributes.css + (css + ++ [ Css.display Css.inlineBlock + ] + ) + ] + [ Html.map never record.icon + ] + + [] -> + Html.map never record.icon diff --git a/styleguide-app/Examples/Svg.elm b/styleguide-app/Examples/Svg.elm index 5e42f887..bb0b7b88 100644 --- a/styleguide-app/Examples/Svg.elm +++ b/styleguide-app/Examples/Svg.elm @@ -17,6 +17,7 @@ module Examples.Svg exposing -} import Color exposing (Color) +import Css import Examples.IconExamples as IconExamples import Html.Styled as Html import Html.Styled.Attributes as Attributes @@ -30,23 +31,36 @@ import Nri.Ui.Svg.V1 as Svg import Nri.Ui.UiIcon.V1 as UiIcon -{-| -} -type Msg - = SetColor (Result String Color) - - -{-| -} -type alias State = - { color : Color - } - - {-| -} example : (Msg -> msg) -> State -> ModuleExample msg example parentMessage state = { name = "Nri.Ui.Svg.V1" , category = Icons , content = + [ viewSettings state + |> Html.map parentMessage + , Html.pre [] + [ [ "UiIcon.newspaper" + , " |> Svg.withColor " ++ Debug.toString (toCssColor state.color) + , " |> Svg.withWidth (Css.px " ++ String.fromFloat state.width ++ ")" + , " |> Svg.withHeight (Css.px " ++ String.fromFloat state.height ++ ")" + , " |> Svg.toHtml" + ] + |> String.join "\n" + |> Html.text + ] + , UiIcon.newspaper + |> Svg.withColor (toCssColor state.color) + |> Svg.withWidth (Css.px state.width) + |> Svg.withHeight (Css.px state.height) + |> Svg.toHtml + ] + } + + +viewSettings : State -> Html.Html Msg +viewSettings state = + Html.div [] [ Html.label [] [ Html.text "Color: " , Html.input @@ -55,22 +69,56 @@ example parentMessage state = , Events.onInput (SetColor << Color.fromHex) ] [] - |> Html.map parentMessage ] - , UiIcon.newspaper - |> Svg.withColor (toCssColor state.color) - |> Svg.toHtml + , Html.label [] + [ Html.text "Width: " + , Html.input + [ Attributes.type_ "range" + , Attributes.min "0" + , Attributes.max "200" + , Attributes.value (String.fromFloat state.width) + , Events.onInput (SetWidth << String.toFloat) + ] + [] + ] + , Html.label [] + [ Html.text "Height: " + , Html.input + [ Attributes.type_ "range" + , Attributes.min "0" + , Attributes.max "200" + , Attributes.value (String.fromFloat state.height) + , Events.onInput (SetHeight << String.toFloat) + ] + [] + ] ] - } {-| -} init : State init = { color = fromCssColor Colors.blue + , width = 30 + , height = 30 } +{-| -} +type alias State = + { color : Color + , width : Float + , height : Float + } + + +{-| -} +type Msg + = SetColor (Result String Color) + | SetWidth (Maybe Float) + | SetHeight (Maybe Float) + + {-| -} update : Msg -> State -> ( State, Cmd Msg ) update msg state = @@ -82,3 +130,15 @@ update msg state = SetColor (Err err) -> ( state, Cmd.none ) + + SetWidth (Just width) -> + ( { state | width = width }, Cmd.none ) + + SetWidth Nothing -> + ( state, Cmd.none ) + + SetHeight (Just height) -> + ( { state | height = height }, Cmd.none ) + + SetHeight Nothing -> + ( state, Cmd.none ) From bd71eb9f595e3fde3b032b7c00cf5e08647700d3 Mon Sep 17 00:00:00 2001 From: Tessa Kelly Date: Mon, 25 Nov 2019 18:08:40 -0800 Subject: [PATCH 3/7] Adds aria-label helper --- src/Nri/Ui/Svg/V1.elm | 29 ++++++++++++++++++++++------- styleguide-app/Examples/Svg.elm | 32 ++++++++++++++++++++++++-------- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/Nri/Ui/Svg/V1.elm b/src/Nri/Ui/Svg/V1.elm index 4402ec14..7c5faa37 100644 --- a/src/Nri/Ui/Svg/V1.elm +++ b/src/Nri/Ui/Svg/V1.elm @@ -12,6 +12,7 @@ module Nri.Ui.Svg.V1 exposing -} +import Accessibility.Styled.Widget as Widget import Css exposing (Color) import Html.Styled as Html exposing (Html) import Html.Styled.Attributes as Attributes @@ -78,17 +79,31 @@ toHtml (Svg record) = , Maybe.map Css.height record.height ] in - case css of - x :: xs -> + case ( css, record.label ) of + ( x :: xs, Just label ) -> Html.div [ Attributes.css - (css - ++ [ Css.display Css.inlineBlock - ] - ) + (css ++ [ Css.display Css.inlineBlock ]) + , Widget.label label ] [ Html.map never record.icon ] - [] -> + ( x :: xs, Nothing ) -> + Html.div + [ Attributes.css + (css ++ [ Css.display Css.inlineBlock ]) + ] + [ Html.map never record.icon + ] + + ( [], Just label ) -> + Html.div + [ Widget.label label + , Attributes.css [ Css.display Css.inlineBlock ] + ] + [ Html.map never record.icon + ] + + ( [], Nothing ) -> Html.map never record.icon diff --git a/styleguide-app/Examples/Svg.elm b/styleguide-app/Examples/Svg.elm index bb0b7b88..8e8ace2e 100644 --- a/styleguide-app/Examples/Svg.elm +++ b/styleguide-app/Examples/Svg.elm @@ -44,6 +44,7 @@ example parentMessage state = , " |> Svg.withColor " ++ Debug.toString (toCssColor state.color) , " |> Svg.withWidth (Css.px " ++ String.fromFloat state.width ++ ")" , " |> Svg.withHeight (Css.px " ++ String.fromFloat state.height ++ ")" + , " |> Svg.withLabel \"" ++ state.label ++ "\"" , " |> Svg.toHtml" ] |> String.join "\n" @@ -53,6 +54,7 @@ example parentMessage state = |> Svg.withColor (toCssColor state.color) |> Svg.withWidth (Css.px state.width) |> Svg.withHeight (Css.px state.height) + |> Svg.withLabel state.label |> Svg.toHtml ] } @@ -92,23 +94,33 @@ viewSettings state = ] [] ] + , Html.label [] + [ Html.text "Aria-label: " + , Html.input + [ Attributes.value state.label + , Events.onInput SetLabel + ] + [] + ] ] +{-| -} +type alias State = + { color : Color + , width : Float + , height : Float + , label : String + } + + {-| -} init : State init = { color = fromCssColor Colors.blue , width = 30 , height = 30 - } - - -{-| -} -type alias State = - { color : Color - , width : Float - , height : Float + , label = "Newspaper" } @@ -117,6 +129,7 @@ type Msg = SetColor (Result String Color) | SetWidth (Maybe Float) | SetHeight (Maybe Float) + | SetLabel String {-| -} @@ -142,3 +155,6 @@ update msg state = SetHeight Nothing -> ( state, Cmd.none ) + + SetLabel label -> + ( { state | label = label }, Cmd.none ) From fbc461b3feff848058c90e41efe539fd8d447874 Mon Sep 17 00:00:00 2001 From: Tessa Kelly Date: Mon, 25 Nov 2019 18:18:11 -0800 Subject: [PATCH 4/7] Improve styling a touch --- styleguide-app/Examples/Svg.elm | 61 +++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/styleguide-app/Examples/Svg.elm b/styleguide-app/Examples/Svg.elm index 8e8ace2e..b1cd4222 100644 --- a/styleguide-app/Examples/Svg.elm +++ b/styleguide-app/Examples/Svg.elm @@ -39,30 +39,19 @@ example parentMessage state = , content = [ viewSettings state |> Html.map parentMessage - , Html.pre [] - [ [ "UiIcon.newspaper" - , " |> Svg.withColor " ++ Debug.toString (toCssColor state.color) - , " |> Svg.withWidth (Css.px " ++ String.fromFloat state.width ++ ")" - , " |> Svg.withHeight (Css.px " ++ String.fromFloat state.height ++ ")" - , " |> Svg.withLabel \"" ++ state.label ++ "\"" - , " |> Svg.toHtml" - ] - |> String.join "\n" - |> Html.text - ] - , UiIcon.newspaper - |> Svg.withColor (toCssColor state.color) - |> Svg.withWidth (Css.px state.width) - |> Svg.withHeight (Css.px state.height) - |> Svg.withLabel state.label - |> Svg.toHtml + , viewResults state ] } viewSettings : State -> Html.Html Msg viewSettings state = - Html.div [] + Html.div + [ Attributes.css + [ Css.displayFlex + , Css.justifyContent Css.spaceBetween + ] + ] [ Html.label [] [ Html.text "Color: " , Html.input @@ -105,6 +94,42 @@ viewSettings state = ] +viewResults : State -> Html.Html msg +viewResults state = + Html.div [ Attributes.css [ Css.displayFlex ] ] + [ Html.pre + [ Attributes.css + [ Css.width (Css.px 400) + , Css.marginRight (Css.px 20) + , Css.overflow Css.scroll + ] + ] + [ [ "UiIcon.newspaper" + , " |> Svg.withColor " ++ Debug.toString (toCssColor state.color) + , " |> Svg.withWidth (Css.px " ++ String.fromFloat state.width ++ ")" + , " |> Svg.withHeight (Css.px " ++ String.fromFloat state.height ++ ")" + , " |> Svg.withLabel \"" ++ state.label ++ "\"" + , " |> Svg.toHtml" + ] + |> String.join "\n" + |> Html.text + ] + , Html.div + [ Attributes.css + [ Css.backgroundColor Colors.gray92 + , Css.flexGrow (Css.int 2) + ] + ] + [ UiIcon.newspaper + |> Svg.withColor (toCssColor state.color) + |> Svg.withWidth (Css.px state.width) + |> Svg.withHeight (Css.px state.height) + |> Svg.withLabel state.label + |> Svg.toHtml + ] + ] + + {-| -} type alias State = { color : Color From 7c13a8fa2d4ee87aadddf085afe2bdaf42bd5b09 Mon Sep 17 00:00:00 2001 From: Tessa Kelly Date: Tue, 26 Nov 2019 15:47:42 -0800 Subject: [PATCH 5/7] Adds docs --- src/Nri/Ui/Svg/V1.elm | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Nri/Ui/Svg/V1.elm b/src/Nri/Ui/Svg/V1.elm index 7c5faa37..c7715beb 100644 --- a/src/Nri/Ui/Svg/V1.elm +++ b/src/Nri/Ui/Svg/V1.elm @@ -49,7 +49,12 @@ withColor color (Svg record) = Svg { record | color = Just color } -{-| -} +{-| Add a string aria-label property to the element. + +See [Using the aria-label attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute) for +guidelines of when and how to use this attribute. + +-} withLabel : String -> Svg -> Svg withLabel label (Svg record) = Svg { record | label = Just label } From 0033e0dee275785785c47df7b77f5a66bba6d1f7 Mon Sep 17 00:00:00 2001 From: Tessa Kelly Date: Tue, 26 Nov 2019 15:54:07 -0800 Subject: [PATCH 6/7] :art: DRY toHtml --- src/Nri/Ui/Svg/V1.elm | 42 +++++++++++++++--------------------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/src/Nri/Ui/Svg/V1.elm b/src/Nri/Ui/Svg/V1.elm index c7715beb..927e9804 100644 --- a/src/Nri/Ui/Svg/V1.elm +++ b/src/Nri/Ui/Svg/V1.elm @@ -83,32 +83,20 @@ toHtml (Svg record) = , Maybe.map Css.width record.width , Maybe.map Css.height record.height ] + + attributes = + List.filterMap identity + [ if List.isEmpty css then + Nothing + + else + Just (Attributes.css (Css.display Css.inlineBlock :: css)) + , Maybe.map Widget.label record.label + ] in - case ( css, record.label ) of - ( x :: xs, Just label ) -> - Html.div - [ Attributes.css - (css ++ [ Css.display Css.inlineBlock ]) - , Widget.label label - ] - [ Html.map never record.icon - ] - - ( x :: xs, Nothing ) -> - Html.div - [ Attributes.css - (css ++ [ Css.display Css.inlineBlock ]) - ] - [ Html.map never record.icon - ] - - ( [], Just label ) -> - Html.div - [ Widget.label label - , Attributes.css [ Css.display Css.inlineBlock ] - ] - [ Html.map never record.icon - ] - - ( [], Nothing ) -> + case attributes of + [] -> Html.map never record.icon + + _ -> + Html.div attributes [ Html.map never record.icon ] From 1e6249fe41f136f1bd8f7ce7ab2e0c8f37049490 Mon Sep 17 00:00:00 2001 From: Tessa Kelly Date: Tue, 26 Nov 2019 16:03:26 -0800 Subject: [PATCH 7/7] Remove overflow from svg example --- styleguide-app/Examples/Svg.elm | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/styleguide-app/Examples/Svg.elm b/styleguide-app/Examples/Svg.elm index b1cd4222..ee278612 100644 --- a/styleguide-app/Examples/Svg.elm +++ b/styleguide-app/Examples/Svg.elm @@ -96,20 +96,30 @@ viewSettings state = viewResults : State -> Html.Html msg viewResults state = + let + ( red, green, blue ) = + Color.toRGB state.color + in Html.div [ Attributes.css [ Css.displayFlex ] ] [ Html.pre [ Attributes.css [ Css.width (Css.px 400) , Css.marginRight (Css.px 20) - , Css.overflow Css.scroll ] ] - [ [ "UiIcon.newspaper" - , " |> Svg.withColor " ++ Debug.toString (toCssColor state.color) - , " |> Svg.withWidth (Css.px " ++ String.fromFloat state.width ++ ")" - , " |> Svg.withHeight (Css.px " ++ String.fromFloat state.height ++ ")" - , " |> Svg.withLabel \"" ++ state.label ++ "\"" - , " |> Svg.toHtml" + [ [ "color : Css.Color" + , "color =" + , " Css.rgb " ++ String.fromFloat red ++ " " ++ String.fromFloat green ++ " " ++ String.fromFloat blue + , "" + , "" + , "renderedSvg : Svg " + , "renderedSvg = " + , " UiIcon.newspaper" + , " |> Svg.withColor color" + , " |> Svg.withWidth (Css.px " ++ String.fromFloat state.width ++ ")" + , " |> Svg.withHeight (Css.px " ++ String.fromFloat state.height ++ ")" + , " |> Svg.withLabel \"" ++ state.label ++ "\"" + , " |> Svg.toHtml" ] |> String.join "\n" |> Html.text