diff --git a/src/Nri/Ui/Header/V1.elm b/src/Nri/Ui/Header/V1.elm index a016349d0..546fc7c35 100644 --- a/src/Nri/Ui/Header/V1.elm +++ b/src/Nri/Ui/Header/V1.elm @@ -1,16 +1,42 @@ module Nri.Ui.Header.V1 exposing - ( view - , Attribute, aTagAttributes, extraContent, description, extraSubheadContent, customPageWidth, breadCrumbsLabel + ( view, Attribute + , aTagAttributes, customPageWidth, breadCrumbsLabel + , extraContent, description, extraNav + , extraSubheadContent ) {-| -@docs view -@docs Attribute, aTagAttributes, extraContent, description, extraSubheadContent, customPageWidth, breadCrumbsLabel + +## Changelog + + +### Patch changes + + - marked extraSubheadContent as deprecated + - added extraNav + +@docs view, Attribute + + +## Customize the header + +@docs aTagAttributes, customPageWidth, breadCrumbsLabel + + +## Add additional content to the header + +@docs extraContent, description, extraNav + + +### Deprecated, to be removed: + +@docs extraSubheadContent -} import Accessibility.Styled as Html exposing (Html) +import Accessibility.Styled.Aria as Aria import Css import Css.Media as Media import Html.Styled.Attributes exposing (css) @@ -41,6 +67,23 @@ extraContent value = {-| -} +extraNav : String -> List (Html msg) -> Attribute route msg +extraNav label value = + Attribute + (\soFar -> + { soFar + | extraNav = + if List.isEmpty value then + Nothing + + else + Just ( label, value ) + } + ) + + +{-| This attribute is unused and will be removed in the next version of Header. +-} extraSubheadContent : List (Html msg) -> Attribute route msg extraSubheadContent value = Attribute (\soFar -> { soFar | extraSubheadContent = value }) @@ -77,6 +120,7 @@ type alias Config route msg = , description : Maybe String , pageWidth : Css.Px , breadCrumbsLabel : String + , extraNav : Maybe ( String, List (Html msg) ) } @@ -90,6 +134,7 @@ customize = , description = Nothing , pageWidth = MediaQuery.mobileBreakpoint , breadCrumbsLabel = "breadcrumbs" + , extraNav = Nothing } @@ -105,11 +150,35 @@ view attrs { breadCrumbs, isCurrentRoute } = let config = customize attrs + + ( extraContent_, extraNav_ ) = + -- when there's no content in the "extra content" hole to the right of the breadcrumbs, + -- put the extra nav there. If there is content there, put the links directly above the description. + case config.extraContent of + [] -> + ( [ viewJust (viewExtraNav []) config.extraNav ] + , Html.text "" + ) + + _ -> + ( config.extraContent + , viewJust + (viewExtraNav + [ Spacing.centeredContentWithSidePaddingAndCustomWidth config.pageWidth + ] + ) + config.extraNav + ) in Html.div [ css [ Css.backgroundColor Colors.gray96 , Css.borderBottom3 (Css.px 1) Css.solid Colors.gray92 + , Css.paddingTop (Css.px 30) + , Css.paddingBottom (Css.px 20) + , Media.withMedia [ MediaQuery.mobile ] + [ Css.important (Css.padding2 (Css.px 20) (Css.px 15)) + ] ] , AttributesExtra.nriDescription "Nri-Header" ] @@ -118,12 +187,7 @@ view attrs { breadCrumbs, isCurrentRoute } = [ Spacing.centeredContentWithSidePaddingAndCustomWidth config.pageWidth , Css.alignItems Css.center , Css.displayFlex - , Css.paddingTop (Css.px 30) - , Css.paddingBottom (Css.px 20) - , Media.withMedia [ MediaQuery.mobile ] - [ Css.important (Css.padding2 (Css.px 20) (Css.px 15)) - , Css.flexDirection Css.column - ] + , Media.withMedia [ MediaQuery.mobile ] [ Css.flexDirection Css.column ] ] :: config.containerAttributes ) @@ -144,8 +208,9 @@ view attrs { breadCrumbs, isCurrentRoute } = _ -> Html.div [] (breadcrumbsView :: config.extraSubheadContent) ] - :: config.extraContent + :: extraContent_ ) + , extraNav_ , viewJust (viewDescription config.pageWidth) config.description ] @@ -157,7 +222,28 @@ viewDescription pageWidth description_ = [ Spacing.centeredContentWithSidePaddingAndCustomWidth pageWidth , Css.color Colors.gray45 , Css.important (Css.margin Css.auto) - , Css.important (Css.paddingBottom (Css.px 20)) + , Css.important (Css.paddingTop (Css.px 20)) ] , Text.plaintext description_ ] + + +viewExtraNav : List Css.Style -> ( String, List (Html msg) ) -> Html msg +viewExtraNav styles ( label, values ) = + Html.nav [ Aria.label label, css styles ] + [ Html.ul + [ css + [ Css.margin Css.zero + , Css.padding Css.zero + , Css.displayFlex + , Css.alignItems Css.center + , Css.justifyContent Css.flexStart + , Css.flexWrap Css.wrap + , Css.property "column-gap" (.value Spacing.horizontalSpacerPx) + ] + ] + (List.map + (\i -> Html.li [ css [ Css.listStyle Css.none ] ] [ i ]) + values + ) + ] diff --git a/styleguide-app/App.elm b/styleguide-app/App.elm index 89e6c8187..fcd0c83ba 100644 --- a/styleguide-app/App.elm +++ b/styleguide-app/App.elm @@ -18,6 +18,7 @@ import InputMethod exposing (InputMethod) import Json.Decode as Decode import Nri.Ui.CssVendorPrefix.V1 as VendorPrefixed import Nri.Ui.FocusRing.V1 as FocusRing +import Nri.Ui.Header.V1 as Header import Nri.Ui.MediaQuery.V1 exposing (mobile) import Nri.Ui.Page.V3 as Page import Nri.Ui.SideNav.V4 as SideNav @@ -277,10 +278,7 @@ viewExample : Model key -> Example a Examples.Msg -> Html Msg viewExample model example = Example.view { packageDependencies = model.elliePackageDependencies } example |> Html.map (UpdateModuleStates example.name) - |> viewLayout model - [ Example.extraLinks example - |> Html.map (UpdateModuleStates example.name) - ] + |> viewLayout model [ Example.extraLinks (UpdateModuleStates example.name) example ] notFound : Html Msg @@ -319,7 +317,7 @@ viewCategory model category = ) -viewLayout : Model key -> List (Html Msg) -> Html Msg -> Html Msg +viewLayout : Model key -> List (Header.Attribute (Routes.Route Examples.State Examples.Msg) Msg) -> Html Msg -> Html Msg viewLayout model headerExtras content = Html.div [] [ Routes.viewHeader model.route headerExtras diff --git a/styleguide-app/CommonControls.elm b/styleguide-app/CommonControls.elm index c75a9c191..95c702dc6 100644 --- a/styleguide-app/CommonControls.elm +++ b/styleguide-app/CommonControls.elm @@ -6,7 +6,7 @@ module CommonControls exposing , customIcon , specificColor , string - , content, exampleHtml + , content , httpError, badBodyString , guidanceAndErrorMessage , disabledListItem, premiumDisplay @@ -25,7 +25,7 @@ module CommonControls exposing ### Content @docs string -@docs content, exampleHtml +@docs content @docs httpError, badBodyString @docs guidanceAndErrorMessage diff --git a/styleguide-app/Example.elm b/styleguide-app/Example.elm index efd58e2ee..630ac66eb 100644 --- a/styleguide-app/Example.elm +++ b/styleguide-app/Example.elm @@ -2,7 +2,7 @@ module Example exposing (Example, extraLinks, fullName, preview, view, wrapMsg, import Accessibility.Styled.Aria as Aria import Category exposing (Category) -import Css exposing (..) +import Css import EllieLink import Html.Styled as Html exposing (Html) import Html.Styled.Attributes as Attributes @@ -12,6 +12,9 @@ import KeyboardSupport exposing (KeyboardSupport) import Nri.Ui.ClickableText.V3 as ClickableText import Nri.Ui.Colors.V1 as Colors import Nri.Ui.Container.V2 as Container +import Nri.Ui.Header.V1 as Header +import Nri.Ui.Svg.V1 as Svg +import Nri.Ui.UiIcon.V1 as UiIcon type alias Example state msg = @@ -154,33 +157,15 @@ view_ ellieLinkConfig example = ] -extraLinks : Example state msg -> Html msg -extraLinks example = - Html.nav [ Aria.label (fullName example) ] - [ Html.ul - [ Attributes.css - [ margin zero - , padding zero - , displayFlex - , alignItems center - , justifyContent flexStart - , flexWrap Css.wrap - ] - ] - (List.map - (\i -> - Html.li - [ Attributes.css - [ Css.listStyle Css.none ] - ] - [ i ] - ) - [ docsLink example, srcLink example ] - ) +extraLinks : (msg -> msg2) -> Example state msg -> Header.Attribute route msg2 +extraLinks f example = + Header.extraNav (fullName example) + [ Html.map f (docsLink example) + , Html.map f (srcLink example) ] -docsLink : Example state msg -> Html msg +docsLink : Example state msg -> Html msg2 docsLink example = let link = @@ -189,10 +174,11 @@ docsLink example = in ClickableText.link "Docs" [ ClickableText.linkExternal link + , ClickableText.rightIcon (Svg.withLabel "Opens in a new tab" UiIcon.openInNewTab) ] -srcLink : Example state msg -> Html msg +srcLink : Example state msg -> Html msg2 srcLink example = let link = @@ -202,5 +188,5 @@ srcLink example = in ClickableText.link "Source" [ ClickableText.linkExternal link - , ClickableText.css [ Css.marginLeft (Css.px 20) ] + , ClickableText.rightIcon (Svg.withLabel "Opens in a new tab" UiIcon.openInNewTab) ] diff --git a/styleguide-app/Examples/Header.elm b/styleguide-app/Examples/Header.elm index 45f61486c..346fe5d7e 100644 --- a/styleguide-app/Examples/Header.elm +++ b/styleguide-app/Examples/Header.elm @@ -9,7 +9,6 @@ module Examples.Header exposing (example, State, Msg) import Accessibility.Styled.Role as Role import Category exposing (Category(..)) import Code -import CommonControls import Css import Debug.Control as Control exposing (Control) import Debug.Control.Extra as ControlExtra @@ -18,10 +17,12 @@ import Example exposing (Example) import Html.Styled exposing (..) import Html.Styled.Attributes exposing (css) import Nri.Ui.BreadCrumbs.V2 as BreadCrumbs +import Nri.Ui.ClickableText.V3 as ClickableText import Nri.Ui.Colors.V1 as Colors import Nri.Ui.Fonts.V1 as Fonts import Nri.Ui.Header.V1 as Header import Nri.Ui.Heading.V3 as Heading +import Nri.Ui.Select.V8 as Select import Nri.Ui.Svg.V1 as Svg import Nri.Ui.UiIcon.V1 as UiIcon @@ -43,7 +44,7 @@ example = , version = version , categories = [ Layout ] , keyboardSupport = [] - , state = init + , state = init Nothing , update = update , subscriptions = \_ -> Sub.none , preview = [ viewPreview ] @@ -143,17 +144,45 @@ viewPreview = {-| -} type alias State = { control : Control Settings + , selection : Maybe String } -init : State -init = +init : Maybe String -> State +init selection = { control = ControlExtra.list |> ControlExtra.optionalListItem "extraContent" (Control.value ( "Header.extraContent [ Html.text \"…\" ]" - , Header.extraContent CommonControls.exampleHtml + , Header.extraContent + [ Select.view "Tortilla Selector" + [ Select.choices identity + [ { label = "Tacos", value = "tacos" } + , { label = "Burritos", value = "burritos" } + , { label = "Enchiladas", value = "enchiladas" } + ] + , Select.value selection + ] + |> map Select + ] + ) + ) + |> ControlExtra.optionalListItem "extraNav" + (Control.value + ( Code.fromModule "Header" "extraNav " + ++ Code.string "Resources" + ++ Code.listMultiline + [ Code.fromModule "ClickableText" "link " ++ Code.string "Zendesk" ++ " []" + , Code.fromModule "ClickableText" "link " ++ Code.string "FAQ" ++ " []" + , Code.fromModule "ClickableText" "link " ++ Code.string "About" ++ " []" + ] + 2 + , Header.extraNav "Resources" + [ ClickableText.link "Zendesk" [] + , ClickableText.link "FAQ" [] + , ClickableText.link "About" [] + ] ) ) |> ControlExtra.optionalListItem "description" @@ -165,12 +194,6 @@ init = ) (Control.string "This page has some good content.") ) - |> ControlExtra.optionalListItem "extraSubheadContent" - (Control.value - ( "Header.extraSubheadContent [ Html.text \"…\" ]" - , Header.extraSubheadContent CommonControls.exampleHtml - ) - ) |> ControlExtra.optionalListItem "customPageWidth" (Control.map (\width -> @@ -180,6 +203,7 @@ init = ) (ControlExtra.float 750) ) + , selection = Nothing } @@ -190,6 +214,7 @@ type alias Settings = {-| -} type Msg = UpdateControl (Control Settings) + | Select String update : Msg -> State -> ( State, Cmd Msg ) @@ -197,3 +222,6 @@ update msg state = case msg of UpdateControl settings -> ( { state | control = settings }, Cmd.none ) + + Select value -> + ( { state | selection = Just value }, Cmd.none ) diff --git a/styleguide-app/Routes.elm b/styleguide-app/Routes.elm index 350db1ae4..d76de0b8f 100644 --- a/styleguide-app/Routes.elm +++ b/styleguide-app/Routes.elm @@ -103,16 +103,17 @@ fromLocation examples location = |> Result.withDefault All -viewHeader : Route state msg -> List (Html msg2) -> Html msg2 +viewHeader : Route state msg -> List (Header.Attribute (Route state msg) msg2) -> Html msg2 viewHeader currentRoute extraContent = breadCrumbs currentRoute |> Maybe.map (\crumbs -> Header.view - [ Header.aTagAttributes (\r -> [ Attributes.href ("/" ++ toString r) ]) - , Header.extraContent extraContent - , Header.customPageWidth (Css.px 1400) - ] + ([ Header.aTagAttributes (\r -> [ Attributes.href ("/" ++ toString r) ]) + , Header.customPageWidth (Css.px 1400) + ] + ++ extraContent + ) { breadCrumbs = crumbs , isCurrentRoute = (==) currentRoute }