From 5d44e2da3fc6d02af58defaf00c24b743f6a022a Mon Sep 17 00:00:00 2001 From: Jasper Woudenberg Date: Tue, 16 Jan 2018 09:18:23 +0100 Subject: [PATCH] Implement new Outline styling This doesn't include the entire spec for the new outline styling, just the part we currently need for content creation outline draggable creation. The additions to complete the spec look doable in the current structure though. --- elm-package.json | 69 +++-- src/Nri/Effects.elm | 35 +++ src/Nri/Outline.elm | 518 ++++++++++++++++++++++++++----------- src/Nri/Outline/Styles.elm | 270 ------------------- src/Nri/Outline/Types.elm | 90 ------- src/Nri/Outline/Utils.elm | 392 ---------------------------- 6 files changed, 430 insertions(+), 944 deletions(-) create mode 100644 src/Nri/Effects.elm delete mode 100644 src/Nri/Outline/Styles.elm delete mode 100644 src/Nri/Outline/Types.elm delete mode 100644 src/Nri/Outline/Utils.elm diff --git a/elm-package.json b/elm-package.json index 8d1b7f85..1f385075 100644 --- a/elm-package.json +++ b/elm-package.json @@ -1,37 +1,36 @@ { - "version": "2.9.0", - "summary": "Doodads we use at NRI", - "repository": "https://github.com/NoRedInk/elm-doodad.git", - "license": "BSD3", - "source-directories": [ - "src" - ], - "exposed-modules": [ - "Nri.Alert", - "Nri.BannerAlert", - "Nri.Button", - "Nri.Divider", - "Nri.Modal", - "Nri.Outline", - "Nri.Outline.Types", - "Nri.Palette", - "Nri.Styles", - "Nri.Tabs", - "Nri.Text", - "Nri.TextAreaWithOverlappingLabel", - "Nri.TextInput" - ], - "dependencies": { - "NoRedInk/nri-elm-css": "5.0.0 <= v <= 5.0.0", - "NoRedInk/view-extra": "2.0.0 <= v < 3.0.0", - "elm-lang/core": "5.1.1 <= v < 6.0.0", - "elm-lang/html": "2.0.0 <= v < 3.0.0", - "pablohirafuji/elm-markdown": "2.0.4 <= v < 3.0.0", - "rtfeldman/elm-css": "11.2.0 <= v < 12.0.0", - "rtfeldman/elm-css-helpers": "2.1.0 <= v < 3.0.0", - "rtfeldman/elm-css-util": "1.0.2 <= v < 2.0.0", - "tesk9/accessible-html": "3.0.0 <= v < 4.0.0", - "wernerdegroot/listzipper": "3.0.0 <= v < 4.0.0" - }, - "elm-version": "0.18.0 <= v < 0.19.0" + "version": "2.9.0", + "summary": "Doodads we use at NRI", + "repository": "https://github.com/NoRedInk/elm-doodad.git", + "license": "BSD3", + "source-directories": [ + "src" + ], + "exposed-modules": [ + "Nri.Alert", + "Nri.BannerAlert", + "Nri.Button", + "Nri.Divider", + "Nri.Modal", + "Nri.Outline", + "Nri.Palette", + "Nri.Styles", + "Nri.Tabs", + "Nri.Text", + "Nri.TextAreaWithOverlappingLabel", + "Nri.TextInput" + ], + "dependencies": { + "NoRedInk/nri-elm-css": "5.0.0 <= v <= 5.0.0", + "NoRedInk/view-extra": "2.0.0 <= v < 3.0.0", + "elm-lang/core": "5.1.1 <= v < 6.0.0", + "elm-lang/html": "2.0.0 <= v < 3.0.0", + "pablohirafuji/elm-markdown": "2.0.4 <= v < 3.0.0", + "rtfeldman/elm-css": "11.2.0 <= v < 12.0.0", + "rtfeldman/elm-css-helpers": "2.1.0 <= v < 3.0.0", + "rtfeldman/elm-css-util": "1.0.2 <= v < 2.0.0", + "tesk9/accessible-html": "3.0.0 <= v < 4.0.0", + "wernerdegroot/listzipper": "3.0.0 <= v < 4.0.0" + }, + "elm-version": "0.18.0 <= v < 0.19.0" } diff --git a/src/Nri/Effects.elm b/src/Nri/Effects.elm new file mode 100644 index 00000000..47f2302f --- /dev/null +++ b/src/Nri/Effects.elm @@ -0,0 +1,35 @@ +module Nri.Effects exposing (selectionShadow) + +{-| Css mixins reused across Nri modules. + +@docs selectionShadow + +-} + +import Css exposing (..) +import Nri.Colors + + +{-| Draw a 2 px thick ochre border around the element to indicate it is +selected. + +This uses a CSS box shadow to draw what looks like a border. Box shadows are +perfect for this because they don't affect the elements positioning in any way. +This means we can be sure switching the selection shadow on and off is not +going to make the element jump. + +-} +selectionShadow : List Style +selectionShadow = + -- There should appear to be 2px of space between the element outline and + -- the surrounding selection border. To accomplish this we use two box + -- shadows, a inner white shadow and an outer ochre one. + -- Elm-css does not support multiple box shadows, so we build up that the + -- CSS value manually. + [ Css.property "box-shadow" ("0 0 0 2px white, 0 0 0 4px " ++ colorToString Nri.Colors.ochre) + ] + + +colorToString : Css.Color -> String +colorToString { red, green, blue } = + String.concat [ "rgb(", toString red, ",", toString green, ",", toString blue, ")" ] diff --git a/src/Nri/Outline.elm b/src/Nri/Outline.elm index f7367fdb..7e7a5392 100644 --- a/src/Nri/Outline.elm +++ b/src/Nri/Outline.elm @@ -1,181 +1,385 @@ -module Nri.Outline - exposing - ( OutlineLayout - , container - , customRow - , row - , rowWithExtraContent - , styles - , withEvaluated - , withTitle - ) +module Nri.Outline exposing (NodeConfig, NodeLayout, config, html, node, segment, styles) -{-| A nestedable layout that can be themed. - - -## Types - -@docs OutlineLayout - - -## Main container - -@docs container - - -## Rows - -@docs row, rowWithExtraContent, customRow - - -## Row modifiers - -@docs withTitle, withEvaluated - - -## Styles +{-| A module for rendering outline layouts. +@docs segment +@docs node +@docs NodeLayout +@docs NodeConfig +@docs config +@docs html @docs styles -} -import Html exposing (..) -import Nri.Outline.Styles as Styles exposing (styles) -import Nri.Outline.Types as Types -import Nri.Outline.Utils as Utils -import Nri.Styles +import Css exposing (Stylesheet) +import Html exposing (Attribute, Html) +import Nri.Colors +import Nri.Effects +import Nri.Palette exposing (Palette) +import Nri.Stylers +import Nri.Styles exposing (Styles) -{-| Aliased strictly for exporting +{-| A wrapper for a node rendered into Html. This type exists to prevent us +from accidentally wrapping a node in a container element before passing it as a +child to another node or segment. Such wrapping would break some of our +styling, which assumes nodes of the same level are sibblings in the Html tree. -} -type alias OutlineLayout msg = - Types.OutlineLayout msg +type NodeLayout msg + = NodeLayout (Html msg) -{-| The row container. This is required as it injects the styles for the rows into a style tag. +{-| A container to draw nodes in. - import Html exposing (..) - import Nri.Outline as Outline - - main : Html msg - main = - div [] - [ Outline.container - [{- Extra attributes go here -}] - [{- Rows go here -}] - ] + segment + [ node { config | label = "First Node" } + , node { config | label = "Second Node" } + ] -} -container : List (Attribute msg) -> List (Types.OutlineLayout msg) -> Html msg -container attributes rows = - ul (attributes ++ [ styles.class [ Styles.Container ] ]) - (List.map (Utils.rowToHtml Types.Root) rows) +segment : List (NodeLayout msg) -> Html msg +segment children = + styles.div Segment (List.map unlayout children) -{-| Render an unstyled row with only the outline styles. +{-| Wrap any html in a NodeLayout so you can use it as sibling content to nodes. - import Html exposing (..) - import Nri.Outline as Outline + segment + [ node { config | label = "This is a node" } + , html (Html.text "This is some random Html content!") + ] - main : Html msg - main = - div [] - [ Outline.container [] - [ Outline.row - { content = text "This is my content" - , palette = Palette.red - , rows = [] - } +-} +html : Html msg -> NodeLayout msg +html child = + styles.div CustomHtml [ child ] + |> NodeLayout + + +{-| Defines how a node should look. +-} +type alias NodeConfig msg = + -- The node's label. + { label : Html msg + + -- The content of the node (the part in the colored area). + , contents : Html msg + + -- Child nodes (and other content) to be placed below the content. + , children : List (NodeLayout msg) + + -- The node is selected. Draw a selection shadow around it. + , selected : Bool + + -- The node is ghosted. Fade it out. + , ghosted : Bool + + -- Addition attributes to be set on the top level node element. + , attrs : List (Html.Attribute msg) + } + + +{-| A default node configuration, allowing you to only set the properties you care about. + + node { config | label = "Claim" } + +-} +config : NodeConfig msg +config = + { label = Html.text "" + , contents = Html.text "" + , children = [] + , selected = False + , ghosted = False + , attrs = [] + } + + +{-| Draw a node of an outline structure. You can draw other nodes inside it and +connecting lines will appear. + + node { config | label = "Claim" } + +-} +node : NodeConfig msg -> NodeLayout msg +node { label, contents, children, selected, attrs, ghosted } = + NodeLayout <| + -- We use a custom Html tag name here, to ensure we can find the first and + -- last node in a last-of-type selector. + Html.node "outline-node" + (styles.classList + [ ( Node, True ) + , ( GhostedNode, ghosted ) ] - ] - --} -row : Types.RowConfig msg -> Types.OutlineLayout msg -row config = - Types.Row <| Utils.rawRow config - - -{-| -} -customRow : Types.CustomConfig msg -> Types.OutlineLayout msg -customRow config = - Types.Row config - - -{-| Render a row with extra content. This row cannot have child rows. - - import Html exposing (..) - import Nri.Outline as Outline - - main : Html msg - main = - div [] - [ Outline.container [] - [ Outline.rowWithExtraContent - { content = text "This is my content" - , palette = Palette.red - , extraContent = text "My extra content" - } + :: attrs + ) + [ Html.div + [ styles.classList + [ ( InnerNode, True ) + , ( SelectedNode, selected ) + ] ] + (styles.div Label [ label ] + :: styles.div Contents [ contents ] + :: List.map unlayout children + ) ] + +unlayout : NodeLayout msg -> Html msg +unlayout (NodeLayout html) = + html + + +type Style + = Segment + | Node + | InnerNode + | SelectedNode + | GhostedNode + | Label + | Contents + | CustomHtml + + +labelHeight : Float +labelHeight = + 35 + + +{-| Styles used by outline structures. -} -rowWithExtraContent : Types.ExtraContenRowConfig msg -> Types.OutlineLayout msg -rowWithExtraContent config = - Types.Row <| - Utils.rawRowWithExtraContent config - - -{-| Render a row with a title - - import Html exposing (..) - import Nri.Outline as Outline - - main : Html msg - main = - div [] - [ Outline.container [] - [ Outline.withTitle "My Title" <| - Outline.row - { content = text "This is my content" - , palette = Palette.red - , rows = [] - } - ] - ] - --} -withTitle : String -> Types.OutlineLayout msg -> Types.OutlineLayout msg -withTitle = - Utils.withTitle - - -{-| Render a row with 'good' emphasis - - import Html exposing (..) - import Nri.Outline as Outline - import Nri.Outline.Types as Types - - main : Html msg - main = - div [] - [ Outline.container [] - [ Outline.withEvaluated Types.Good <| - Outline.row - { content = text "This is my content" - , palette = Palette.red - , rows = [] - } - ] - ] - --} -withEvaluated : Types.Evaluation -> Types.OutlineLayout msg -> Types.OutlineLayout msg -withEvaluated = - Utils.withEvaluated - - -{-| Styles used by this module --} -styles : Nri.Styles.Styles Never Styles.CssClasses msg +styles : Styles a Style b styles = - Styles.styles + Nri.Styles.styles "Outline" <| + [ Css.class Segment + [ Css.position Css.relative + , Css.zIndex (Css.int 0) + + -- The overflow property cuts of connecting lines extending from + -- top level nodes. + , Css.overflow Css.auto + ] + , Css.class Node + -- The node's relative positioning allows the connecting line to + -- point upward relative from the node's bounding box. + [ Css.position Css.relative + , Css.display Css.block + + -- This selects all nodes on a level but the first. + , Css.generalSiblings + [ Css.class Node + -- Add some spacing between nodes of the same level. + [ Css.marginTop (Css.px 20) + , Css.before + [ Css.property "content" "''" + , Css.borderLeft2 (Css.px 1) Css.solid + , Css.batch lineStyles + ] + ] + ] + + -- Child nodes have a connecting line and are indented. + , Css.descendants nestedNodeStyles + ] + , Css.class InnerNode + [ Css.overflow Css.auto + + -- The position and zIndex create a new stacking context. Connecting + -- lines in child nodes of this one will be drawn in this context. + , Css.position Css.relative + , Css.zIndex (Css.int 0) + + -- Recursively assign color styles to the different nested levels of + -- the outline structure. + , Css.descendants + (colorStyles + [ Nri.Palette.cornflower + , Nri.Palette.aqua + , Nri.Palette.turquoise + , Nri.Palette.green + ] + ) + ] + , Css.class GhostedNode + [ Css.opacity (Css.num 0.5) + , Css.zIndex (Css.int -1) + , Css.position Css.relative + ] + , Css.class Label + [ Css.border2 (Css.px 1) Css.solid + , Css.padding2 Css.zero (Css.px 15) + , Css.fontSize (Css.px 15) + , Css.borderRadius (Css.px labelHeight) + , Css.lineHeight (Css.px (labelHeight - 3)) + , Css.height (Css.px labelHeight) + , Css.backgroundColor Nri.Colors.white + , Css.position Css.absolute + , Css.boxSizing Css.borderBox + , Css.top Css.zero + , Css.left Css.zero + , Nri.Stylers.makeFont (Css.px 15) Nri.Colors.gray20 + , Css.fontWeight Css.bold + ] + , Css.class Contents + [ Css.borderRadius (Css.px 8) + , Css.marginTop (Css.px (labelHeight / 2)) + , Css.marginLeft (Css.px (labelHeight / 2)) + , Css.minHeight (Css.px 70) + + -- Ensure there's some margin on all sides, so we have the option of + -- drawing a border around selected contents without it being cut of + -- by the surrounding inner node. + , Css.marginRight (Css.px 5) + , Css.marginBottom (Css.px 5) + ] + , Css.class SelectedNode + [ Css.children + [ Css.class Contents + [ Css.batch Nri.Effects.selectionShadow + ] + ] + ] + ] + ++ curvedConnectingLineStyles + + +nestedNodeStyles : List Css.Snippet +nestedNodeStyles = + [ Css.class Node + [ Css.marginTop (Css.px 20) + , Css.before + -- Draw the connect line. It is like an antenna pointing + -- upward in the direction of the parent node. + [ Css.property "content" "''" + , Css.borderLeft2 (Css.px 1) Css.solid + , Css.borderBottom2 (Css.px 1) Css.solid + , Css.batch lineStyles + ] + , Css.children + -- Indent this node relative to the parent. + [ Css.class InnerNode + [ Css.marginLeft (Css.px 50) + ] + ] + ] + , Css.class CustomHtml + [ Css.marginLeft (Css.px 50) + ] + ] + + +{-| The last node is sometimes connected by a curving line to its parent. +Whether this curve should appear or not depends on the level of the node. +-} +curvedConnectingLineStyles : List Css.Snippet +curvedConnectingLineStyles = + -- 1. Root level nodes are connected with one another using straight lines, + -- so they are never curved. + -- + -- Root Node 1 + -- │ + -- Root Node 2 + -- + -- 2. Second level nodes have a curved line when they are the last node of + -- their level, and if their parent is the last root node. If either + -- case is not true, they are connected to a straight line that + -- continues beneath then. This is illustrated in the diagram below. As + -- you can see only 'Child Node 3' should have a curved connecting line. + -- + -- Root Node 1 + -- │ + -- ├─ Child Node 1 + -- │ + -- Root Node 2 + -- │ + -- ├─ Child Node 2 + -- │ + -- ╰─ Child Node 3 + -- + [ Css.class Node + [ Css.lastOfType + [ Css.descendants + [ Css.class Node + [ Css.lastOfType + [ Css.before + [ Css.borderRadius (Css.px 8) + ] + ] + ] + ] + ] + ] + + -- 3. Third and lower level nodes always have a curved line when they are + -- the last node on their level. This is illustrated in the diagram + -- below. Sub-Child Node 2 has a curved connecting line, even though it's + -- parent node is not the last node on its level. + -- + -- Root Node + -- │ + -- ├─ Child Node 1 + -- │ │ + -- │ ├─ Sub-Child Node 1 + -- │ │ + -- │ ╰─ Sub-Child Node 2 + -- │ + -- ╰─ Child Node 2 + -- + , Css.class Node + [ Css.descendants + [ Css.class Node + [ Css.descendants + [ Css.class Node + [ Css.lastOfType + [ Css.before + [ Css.borderRadius (Css.px 8) + ] + ] + ] + ] + ] + ] + ] + ] + + +colorStyles : List Palette -> List Css.Snippet +colorStyles palettes = + case palettes of + [] -> + [] + + palette :: rest -> + [ Css.class InnerNode + [ Css.descendants (colorStyles rest) + ] + , Css.class Contents + [ Css.backgroundColor palette.background + ] + , Css.class Label + [ Css.color palette.primary + , Css.borderColor palette.border + ] + ] + + +lineStyles : List Css.Style +lineStyles = + [ Css.display Css.block + , Css.borderColor Nri.Colors.gray75 + , Css.position Css.absolute + , Css.width (Css.px 30) + , Css.left (Css.px 30) + , Css.bottom (Css.calc (Css.pct 100) Css.minus (Css.px (labelHeight / 2))) + + -- Ensure the connecting line is long enough. The containing element will + -- cut it to size. + , Css.height (Css.vh 10000) + + -- Make the connecting line go beneath the parent node, + -- giving the impression it stops when touching the + -- parent. + , Css.zIndex (Css.int -100) + ] diff --git a/src/Nri/Outline/Styles.elm b/src/Nri/Outline/Styles.elm deleted file mode 100644 index 0a75d2c3..00000000 --- a/src/Nri/Outline/Styles.elm +++ /dev/null @@ -1,270 +0,0 @@ -module Nri.Outline.Styles exposing (..) - -import Css exposing (..) -import Nri.Colors as Colors -import Nri.Css.Extra -import Nri.Fonts -import Nri.Palette as Palette exposing (Palette) -import Nri.Styles - - -type CssClasses - = Container - | Row - | ChildRow - | RowGray - | RowDarkGray - | RowBlue - | RowDarkBlue - | RowPurple - | RowTurquoise - | RowRed - | RowGreen - | RowWhite - | RowCornflower - | RowAqua - | RowPanelTitle - | RowPanelTitleGray - | RowPanelTitleDarkGray - | RowPanelTitleBlue - | RowPanelTitleDarkBlue - | RowPanelTitlePurple - | RowPanelTitleTurquoise - | RowPanelTitleRed - | RowPanelTitleGreen - | RowPanelTitleWhite - | RowPanelTitleCornflower - | RowPanelTitleAqua - | RowPanelContent - | RowPanelContentGray - | RowPanelContentCornflower - | RowPanelContentDarkGray - | RowPanelContentBlue - | RowPanelContentDarkBlue - | RowPanelContentPurple - | RowPanelContentTurquoise - | RowPanelContentRed - | RowPanelContentGreen - | RowPanelContentWhite - | RowPanelContentAqua - | RowPanelContentDashed - | ChildRowContent - | ChildRowContentCornflower - | ChildRowContentGray - | ChildRowContentDarkGray - | ChildRowContentBlue - | ChildRowContentDarkBlue - | ChildRowContentPurple - | ChildRowContentTurquoise - | ChildRowContentRed - | ChildRowContentGreen - | ChildRowContentWhite - | ChildRowContentAqua - | RowContent - | RowChildren - - -styles : Nri.Styles.Styles Never CssClasses msg -styles = - Nri.Styles.styles "Nri-Outline-" - [ Css.class Container - [ listStyle none - , margin zero - , padding zero - ] - - -- rows - , Css.class Row - [ paddingBottom (px 16) - , position relative - , lastChild [ paddingBottom zero ] - ] - , Css.class ChildRow - [ after - [ property "content" "''" - , position absolute - , top (px -16) - , left (px -14) - , width (px 14) - , borderLeft3 (px 1) solid (Palette.gray |> .border) - , property "height" "calc(100% + 16px)" - ] - , lastChild - [ after [ borderLeftWidth zero ] ] - , onlyChild - {- Fixes border styles if there is only one child row -} - [ after - [ property "content" "''" - , position absolute - , top (px -16) - , left (px -14) - , width (px 14) - , borderLeftWidth (px 1) - , borderLeftStyle solid - , property "height" "16px" - ] - ] - ] - , Css.class RowGray - [ rowTheme Palette.gray ] - , Css.class RowDarkGray - [ rowTheme Palette.darkGray ] - , Css.class RowBlue - [ rowTheme Palette.blue ] - , Css.class RowDarkBlue - [ rowTheme Palette.darkBlue ] - , Css.class RowPurple - [ rowTheme Palette.purple ] - , Css.class RowTurquoise - [ rowTheme Palette.turquoise ] - , Css.class RowRed - [ rowTheme Palette.red ] - , Css.class RowGreen - [ rowTheme Palette.green ] - , Css.class RowWhite - [ rowTheme Palette.white ] - , Css.class RowCornflower - [ rowTheme Palette.cornflower ] - , Css.class RowAqua - [ rowTheme Palette.aqua ] - - -- row panel titles - , Css.class RowPanelTitle - [ Nri.Fonts.baseFont - , borderRadius (px 16) - , color Colors.white - , display inlineBlock - , fontSize (px 12) - , height (px 16) - , left (px -4) - , lineHeight (px 16) - , padding2 zero (px 7) - , position absolute - , top (px -8) - , property "z-index" "2" - ] - , Css.class RowPanelTitleGray - [ rowPanelTitleTheme Palette.gray ] - , Css.class RowPanelTitleDarkGray - [ rowPanelTitleTheme Palette.darkGray ] - , Css.class RowPanelTitleBlue - [ rowPanelTitleTheme Palette.blue ] - , Css.class RowPanelTitleDarkBlue - [ rowPanelTitleTheme Palette.darkBlue ] - , Css.class RowPanelTitlePurple - [ rowPanelTitleTheme Palette.purple ] - , Css.class RowPanelTitleTurquoise - [ rowPanelTitleTheme Palette.turquoise ] - , Css.class RowPanelTitleRed - [ rowPanelTitleTheme Palette.red ] - , Css.class RowPanelTitleGreen - [ rowPanelTitleTheme Palette.green ] - , Css.class RowPanelTitleWhite - [ rowPanelTitleTheme Palette.white ] - , Css.class RowPanelTitleCornflower - [ rowPanelTitleTheme Palette.cornflower ] - , Css.class RowPanelTitleAqua - [ rowPanelTitleTheme Palette.aqua ] - , Css.class RowPanelContent - [ borderRadius (px 8) - , borderWidth (px 1) - , borderColor (Palette.gray |> .border) - , borderStyle solid - , backgroundColor (Palette.gray |> .background) - , color Colors.gray20 - , fontSize (px 18) - , Nri.Fonts.quizFont - , padding (px 13) - , Nri.Css.Extra.lineHeightNum 1.2 - ] - , Css.class RowPanelContentGray - [ rowPanelContentTheme Palette.gray ] - , Css.class RowPanelContentCornflower - [ rowPanelContentTheme Palette.cornflower ] - , Css.class RowPanelContentDarkGray - [ rowPanelContentTheme Palette.darkGray ] - , Css.class RowPanelContentBlue - [ rowPanelContentTheme Palette.blue ] - , Css.class RowPanelContentDarkBlue - [ rowPanelContentTheme Palette.darkBlue ] - , Css.class RowPanelContentPurple - [ rowPanelContentTheme Palette.purple ] - , Css.class RowPanelContentTurquoise - [ rowPanelContentTheme Palette.turquoise ] - , Css.class RowPanelContentRed - [ rowPanelContentTheme Palette.red ] - , Css.class RowPanelContentGreen - [ rowPanelContentTheme Palette.green ] - , Css.class RowPanelContentWhite - [ rowPanelContentTheme Palette.white ] - , Css.class RowPanelContentAqua - [ rowPanelContentTheme Palette.aqua ] - , Css.class RowPanelContentDashed - [ borderStyle dashed ] - , Css.class ChildRowContent - [ after - [ property "content" "''" - , height (pct 50) - , width (px 14) - , borderBottom3 (px 1) solid (Palette.gray |> .border) - , borderLeft3 (px 1) solid (Palette.gray |> .border) - , left (px -14) - , top zero - , position absolute - , maxHeight (px 50) - ] - ] - , Css.class ChildRowContentCornflower - [ childRowContentTheme Palette.cornflower ] - , Css.class ChildRowContentGray - [ childRowContentTheme Palette.gray ] - , Css.class ChildRowContentDarkGray - [ childRowContentTheme Palette.darkGray ] - , Css.class ChildRowContentBlue - [ childRowContentTheme Palette.blue ] - , Css.class ChildRowContentDarkBlue - [ childRowContentTheme Palette.darkBlue ] - , Css.class ChildRowContentPurple - [ childRowContentTheme Palette.purple ] - , Css.class ChildRowContentTurquoise - [ childRowContentTheme Palette.turquoise ] - , Css.class ChildRowContentRed - [ childRowContentTheme Palette.red ] - , Css.class ChildRowContentGreen - [ childRowContentTheme Palette.green ] - , Css.class ChildRowContentWhite - [ childRowContentTheme Palette.white ] - , Css.class ChildRowContentAqua - [ childRowContentTheme Palette.aqua ] - , Css.class RowContent - [ position relative ] - , Css.class RowChildren - [ paddingLeft (px 29) - , paddingTop (px 16) - , listStyleType none - ] - ] - - -rowTheme : Palette -> Style -rowTheme palette = - batch [ after [ borderColor palette.border ] ] - - -rowPanelTitleTheme : Palette -> Style -rowPanelTitleTheme palette = - Css.batch [ backgroundColor palette.border ] - - -childRowContentTheme : Palette -> Style -childRowContentTheme palette = - Css.batch [ after [ borderColor palette.border ] ] - - -rowPanelContentTheme : Palette -> Style -rowPanelContentTheme palette = - Css.batch - [ backgroundColor palette.background - , borderColor palette.border - , after [ borderColor palette.border ] - ] diff --git a/src/Nri/Outline/Types.elm b/src/Nri/Outline/Types.elm deleted file mode 100644 index ff40e9aa..00000000 --- a/src/Nri/Outline/Types.elm +++ /dev/null @@ -1,90 +0,0 @@ -module Nri.Outline.Types exposing (..) - -{-| - -@docs BaseConfig, CustomConfig, Evaluation, ExtraContenRowConfig, OutlineLayout, OutlinePanelConfig, RowConfig, RowModifier, RowVerticalAlignment, RowsContent, Hierarchy - --} - -import Html exposing (Html) -import Nri.Palette as Palette - - -{-| -} -type alias BaseConfig msg extras = - { extras - | content : Html msg - , palette : Palette.Palette - } - - -{-| -} -type alias CustomConfig msg = - BaseConfig msg - (RowsContent msg - { verticalAlign : RowVerticalAlignment - , extraContent : Maybe (Html msg) - , modifyRow : RowModifier - , hasDashedBorder : Bool - } - ) - - -{-| -} -type alias RowConfig msg = - BaseConfig msg (RowsContent msg {}) - - -{-| -} -type alias RowsContent msg extras = - { extras | rows : List (OutlineLayout msg) } - - -{-| -} -type alias ExtraContenRowConfig msg = - BaseConfig msg - { rows : List (OutlineLayout msg) - , extraContent : Html msg - } - - -{-| -} -type alias OutlinePanelConfig msg = - { title : String - , content : Html msg - , hasDashedBorder : Bool - , modifyRow : RowModifier - , palette : Palette.Palette - } - - -{-| This type also is used to give nice errors when passing invalid items to the rows field --} -type OutlineLayout msg - = Row (CustomConfig msg) - | KeyedRow String (CustomConfig msg) - - -{-| -} -type RowModifier - = NodeEvaluated Evaluation - | Normal - - -{-| The vertical alignment of the outline horizontal bar --} -type RowVerticalAlignment - = TopAlign - | MiddleAlign - - -{-| -} -type Evaluation - = Good - | Bad - - -{-| -} -type Hierarchy - = Root - | Child diff --git a/src/Nri/Outline/Utils.elm b/src/Nri/Outline/Utils.elm deleted file mode 100644 index c59f0693..00000000 --- a/src/Nri/Outline/Utils.elm +++ /dev/null @@ -1,392 +0,0 @@ -module Nri.Outline.Utils exposing (..) - -{-| - -@docs RowNodeType, keyedRowToHtml, outlinePanel, paletteOfFirst, rawRow, rawRowWithExtraContent, rowToHtml, toHtml, toKeyedHtml, toRowNodeType, viewExtraContent, viewRow, withEvaluated, withTitle - --} - -import Css exposing (..) -import Html exposing (..) -import Html.Attributes -import Html.Keyed -import Nri.Outline.Styles as Styles exposing (styles) -import Nri.Outline.Types as Types -import Nri.Palette as Palette - - -{-| -} -type RowNodeType msg - = Tag (Html msg) - | KeyedTag ( String, Html msg ) - - -{-| -} -withTitle : String -> Types.OutlineLayout msg -> Types.OutlineLayout msg -withTitle title taggedRow = - let - updatedConfig config = - { config - | content = - outlinePanel - { title = title - , content = config.content - , hasDashedBorder = config.hasDashedBorder - , palette = config.palette - , modifyRow = config.modifyRow - } - , verticalAlign = Types.TopAlign - } - in - case taggedRow of - Types.Row config -> - Types.Row <| updatedConfig config - - Types.KeyedRow key config -> - Types.KeyedRow key <| updatedConfig config - - -{-| -} -withEvaluated : Types.Evaluation -> Types.OutlineLayout msg -> Types.OutlineLayout msg -withEvaluated evaluation taggedRow = - {- TODO: this should render with styles like a row with title, but hide the title. - Currently, the developer and use this without a title. If that happens, then - this has no affect on the row - -} - case taggedRow of - Types.Row config -> - Types.Row { config | modifyRow = Types.NodeEvaluated evaluation } - - Types.KeyedRow key config -> - Types.KeyedRow key { config | modifyRow = Types.NodeEvaluated evaluation } - - -{-| -} -outlinePanel : Types.OutlinePanelConfig msg -> Html msg -outlinePanel config = - div [] - [ div - [ styles.class - [ Styles.RowPanelTitle - , case config.palette.name of - Palette.Gray -> - Styles.RowPanelTitleGray - - Palette.DarkGray -> - Styles.RowPanelTitleDarkGray - - Palette.Blue -> - Styles.RowPanelTitleBlue - - Palette.DarkBlue -> - Styles.RowPanelTitleDarkBlue - - Palette.Purple -> - Styles.RowPanelTitlePurple - - Palette.Turquoise -> - Styles.RowPanelTitleTurquoise - - Palette.Red -> - Styles.RowPanelTitleRed - - Palette.Green -> - Styles.RowPanelTitleGreen - - Palette.White -> - Styles.RowPanelTitleWhite - - Palette.Cornflower -> - Styles.RowPanelTitleCornflower - - Palette.Aqua -> - Styles.RowPanelTitleAqua - ] - ] - [ Html.text config.title ] - , div - [ styles.classList - [ ( Styles.RowPanelContent, True ) - , ( Styles.RowPanelContentDashed, config.hasDashedBorder ) - , ( case config.modifyRow of - Types.NodeEvaluated Types.Good -> - Styles.RowPanelContentGreen - - Types.NodeEvaluated Types.Bad -> - Styles.RowPanelContentPurple - - _ -> - case config.palette.name of - Palette.Gray -> - Styles.RowPanelContentGray - - Palette.DarkGray -> - Styles.RowPanelContentDarkGray - - Palette.Blue -> - Styles.RowPanelContentBlue - - Palette.DarkBlue -> - Styles.RowPanelContentDarkBlue - - Palette.Purple -> - Styles.RowPanelContentPurple - - Palette.Turquoise -> - Styles.RowPanelContentTurquoise - - Palette.Red -> - Styles.RowPanelContentRed - - Palette.Green -> - Styles.RowPanelContentGreen - - Palette.White -> - Styles.RowPanelContentWhite - - Palette.Cornflower -> - Styles.RowPanelContentCornflower - - Palette.Aqua -> - Styles.RowPanelContentAqua - , True - ) - ] - ] - [ config.content ] - ] - - -{-| -} -toRowNodeType : Types.Hierarchy -> Types.OutlineLayout msg -> RowNodeType msg -toRowNodeType hierarchy layout = - case layout of - Types.Row config -> - Tag <| - viewRow - hierarchy - config - (ul - [ styles.class [ Styles.RowChildren ] ] - (List.map (rowToHtml Types.Child) config.rows) - ) - - Types.KeyedRow key config -> - KeyedTag - ( key - , viewRow - hierarchy - config - (Html.Keyed.node "ul" - [ styles.class [ Styles.RowChildren ] ] - (List.map (keyedRowToHtml Types.Child) config.rows) - ) - ) - - -{-| -} -viewRow : Types.Hierarchy -> Types.CustomConfig msg -> Html msg -> Html msg -viewRow hierarchy config children = - let - extraContentPalette = - paletteOfFirst config.rows - - rowAttrs = - [ styles.classList - [ ( Styles.Row, True ) - , ( Styles.ChildRow, hierarchy == Types.Child ) - , ( case config.palette.name of - Palette.Blue -> - Styles.RowBlue - - Palette.Gray -> - Styles.RowGray - - Palette.DarkGray -> - Styles.RowDarkGray - - Palette.DarkBlue -> - Styles.RowDarkBlue - - Palette.Purple -> - Styles.RowPurple - - Palette.Turquoise -> - Styles.RowTurquoise - - Palette.Red -> - Styles.RowRed - - Palette.Green -> - Styles.RowGreen - - Palette.White -> - Styles.RowWhite - - Palette.Cornflower -> - Styles.RowCornflower - - Palette.Aqua -> - Styles.RowAqua - , True - ) - ] - - -- , OutlineCss.modifierClassFromAlign config.verticalAlign - ] - in - li - rowAttrs - [ div - [ styles.classList - [ ( Styles.RowContent, True ) - , ( Styles.ChildRowContent, hierarchy == Types.Child ) - , ( case config.palette.name of - Palette.Blue -> - Styles.ChildRowContentBlue - - Palette.Gray -> - Styles.ChildRowContentGray - - Palette.DarkGray -> - Styles.ChildRowContentDarkGray - - Palette.DarkBlue -> - Styles.ChildRowContentDarkBlue - - Palette.Purple -> - Styles.ChildRowContentPurple - - Palette.Turquoise -> - Styles.ChildRowContentTurquoise - - Palette.Red -> - Styles.ChildRowContentRed - - Palette.Green -> - Styles.ChildRowContentGreen - - Palette.White -> - Styles.ChildRowContentWhite - - Palette.Cornflower -> - Styles.ChildRowContentCornflower - - Palette.Aqua -> - Styles.ChildRowContentAqua - , True - ) - ] - ] - [ config.content - , Maybe.map (viewExtraContent extraContentPalette) config.extraContent - |> Maybe.withDefault (Html.text "") - ] - , if List.isEmpty config.rows then - Html.text "" - else - children - ] - - -{-| -} -viewExtraContent : Maybe Palette.Palette -> Html msg -> Html msg -viewExtraContent palette content = - let - {- Styles are inline here to accomodate the calculations we must do - to correctly format extra content. This is based off if there are any child rows - following the extra content. If there are, we add the padding and border styles. - If there are not, we have no styling. - -} - styles = - (Css.asPairs >> Html.Attributes.style) <| - case palette of - Just { border } -> - [ marginLeft (px 15) - , borderLeft3 (px 1) solid border - , paddingLeft (px 15) - ] - - Nothing -> - [] - in - div [ styles ] [ content ] - - -{-| When the row has extra content, the palette from the first child needs to be known in -order to have the correct border on the left of the extra content. This ensures we have -a consistent styling on the outline borders. --} -paletteOfFirst : List (Types.OutlineLayout msg) -> Maybe Palette.Palette -paletteOfFirst rows = - rows - |> List.head - |> Maybe.map - (\row -> - case row of - Types.Row config -> - config.palette - - Types.KeyedRow _ config -> - config.palette - ) - - -{-| -} -rowToHtml : Types.Hierarchy -> Types.OutlineLayout msg -> Html msg -rowToHtml hierarchy = - toRowNodeType hierarchy >> toHtml - - -{-| -} -keyedRowToHtml : Types.Hierarchy -> Types.OutlineLayout msg -> ( String, Html msg ) -keyedRowToHtml hierarchy = - toRowNodeType hierarchy >> toKeyedHtml - - -{-| -} -toHtml : RowNodeType msg -> Html msg -toHtml row = - case row of - Tag html -> - html - - KeyedTag ( _, html ) -> - html - - -{-| -} -toKeyedHtml : RowNodeType msg -> ( String, Html msg ) -toKeyedHtml row = - case row of - Tag html -> - ( "", html ) - - KeyedTag output -> - output - - -{-| -} -rawRow : Types.RowConfig msg -> Types.CustomConfig msg -rawRow config = - { content = config.content - , palette = config.palette - , rows = config.rows - , verticalAlign = Types.MiddleAlign - , extraContent = Nothing - , modifyRow = Types.Normal - , hasDashedBorder = False - } - - -{-| -} -rawRowWithExtraContent : Types.ExtraContenRowConfig msg -> Types.CustomConfig msg -rawRowWithExtraContent config = - { content = config.content - , palette = config.palette - , rows = config.rows - , verticalAlign = Types.TopAlign - , extraContent = Just config.extraContent - , modifyRow = Types.Normal - , hasDashedBorder = False - }