diff --git a/elm.json b/elm.json index 91ee75ee..a207cee7 100644 --- a/elm.json +++ b/elm.json @@ -71,6 +71,7 @@ "Nri.Ui.Tabs.V4", "Nri.Ui.Text.V2", "Nri.Ui.Text.V3", + "Nri.Ui.Text.V4", "Nri.Ui.Text.Writing.V1", "Nri.Ui.TextArea.V3", "Nri.Ui.TextArea.V4", diff --git a/src/Nri/Ui/Heading/V1.elm b/src/Nri/Ui/Heading/V1.elm index c6fc17e3..cbfd0352 100644 --- a/src/Nri/Ui/Heading/V1.elm +++ b/src/Nri/Ui/Heading/V1.elm @@ -5,8 +5,17 @@ module Nri.Ui.Heading.V1 exposing , view ) -{-| Headings such as you'd find in Nri.Ui.Text.V3, but customization options for -accessibility. +{-| Headings with customization options for accessibility. + + +## Understanding spacing + + - All text styles have a specific line-height. This is set so that when text + in the given style is long enough to wrap, the spacing between wrapped lines + looks good. + - No heading styles have padding. + - **Heading styles** do not have margin. It is up to the caller to add + appropriate margin to the layout. @docs Heading, heading diff --git a/src/Nri/Ui/Text/V3.elm b/src/Nri/Ui/Text/V3.elm index 6af295c1..82445342 100644 --- a/src/Nri/Ui/Text/V3.elm +++ b/src/Nri/Ui/Text/V3.elm @@ -46,12 +46,9 @@ make a new Text version, please remove them. -} -import Css exposing (..) -import Html.Styled exposing (..) -import Html.Styled.Attributes exposing (css) -import Nri.Ui.Colors.V1 exposing (..) -import Nri.Ui.Fonts.V1 as Fonts +import Html.Styled exposing (Html) import Nri.Ui.Heading.V1 as Heading +import Nri.Ui.Text.V4 as V4 {-| This is a Page Heading. @@ -97,117 +94,43 @@ smallHeading content = {-| This is some medium body copy. -} mediumBody : List (Html msg) -> Html msg -mediumBody content = - p - [ paragraphStyles - { font = Fonts.baseFont - , color = gray20 - , size = 18 - , lineHeight = 28 - , weight = 400 - , margin = 10 - } - ] - content +mediumBody = + V4.mediumBody {-| This is some small body copy. -} smallBody : List (Html msg) -> Html msg -smallBody content = - p - [ paragraphStyles - { font = Fonts.baseFont - , color = gray20 - , size = 15 - , lineHeight = 23 - , weight = 400 - , margin = 7 - } - ] - content +smallBody = + V4.smallBody {-| This is some small body copy but it's gray. -} smallBodyGray : List (Html msg) -> Html msg -smallBodyGray content = - p - [ paragraphStyles - { font = Fonts.baseFont - , color = gray45 - , size = 15 - , lineHeight = 23 - , weight = 400 - , margin = 7 - } - ] - content - - -paragraphStyles config = - css - [ config.font - , fontSize (px config.size) - , color config.color - , lineHeight (px config.lineHeight) - , fontWeight (int config.weight) - , padding zero - , textAlign left - , margin4 (px 0) (px 0) (px config.margin) (px 0) - , lastChild - [ margin zero - ] - ] +smallBodyGray = + V4.smallBodyGray {-| This is a little note or caption. -} caption : List (Html msg) -> Html msg -caption content = - p - [ paragraphStyles - { font = Fonts.baseFont - , color = gray45 - , size = 13 - , lineHeight = 18 - , weight = 400 - , margin = 5 - } - ] - content +caption = + V4.caption {-| User-generated text. -} ugMediumBody : List (Html msg) -> Html msg ugMediumBody = - p - [ css - [ Fonts.quizFont - , fontSize (px 18) - , lineHeight (px 30) - , whiteSpace preLine - , color gray20 - , margin zero - ] - ] + V4.ugMediumBody {-| User-generated text. -} ugSmallBody : List (Html msg) -> Html msg ugSmallBody = - p - [ css - [ Fonts.quizFont - , fontSize (px 16) - , lineHeight (px 25) - , whiteSpace preLine - , color gray20 - , margin zero - ] - ] + V4.ugSmallBody {-| Eliminate widows (single words on their own line caused by @@ -215,29 +138,5 @@ wrapping) by inserting a non-breaking space if there are at least two words. -} noWidow : String -> String -noWidow inputs = - let - -- this value is a unicode non-breaking space since Elm - -- doesn't support named character entities - nbsp = - "\u{00A0}" - - words = - String.split " " inputs - - insertPoint = - List.length words - 1 - in - words - |> List.indexedMap - (\i word -> - if i == 0 then - word - - else if i == insertPoint && insertPoint > 0 then - nbsp ++ word - - else - " " ++ word - ) - |> String.join "" +noWidow = + V4.noWidow diff --git a/src/Nri/Ui/Text/V4.elm b/src/Nri/Ui/Text/V4.elm new file mode 100644 index 00000000..210ff253 --- /dev/null +++ b/src/Nri/Ui/Text/V4.elm @@ -0,0 +1,193 @@ +module Nri.Ui.Text.V4 exposing + ( caption, mediumBody, smallBody, smallBodyGray + , ugMediumBody, ugSmallBody + , noWidow + ) + +{-| Changes from V3: + + - Removes Headings (they now live in Nri.Ui.Heading.V1) + + +## Understanding spacing + + - All text styles have a specific line-height. This is set so that when text in the given style + is long enough to wrap, the spacing between wrapped lines looks good. + - No text styles have padding. + - **Heading styles** do not have margin. It is up to the caller to add appropriate margin to the layout. + - **Paragraph styles** only have bottom margin, but with **:last-child bottom margin set to zero**. + This bottom margin is set to look good when multiple paragraphs of the same style follow one another. + - If you want content after the paragraph and don't want the margin, put the paragraph in a `div` so that it will be the last-child, which will get rid of the bottom margin. + - **User-authored content blocks** preserve line breaks and do not have margin. + + +## Paragraph styles + +@docs caption, mediumBody, smallBody, smallBodyGray + + +## User-authored content blocks: + +@docs ugMediumBody, ugSmallBody + + +## Modifying strings to display nicely: + +@docs noWidow + +-} + +import Css exposing (..) +import Html.Styled exposing (..) +import Html.Styled.Attributes exposing (css) +import Nri.Ui.Colors.V1 exposing (..) +import Nri.Ui.Fonts.V1 as Fonts + + +{-| This is some medium body copy. +-} +mediumBody : List (Html msg) -> Html msg +mediumBody content = + p + [ paragraphStyles + { font = Fonts.baseFont + , color = gray20 + , size = 18 + , lineHeight = 28 + , weight = 400 + , margin = 10 + } + ] + content + + +{-| This is some small body copy. +-} +smallBody : List (Html msg) -> Html msg +smallBody content = + p + [ paragraphStyles + { font = Fonts.baseFont + , color = gray20 + , size = 15 + , lineHeight = 23 + , weight = 400 + , margin = 7 + } + ] + content + + +{-| This is some small body copy but it's gray. +-} +smallBodyGray : List (Html msg) -> Html msg +smallBodyGray content = + p + [ paragraphStyles + { font = Fonts.baseFont + , color = gray45 + , size = 15 + , lineHeight = 23 + , weight = 400 + , margin = 7 + } + ] + content + + +paragraphStyles config = + css + [ config.font + , fontSize (px config.size) + , color config.color + , lineHeight (px config.lineHeight) + , fontWeight (int config.weight) + , padding zero + , textAlign left + , margin4 (px 0) (px 0) (px config.margin) (px 0) + , lastChild + [ margin zero + ] + ] + + +{-| This is a little note or caption. +-} +caption : List (Html msg) -> Html msg +caption content = + p + [ paragraphStyles + { font = Fonts.baseFont + , color = gray45 + , size = 13 + , lineHeight = 18 + , weight = 400 + , margin = 5 + } + ] + content + + +{-| User-generated text. +-} +ugMediumBody : List (Html msg) -> Html msg +ugMediumBody = + p + [ css + [ Fonts.quizFont + , fontSize (px 18) + , lineHeight (px 30) + , whiteSpace preLine + , color gray20 + , margin zero + ] + ] + + +{-| User-generated text. +-} +ugSmallBody : List (Html msg) -> Html msg +ugSmallBody = + p + [ css + [ Fonts.quizFont + , fontSize (px 16) + , lineHeight (px 25) + , whiteSpace preLine + , color gray20 + , margin zero + ] + ] + + +{-| Eliminate widows (single words on their own line caused by +wrapping) by inserting a non-breaking space if there are at least two +words. +-} +noWidow : String -> String +noWidow inputs = + let + -- this value is a unicode non-breaking space since Elm + -- doesn't support named character entities + nbsp = + "\u{00A0}" + + words = + String.split " " inputs + + insertPoint = + List.length words - 1 + in + words + |> List.indexedMap + (\i word -> + if i == 0 then + word + + else if i == insertPoint && insertPoint > 0 then + nbsp ++ word + + else + " " ++ word + ) + |> String.join "" diff --git a/styleguide-app/Examples/Button.elm b/styleguide-app/Examples/Button.elm index 6d4180ce..8cbe92a0 100644 --- a/styleguide-app/Examples/Button.elm +++ b/styleguide-app/Examples/Button.elm @@ -16,7 +16,6 @@ import Nri.Ui.AssetPath exposing (Asset) import Nri.Ui.Button.V9 as Button import Nri.Ui.Icon.V5 as Icon import Nri.Ui.Svg.V1 as NriSvg exposing (Svg) -import Nri.Ui.Text.V3 as Text {-| -} diff --git a/styleguide-app/Examples/ClickableText.elm b/styleguide-app/Examples/ClickableText.elm index 95e10511..27e929b0 100644 --- a/styleguide-app/Examples/ClickableText.elm +++ b/styleguide-app/Examples/ClickableText.elm @@ -15,7 +15,7 @@ import ModuleExample as ModuleExample exposing (Category(..), ModuleExample, Mod import Nri.Ui.ClickableText.V2 as ClickableText exposing (Size(..)) import Nri.Ui.Icon.V5 as Icon import Nri.Ui.Svg.V1 as NriSvg exposing (Svg) -import Nri.Ui.Text.V3 as Text +import Nri.Ui.Text.V4 as Text {-| -} diff --git a/styleguide-app/Examples/Icon.elm b/styleguide-app/Examples/Icon.elm index b2e9f433..0441a23f 100644 --- a/styleguide-app/Examples/Icon.elm +++ b/styleguide-app/Examples/Icon.elm @@ -13,8 +13,9 @@ import Html.Styled as Html exposing (Html) import Html.Styled.Attributes exposing (css, style, title) import ModuleExample exposing (Category(..), ModuleExample) import Nri.Ui.Colors.V1 exposing (..) +import Nri.Ui.Heading.V1 as Heading import Nri.Ui.Icon.V5 as Icon -import Nri.Ui.Text.V3 as Text +import Nri.Ui.Text.V4 as Text {-| -} @@ -128,7 +129,10 @@ viewIconSection : -> Html msg viewIconSection headerText icons = Html.section [] - [ Text.subHeading [ Html.text headerText ] + [ Heading.heading [ Html.text headerText ] + |> Heading.withDocumentLevel Heading.H2 + |> Heading.withVisualLevel Heading.Subhead + |> Heading.view , Html.div [ css [ Css.displayFlex, Css.flexWrap Css.wrap ] ] (List.map viewIcon icons) ] diff --git a/styleguide-app/Examples/Text.elm b/styleguide-app/Examples/Text.elm index 52fa2d65..b1f4d2ce 100644 --- a/styleguide-app/Examples/Text.elm +++ b/styleguide-app/Examples/Text.elm @@ -9,13 +9,13 @@ module Examples.Text exposing (example) import Html.Styled as Html import ModuleExample as ModuleExample exposing (Category(..), ModuleExample) import Nri.Ui.Heading.V1 as Heading exposing (DocumentLevel(..), VisualLevel(..), heading, withDocumentLevel, withVisualLevel) -import Nri.Ui.Text.V3 as Text +import Nri.Ui.Text.V4 as Text {-| -} example : ModuleExample msg example = - { name = "Nri.Ui.Text.V3 (with headers from Nri.Ui.Heading.V1)" + { name = "Nri.Ui.Text.V4 (with headers from Nri.Ui.Heading.V1)" , category = Text , content = let @@ -44,13 +44,19 @@ example = |> withDocumentLevel H4 |> Heading.view , Html.hr [] [] - , Text.heading [ Html.text "Paragraph styles" ] + , heading [ Html.text "Paragraph styles" ] + |> withVisualLevel Top + |> withDocumentLevel H2 + |> Heading.view , Text.mediumBody [ Html.text <| "This is a mediumBody. " ++ longerBody ] , Text.smallBody [ Html.text <| "This is a smallBody. " ++ longerBody ] , Text.smallBodyGray [ Html.text <| "This is a smallBodyGray. " ++ longerBody ] , Text.caption [ Html.text <| "This is a caption. " ++ longerBody ] , Html.hr [] [] - , Text.heading [ Html.text "Paragraph styles for user-authored content" ] + , heading [ Html.text "Paragraph styles for user-authored content" ] + |> withVisualLevel Top + |> withDocumentLevel H2 + |> Heading.view , Text.ugMediumBody [ Html.text <| "This is an ugMediumBody. " ++ longerBody ] , Text.ugSmallBody [ Html.text <| "This is an ugSmallBody. " ++ longerBody ] ] diff --git a/styleguide-app/Examples/TextArea.elm b/styleguide-app/Examples/TextArea.elm index 37d323ce..4fd075ed 100644 --- a/styleguide-app/Examples/TextArea.elm +++ b/styleguide-app/Examples/TextArea.elm @@ -11,7 +11,7 @@ import Html.Styled as Html import ModuleExample as ModuleExample exposing (Category(..), ModuleExample) import Nri.Ui.AssetPath exposing (Asset(..)) import Nri.Ui.Checkbox.V5 as Checkbox -import Nri.Ui.Text.V3 as Text +import Nri.Ui.Heading.V1 as Heading import Nri.Ui.TextArea.V4 as TextArea @@ -38,7 +38,10 @@ example parentMessage state = { name = "Nri.Ui.TextArea.V4" , category = Inputs , content = - [ Text.heading [ Html.text "Textarea controls" ] + [ Heading.heading [ Html.text "Textarea controls" ] + |> Heading.withDocumentLevel Heading.H1 + |> Heading.withVisualLevel Heading.Top + |> Heading.view , Html.div [] [ Checkbox.viewWithLabel { identifier = "show-textarea-label" diff --git a/styleguide-app/Headings.elm b/styleguide-app/Headings.elm index f10c2a36..f134333c 100644 --- a/styleguide-app/Headings.elm +++ b/styleguide-app/Headings.elm @@ -1,29 +1,45 @@ module Headings exposing (h1, h2, h3, h4, h5) import Html.Styled exposing (Html) -import Nri.Ui.Text.V3 as Text +import Nri.Ui.Heading.V1 as Headings exposing (..) +import Nri.Ui.Text.V4 as Text h1 : List (Html msg) -> Html msg h1 = - Text.heading + heading + >> withVisualLevel Top + >> withDocumentLevel H1 + >> view h2 : List (Html msg) -> Html msg h2 = - Text.heading + heading + >> withVisualLevel Top + >> withDocumentLevel H2 + >> view h3 : List (Html msg) -> Html msg h3 = - Text.subHeading + heading + >> withVisualLevel Subhead + >> withDocumentLevel H3 + >> view h4 : List (Html msg) -> Html msg h4 = - Text.subHeading + heading + >> withVisualLevel Subhead + >> withDocumentLevel H4 + >> view h5 : List (Html msg) -> Html msg h5 = - Text.subHeading + heading + >> withVisualLevel Subhead + >> withDocumentLevel H5 + >> view