From 5885dc42aafdaea15545a7d68f49cf2ebff61749 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Wed, 29 Mar 2023 08:24:28 -0500 Subject: [PATCH 01/30] introduce SortableTable.V4 --- .../Examples/SortableTable.elm | 4 +- deprecated-modules.csv | 1 + elm.json | 1 + forbidden-imports.toml | 3 + src/Nri/Ui/SortableTable/V4.elm | 387 ++++++++++++++++++ tests/Spec/Nri/Ui/SortableTable.elm | 2 +- tests/elm-verify-examples.json | 1 + 7 files changed, 396 insertions(+), 3 deletions(-) create mode 100644 src/Nri/Ui/SortableTable/V4.elm diff --git a/component-catalog-app/Examples/SortableTable.elm b/component-catalog-app/Examples/SortableTable.elm index 53d4b99d..a9c5fb26 100644 --- a/component-catalog-app/Examples/SortableTable.elm +++ b/component-catalog-app/Examples/SortableTable.elm @@ -17,7 +17,7 @@ import Html.Styled as Html exposing (..) import Html.Styled.Attributes exposing (css) import Nri.Ui.Colors.V1 as Colors import Nri.Ui.Heading.V3 as Heading -import Nri.Ui.SortableTable.V3 as SortableTable exposing (Column) +import Nri.Ui.SortableTable.V4 as SortableTable exposing (Column) import Nri.Ui.Svg.V1 as Svg exposing (Svg) import Nri.Ui.Table.V6 as Table import Nri.Ui.UiIcon.V1 as UiIcon @@ -30,7 +30,7 @@ moduleName = version : Int version = - 3 + 4 {-| -} diff --git a/deprecated-modules.csv b/deprecated-modules.csv index cb9d6412..67e785d9 100644 --- a/deprecated-modules.csv +++ b/deprecated-modules.csv @@ -6,5 +6,6 @@ Nri.Ui.HighlighterToolbar.V2,upgrade to V3 Nri.Ui.QuestionBox.V2,upgrade to V4 Nri.Ui.QuestionBox.V3,upgrade to V4 Nri.Ui.Select.V8,upgrade to V9 +Nri.Ui.SortableTable.V3,upgrade to V4 Nri.Ui.Tabs.V6,upgrade to V8 Nri.Ui.Tabs.V7,upgrade to V8 diff --git a/elm.json b/elm.json index c0608a98..fc0afc3f 100644 --- a/elm.json +++ b/elm.json @@ -70,6 +70,7 @@ "Nri.Ui.Shadows.V1", "Nri.Ui.SideNav.V4", "Nri.Ui.SortableTable.V3", + "Nri.Ui.SortableTable.V4", "Nri.Ui.Spacing.V1", "Nri.Ui.Sprite.V1", "Nri.Ui.Svg.V1", diff --git a/forbidden-imports.toml b/forbidden-imports.toml index 71711516..3d5d14d1 100644 --- a/forbidden-imports.toml +++ b/forbidden-imports.toml @@ -188,6 +188,9 @@ hint = 'upgrade to V4' [forbidden."Nri.Ui.SortableTable.V2"] hint = 'upgrade to V3' +[forbidden."Nri.Ui.SortableTable.V3"] +hint = 'upgrade to V4' + [forbidden."Nri.Ui.Switch.V1"] hint = 'upgrade to V2' diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm new file mode 100644 index 00000000..9bd71121 --- /dev/null +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -0,0 +1,387 @@ +module Nri.Ui.SortableTable.V4 exposing + ( Column, Config, Sorter, State + , init, initDescending + , custom, string, view, viewLoading + , invariantSort, simpleSort, combineSorters + ) + +{-| TODO for next major version: + + - add the possibility to pass Aria.sortAscending and Aria.sortDescending attributes to the tag + +Changes from V2: + + - made column non-sortable (e.g. buttons in a column should not be sorted) + - use a button instead of a clickable div in headers + - use Aria.roleDescription instead of Aria.label in sortable columns headers + - use Nri.Ui.UiIcon.V1 sortArrow and Nri.Ui.UiIcon.V1 sortArrowDown icons for the sort indicators + +@docs Column, Config, Sorter, State +@docs init, initDescending +@docs custom, string, view, viewLoading +@docs invariantSort, simpleSort, combineSorters + +-} + +import Accessibility.Styled.Aria as Aria +import Css exposing (..) +import Html.Styled as Html exposing (Html) +import Html.Styled.Attributes exposing (css) +import Html.Styled.Events +import Nri.Ui.Colors.V1 +import Nri.Ui.CssVendorPrefix.V1 as CssVendorPrefix +import Nri.Ui.Fonts.V1 as Fonts +import Nri.Ui.Svg.V1 +import Nri.Ui.Table.V6 as Table exposing (SortDirection(..)) +import Nri.Ui.UiIcon.V1 + + +{-| -} +type alias Sorter a = + SortDirection -> a -> a -> Order + + +{-| -} +type Column id entry msg + = Column + { id : id + , header : Html msg + , view : entry -> Html msg + , sorter : Maybe (Sorter entry) + , width : Int + , cellStyles : entry -> List Style + } + + +{-| -} +type alias State id = + { column : id + , sortDirection : SortDirection + } + + +{-| -} +type alias Config id entry msg = + { updateMsg : State id -> msg + , columns : List (Column id entry msg) + } + + +{-| -} +init : id -> State id +init initialSort = + { column = initialSort + , sortDirection = Ascending + } + + +{-| -} +initDescending : id -> State id +initDescending initialSort = + { column = initialSort + , sortDirection = Descending + } + + +{-| -} +string : + { id : id + , header : String + , value : entry -> String + , width : Int + , cellStyles : entry -> List Style + } + -> Column id entry msg +string { id, header, value, width, cellStyles } = + Column + { id = id + , header = Html.text header + , view = value >> Html.text + , sorter = Just (simpleSort value) + , width = width + , cellStyles = cellStyles + } + + +{-| -} +custom : + { id : id + , header : Html msg + , view : entry -> Html msg + , sorter : Maybe (Sorter entry) + , width : Int + , cellStyles : entry -> List Style + } + -> Column id entry msg +custom config = + Column + { id = config.id + , header = config.header + , view = config.view + , sorter = config.sorter + , width = config.width + , cellStyles = config.cellStyles + } + + +{-| Create a sorter function that always orders the entries in the same order. +For example, this is useful when we want to resolve ties and sort the tied +entries by name, no matter of the sort direction set on the table. +-} +invariantSort : (entry -> comparable) -> Sorter entry +invariantSort mapper = + \sortDirection elem1 elem2 -> + compare (mapper elem1) (mapper elem2) + + +{-| Create a simple sorter function that orders entries by mapping a function +over the collection. It will also reverse it when the sort direction is descending. +-} +simpleSort : (entry -> comparable) -> Sorter entry +simpleSort mapper = + \sortDirection elem1 elem2 -> + let + result = + compare (mapper elem1) (mapper elem2) + in + case sortDirection of + Ascending -> + result + + Descending -> + flipOrder result + + +flipOrder : Order -> Order +flipOrder order = + case order of + LT -> + GT + + EQ -> + EQ + + GT -> + LT + + +{-| -} +combineSorters : List (Sorter entry) -> Sorter entry +combineSorters sorters = + \sortDirection elem1 elem2 -> + let + folder = + \sorter acc -> + case acc of + EQ -> + sorter sortDirection elem1 elem2 + + _ -> + acc + in + List.foldl folder EQ sorters + + +{-| -} +viewLoading : Config id entry msg -> State id -> Html msg +viewLoading config state = + let + tableColumns = + List.map (buildTableColumn config.updateMsg state) config.columns + in + Table.viewLoading + tableColumns + + +{-| -} +view : Config id entry msg -> State id -> List entry -> Html msg +view config state entries = + let + tableColumns = + List.map (buildTableColumn config.updateMsg state) config.columns + + sorter = + findSorter config.columns state.column + in + Table.view + tableColumns + (List.sortWith (sorter state.sortDirection) entries) + + +findSorter : List (Column id entry msg) -> id -> Sorter entry +findSorter columns columnId = + columns + |> listExtraFind (\(Column column) -> column.id == columnId) + |> Maybe.andThen (\(Column column) -> column.sorter) + |> Maybe.withDefault identitySorter + + +{-| Taken from +-} +listExtraFind : (a -> Bool) -> List a -> Maybe a +listExtraFind predicate list = + case list of + [] -> + Nothing + + first :: rest -> + if predicate first then + Just first + + else + listExtraFind predicate rest + + +identitySorter : Sorter a +identitySorter = + \sortDirection item1 item2 -> + EQ + + +buildTableColumn : (State id -> msg) -> State id -> Column id entry msg -> Table.Column entry msg +buildTableColumn updateMsg state (Column column) = + Table.custom + { header = viewSortHeader (column.sorter /= Nothing) column.header updateMsg state column.id + , view = column.view + , width = Css.px (toFloat column.width) + , cellStyles = column.cellStyles + , sort = + if state.column == column.id then + Just state.sortDirection + + else + Nothing + } + + +viewSortHeader : Bool -> Html msg -> (State id -> msg) -> State id -> id -> Html msg +viewSortHeader isSortable header updateMsg state id = + let + nextState = + nextTableState state id + in + if isSortable then + Html.button + [ css + [ Css.displayFlex + , Css.alignItems Css.center + , Css.justifyContent Css.spaceBetween + , CssVendorPrefix.property "user-select" "none" + , if state.column == id then + fontWeight bold + + else + fontWeight normal + , cursor pointer + + -- make this look less "buttony" + , Css.border Css.zero + , Css.backgroundColor Css.transparent + , Css.width (Css.pct 100) + , Css.height (Css.pct 100) + , Css.margin Css.zero + , Css.padding Css.zero + , Fonts.baseFont + , Css.fontSize (Css.em 1) + ] + , Html.Styled.Events.onClick (updateMsg nextState) + + -- screen readers should know what clicking this button will do + , Aria.roleDescription "sort button" + ] + [ Html.div [] [ header ] + , viewSortButton updateMsg state id + ] + + else + Html.div + [ css [ fontWeight normal ] + ] + [ header ] + + +viewSortButton : (State id -> msg) -> State id -> id -> Html msg +viewSortButton updateMsg state id = + let + arrows upHighlighted downHighlighted = + Html.div + [ css + [ Css.displayFlex + , Css.flexDirection Css.column + , Css.alignItems Css.center + , Css.justifyContent Css.center + ] + ] + [ sortArrow Up upHighlighted + , sortArrow Down downHighlighted + ] + + buttonContent = + case ( state.column == id, state.sortDirection ) of + ( True, Ascending ) -> + arrows True False + + ( True, Descending ) -> + arrows False True + + ( False, _ ) -> + arrows False False + in + Html.div [ css [ padding (px 2) ] ] [ buttonContent ] + + +nextTableState : State id -> id -> State id +nextTableState state id = + if state.column == id then + { column = id + , sortDirection = flipSortDirection state.sortDirection + } + + else + { column = id + , sortDirection = Ascending + } + + +flipSortDirection : SortDirection -> SortDirection +flipSortDirection order = + case order of + Ascending -> + Descending + + Descending -> + Ascending + + +type Direction + = Up + | Down + + +sortArrow : Direction -> Bool -> Html msg +sortArrow direction active = + let + arrow = + case direction of + Up -> + Nri.Ui.UiIcon.V1.sortArrow + + Down -> + Nri.Ui.UiIcon.V1.sortArrowDown + + color = + if active then + Nri.Ui.Colors.V1.azure + + else + Nri.Ui.Colors.V1.gray75 + in + arrow + |> Nri.Ui.Svg.V1.withHeight (px 6) + |> Nri.Ui.Svg.V1.withWidth (px 8) + |> Nri.Ui.Svg.V1.withColor color + |> Nri.Ui.Svg.V1.withCss + [ displayFlex + , margin2 (px 1) zero + ] + |> Nri.Ui.Svg.V1.toHtml diff --git a/tests/Spec/Nri/Ui/SortableTable.elm b/tests/Spec/Nri/Ui/SortableTable.elm index 7fa267a1..d345037b 100644 --- a/tests/Spec/Nri/Ui/SortableTable.elm +++ b/tests/Spec/Nri/Ui/SortableTable.elm @@ -2,7 +2,7 @@ module Spec.Nri.Ui.SortableTable exposing (spec) import Expect import Html.Styled -import Nri.Ui.SortableTable.V3 as SortableTable +import Nri.Ui.SortableTable.V4 as SortableTable import Test exposing (..) import Test.Html.Query as Query import Test.Html.Selector as Selector diff --git a/tests/elm-verify-examples.json b/tests/elm-verify-examples.json index 9491e127..1e05a052 100644 --- a/tests/elm-verify-examples.json +++ b/tests/elm-verify-examples.json @@ -66,6 +66,7 @@ "Nri.Ui.Shadows.V1", "Nri.Ui.SideNav.V4", "Nri.Ui.SortableTable.V3", + "Nri.Ui.SortableTable.V4", "Nri.Ui.Spacing.V1", "Nri.Ui.Sprite.V1", "Nri.Ui.Svg.V1", From 0cc48f9c796ca3c8263c0e79533861d77fc1919e Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Wed, 29 Mar 2023 08:30:51 -0500 Subject: [PATCH 02/30] say what I'm about to change for V4 --- src/Nri/Ui/SortableTable/V4.elm | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index 9bd71121..c89e53f3 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -9,12 +9,10 @@ module Nri.Ui.SortableTable.V4 exposing - add the possibility to pass Aria.sortAscending and Aria.sortDescending attributes to the tag -Changes from V2: +Changes from V3: - - made column non-sortable (e.g. buttons in a column should not be sorted) - - use a button instead of a clickable div in headers - - use Aria.roleDescription instead of Aria.label in sortable columns headers - - use Nri.Ui.UiIcon.V1 sortArrow and Nri.Ui.UiIcon.V1 sortArrowDown icons for the sort indicators + - Change to an HTML-like API + - Allow the table header to be sticky @docs Column, Config, Sorter, State @docs init, initDescending From dec89d9e14cd5376fbbedffb42637c6d4d1639c2 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Wed, 29 Mar 2023 08:37:13 -0500 Subject: [PATCH 03/30] move viewLoading down --- src/Nri/Ui/SortableTable/V4.elm | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index c89e53f3..0e7a0889 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -180,17 +180,6 @@ combineSorters sorters = List.foldl folder EQ sorters -{-| -} -viewLoading : Config id entry msg -> State id -> Html msg -viewLoading config state = - let - tableColumns = - List.map (buildTableColumn config.updateMsg state) config.columns - in - Table.viewLoading - tableColumns - - {-| -} view : Config id entry msg -> State id -> List entry -> Html msg view config state entries = @@ -206,6 +195,17 @@ view config state entries = (List.sortWith (sorter state.sortDirection) entries) +{-| -} +viewLoading : Config id entry msg -> State id -> Html msg +viewLoading config state = + let + tableColumns = + List.map (buildTableColumn config.updateMsg state) config.columns + in + Table.viewLoading + tableColumns + + findSorter : List (Column id entry msg) -> id -> Sorter entry findSorter columns columnId = columns From 7407bb91fddb13371a640955d1cee50f9ee0cd3b Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Wed, 29 Mar 2023 08:55:37 -0500 Subject: [PATCH 04/30] move state to config and make it optional --- .../Examples/SortableTable.elm | 5 +- src/Nri/Ui/SortableTable/V4.elm | 82 ++++++++++++------- 2 files changed, 57 insertions(+), 30 deletions(-) diff --git a/component-catalog-app/Examples/SortableTable.elm b/component-catalog-app/Examples/SortableTable.elm index a9c5fb26..538a2fc6 100644 --- a/component-catalog-app/Examples/SortableTable.elm +++ b/component-catalog-app/Examples/SortableTable.elm @@ -107,6 +107,7 @@ example = config = { updateMsg = SetSortState , columns = columns + , state = Just sortState } ( dataCode, data ) = @@ -149,10 +150,10 @@ example = } , Heading.h2 [ Heading.plaintext "Example" ] , if settings.loading then - SortableTable.viewLoading config sortState + SortableTable.viewLoading config else - SortableTable.view config sortState data + SortableTable.view config data ] } diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index 0e7a0889..2622bd8e 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -62,9 +62,19 @@ type alias State id = type alias Config id entry msg = { updateMsg : State id -> msg , columns : List (Column id entry msg) + , state : Maybe (State id) } +type Attribute id entry msg + = Attribute (Config id entry msg -> Config id entry msg) + + +state : State id -> Attribute id entry msg +state state_ = + Attribute (\config -> { config | state = Just state_ }) + + {-| -} init : id -> State id init initialSort = @@ -181,26 +191,32 @@ combineSorters sorters = {-| -} -view : Config id entry msg -> State id -> List entry -> Html msg -view config state entries = +view : Config id entry msg -> List entry -> Html msg +view config entries = let tableColumns = - List.map (buildTableColumn config.updateMsg state) config.columns - - sorter = - findSorter config.columns state.column + List.map (buildTableColumn config.updateMsg config.state) config.columns in - Table.view - tableColumns - (List.sortWith (sorter state.sortDirection) entries) + case config.state of + Just state_ -> + let + sorter = + findSorter config.columns state_.column + in + Table.view + tableColumns + (List.sortWith (sorter state_.sortDirection) entries) + + Nothing -> + Table.view tableColumns entries {-| -} -viewLoading : Config id entry msg -> State id -> Html msg -viewLoading config state = +viewLoading : Config id entry msg -> Html msg +viewLoading config = let tableColumns = - List.map (buildTableColumn config.updateMsg state) config.columns + List.map (buildTableColumn config.updateMsg config.state) config.columns in Table.viewLoading tableColumns @@ -236,27 +252,37 @@ identitySorter = EQ -buildTableColumn : (State id -> msg) -> State id -> Column id entry msg -> Table.Column entry msg -buildTableColumn updateMsg state (Column column) = +buildTableColumn : (State id -> msg) -> Maybe (State id) -> Column id entry msg -> Table.Column entry msg +buildTableColumn updateMsg maybeState (Column column) = Table.custom - { header = viewSortHeader (column.sorter /= Nothing) column.header updateMsg state column.id + { header = + case maybeState of + Just state_ -> + viewSortHeader (column.sorter /= Nothing) column.header updateMsg state_ column.id + + Nothing -> + Debug.todo "non-sorted header" , view = column.view , width = Css.px (toFloat column.width) , cellStyles = column.cellStyles , sort = - if state.column == column.id then - Just state.sortDirection + Maybe.andThen + (\state_ -> + if state_.column == column.id then + Just state_.sortDirection - else - Nothing + else + Nothing + ) + maybeState } viewSortHeader : Bool -> Html msg -> (State id -> msg) -> State id -> id -> Html msg -viewSortHeader isSortable header updateMsg state id = +viewSortHeader isSortable header updateMsg state_ id = let nextState = - nextTableState state id + nextTableState state_ id in if isSortable then Html.button @@ -265,7 +291,7 @@ viewSortHeader isSortable header updateMsg state id = , Css.alignItems Css.center , Css.justifyContent Css.spaceBetween , CssVendorPrefix.property "user-select" "none" - , if state.column == id then + , if state_.column == id then fontWeight bold else @@ -288,7 +314,7 @@ viewSortHeader isSortable header updateMsg state id = , Aria.roleDescription "sort button" ] [ Html.div [] [ header ] - , viewSortButton updateMsg state id + , viewSortButton updateMsg state_ id ] else @@ -299,7 +325,7 @@ viewSortHeader isSortable header updateMsg state id = viewSortButton : (State id -> msg) -> State id -> id -> Html msg -viewSortButton updateMsg state id = +viewSortButton updateMsg state_ id = let arrows upHighlighted downHighlighted = Html.div @@ -315,7 +341,7 @@ viewSortButton updateMsg state id = ] buttonContent = - case ( state.column == id, state.sortDirection ) of + case ( state_.column == id, state_.sortDirection ) of ( True, Ascending ) -> arrows True False @@ -329,10 +355,10 @@ viewSortButton updateMsg state id = nextTableState : State id -> id -> State id -nextTableState state id = - if state.column == id then +nextTableState state_ id = + if state_.column == id then { column = id - , sortDirection = flipSortDirection state.sortDirection + , sortDirection = flipSortDirection state_.sortDirection } else From 60f7fd7754b5e9cff1483b5d94fb2c73db1df4f7 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Wed, 29 Mar 2023 09:04:53 -0500 Subject: [PATCH 05/30] move columns out of config --- .../Examples/SortableTable.elm | 5 ++--- src/Nri/Ui/SortableTable/V4.elm | 19 +++++++++---------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/component-catalog-app/Examples/SortableTable.elm b/component-catalog-app/Examples/SortableTable.elm index 538a2fc6..c76c0374 100644 --- a/component-catalog-app/Examples/SortableTable.elm +++ b/component-catalog-app/Examples/SortableTable.elm @@ -106,7 +106,6 @@ example = config = { updateMsg = SetSortState - , columns = columns , state = Just sortState } @@ -150,10 +149,10 @@ example = } , Heading.h2 [ Heading.plaintext "Example" ] , if settings.loading then - SortableTable.viewLoading config + SortableTable.viewLoading config columns else - SortableTable.view config data + SortableTable.view config columns data ] } diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index 2622bd8e..d2020a9c 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -59,15 +59,14 @@ type alias State id = {-| -} -type alias Config id entry msg = +type alias Config id msg = { updateMsg : State id -> msg - , columns : List (Column id entry msg) , state : Maybe (State id) } type Attribute id entry msg - = Attribute (Config id entry msg -> Config id entry msg) + = Attribute (Config id msg -> Config id msg) state : State id -> Attribute id entry msg @@ -191,17 +190,17 @@ combineSorters sorters = {-| -} -view : Config id entry msg -> List entry -> Html msg -view config entries = +view : Config id msg -> List (Column id entry msg) -> List entry -> Html msg +view config columns entries = let tableColumns = - List.map (buildTableColumn config.updateMsg config.state) config.columns + List.map (buildTableColumn config.updateMsg config.state) columns in case config.state of Just state_ -> let sorter = - findSorter config.columns state_.column + findSorter columns state_.column in Table.view tableColumns @@ -212,11 +211,11 @@ view config entries = {-| -} -viewLoading : Config id entry msg -> Html msg -viewLoading config = +viewLoading : Config id msg -> List (Column id entry msg) -> Html msg +viewLoading config columns = let tableColumns = - List.map (buildTableColumn config.updateMsg config.state) config.columns + List.map (buildTableColumn config.updateMsg config.state) columns in Table.viewLoading tableColumns From aa42a6f3355f2636ba2a66cfd9754c06963468d8 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Wed, 29 Mar 2023 09:11:56 -0500 Subject: [PATCH 06/30] make updateMsg optional --- .../Examples/SortableTable.elm | 2 +- src/Nri/Ui/SortableTable/V4.elm | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/component-catalog-app/Examples/SortableTable.elm b/component-catalog-app/Examples/SortableTable.elm index c76c0374..6ef7ba31 100644 --- a/component-catalog-app/Examples/SortableTable.elm +++ b/component-catalog-app/Examples/SortableTable.elm @@ -105,7 +105,7 @@ example = Control.currentValue model.settings config = - { updateMsg = SetSortState + { updateMsg = Just SetSortState , state = Just sortState } diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index d2020a9c..dbb5aec7 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -29,6 +29,8 @@ import Html.Styled.Events import Nri.Ui.Colors.V1 import Nri.Ui.CssVendorPrefix.V1 as CssVendorPrefix import Nri.Ui.Fonts.V1 as Fonts +import Nri.Ui.Html.Attributes.V2 exposing (maybe) +import Nri.Ui.Html.V3 exposing (viewJust) import Nri.Ui.Svg.V1 import Nri.Ui.Table.V6 as Table exposing (SortDirection(..)) import Nri.Ui.UiIcon.V1 @@ -60,7 +62,7 @@ type alias State id = {-| -} type alias Config id msg = - { updateMsg : State id -> msg + { updateMsg : Maybe (State id -> msg) , state : Maybe (State id) } @@ -251,13 +253,13 @@ identitySorter = EQ -buildTableColumn : (State id -> msg) -> Maybe (State id) -> Column id entry msg -> Table.Column entry msg -buildTableColumn updateMsg maybeState (Column column) = +buildTableColumn : Maybe (State id -> msg) -> Maybe (State id) -> Column id entry msg -> Table.Column entry msg +buildTableColumn maybeUpdateMsg maybeState (Column column) = Table.custom { header = case maybeState of Just state_ -> - viewSortHeader (column.sorter /= Nothing) column.header updateMsg state_ column.id + viewSortHeader (column.sorter /= Nothing) column.header maybeUpdateMsg state_ column.id Nothing -> Debug.todo "non-sorted header" @@ -277,8 +279,8 @@ buildTableColumn updateMsg maybeState (Column column) = } -viewSortHeader : Bool -> Html msg -> (State id -> msg) -> State id -> id -> Html msg -viewSortHeader isSortable header updateMsg state_ id = +viewSortHeader : Bool -> Html msg -> Maybe (State id -> msg) -> State id -> id -> Html msg +viewSortHeader isSortable header maybeUpdateMsg state_ id = let nextState = nextTableState state_ id @@ -307,13 +309,13 @@ viewSortHeader isSortable header updateMsg state_ id = , Fonts.baseFont , Css.fontSize (Css.em 1) ] - , Html.Styled.Events.onClick (updateMsg nextState) + , maybe (\updateMsg -> Html.Styled.Events.onClick (updateMsg nextState)) maybeUpdateMsg -- screen readers should know what clicking this button will do , Aria.roleDescription "sort button" ] [ Html.div [] [ header ] - , viewSortButton updateMsg state_ id + , viewJust (\updateMsg -> viewSortButton updateMsg state_ id) maybeUpdateMsg ] else From ae850b406a1c36c7b089895cdc390d42ba00534f Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Wed, 29 Mar 2023 09:14:43 -0500 Subject: [PATCH 07/30] viewSortButton doesn't need updateMsg; don't accept it --- src/Nri/Ui/SortableTable/V4.elm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index dbb5aec7..8698dcae 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -309,13 +309,13 @@ viewSortHeader isSortable header maybeUpdateMsg state_ id = , Fonts.baseFont , Css.fontSize (Css.em 1) ] - , maybe (\updateMsg -> Html.Styled.Events.onClick (updateMsg nextState)) maybeUpdateMsg + , maybe (\updateMsg_ -> Html.Styled.Events.onClick (updateMsg_ nextState)) maybeUpdateMsg -- screen readers should know what clicking this button will do , Aria.roleDescription "sort button" ] [ Html.div [] [ header ] - , viewJust (\updateMsg -> viewSortButton updateMsg state_ id) maybeUpdateMsg + , viewJust (\_ -> viewSortButton state_ id) maybeUpdateMsg ] else @@ -325,8 +325,8 @@ viewSortHeader isSortable header maybeUpdateMsg state_ id = [ header ] -viewSortButton : (State id -> msg) -> State id -> id -> Html msg -viewSortButton updateMsg state_ id = +viewSortButton : State id -> id -> Html msg +viewSortButton state_ id = let arrows upHighlighted downHighlighted = Html.div From 4ca0532256c1dc714eb2a45a5bf515bee444eed7 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Wed, 29 Mar 2023 09:15:12 -0500 Subject: [PATCH 08/30] get rid of the rest of the unused variables --- src/Nri/Ui/SortableTable/V4.elm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index 8698dcae..67162390 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -139,7 +139,7 @@ entries by name, no matter of the sort direction set on the table. -} invariantSort : (entry -> comparable) -> Sorter entry invariantSort mapper = - \sortDirection elem1 elem2 -> + \_ elem1 elem2 -> compare (mapper elem1) (mapper elem2) @@ -249,7 +249,7 @@ listExtraFind predicate list = identitySorter : Sorter a identitySorter = - \sortDirection item1 item2 -> + \_ _ _ -> EQ From 2efe8e33c3c7b299224f76447b58aa2ea62c0c4b Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Wed, 29 Mar 2023 09:21:19 -0500 Subject: [PATCH 09/30] switch to the html-like API --- .../Examples/SortableTable.elm | 12 +++--- src/Nri/Ui/SortableTable/V4.elm | 40 ++++++++++++++----- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/component-catalog-app/Examples/SortableTable.elm b/component-catalog-app/Examples/SortableTable.elm index 6ef7ba31..c6e1ede2 100644 --- a/component-catalog-app/Examples/SortableTable.elm +++ b/component-catalog-app/Examples/SortableTable.elm @@ -104,10 +104,10 @@ example = settings = Control.currentValue model.settings - config = - { updateMsg = Just SetSortState - , state = Just sortState - } + attrs = + [ SortableTable.updateMsg SetSortState + , SortableTable.state sortState + ] ( dataCode, data ) = List.unzip dataWithCode @@ -149,10 +149,10 @@ example = } , Heading.h2 [ Heading.plaintext "Example" ] , if settings.loading then - SortableTable.viewLoading config columns + SortableTable.viewLoading attrs columns else - SortableTable.view config columns data + SortableTable.view attrs columns data ] } diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index 67162390..c7f26e46 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -1,7 +1,8 @@ module Nri.Ui.SortableTable.V4 exposing - ( Column, Config, Sorter, State + ( Column, Sorter, State , init, initDescending - , custom, string, view, viewLoading + , custom, string + , Attribute, updateMsg, state, view, viewLoading , invariantSort, simpleSort, combineSorters ) @@ -14,9 +15,10 @@ Changes from V3: - Change to an HTML-like API - Allow the table header to be sticky -@docs Column, Config, Sorter, State +@docs Column, Sorter, State @docs init, initDescending -@docs custom, string, view, viewLoading +@docs custom, string +@docs Attribute, updateMsg, state, view, viewLoading @docs invariantSort, simpleSort, combineSorters -} @@ -67,15 +69,27 @@ type alias Config id msg = } -type Attribute id entry msg +defaultConfig : Config id msg +defaultConfig = + { updateMsg = Nothing + , state = Nothing + } + + +type Attribute id msg = Attribute (Config id msg -> Config id msg) -state : State id -> Attribute id entry msg +state : State id -> Attribute id msg state state_ = Attribute (\config -> { config | state = Just state_ }) +updateMsg : (State id -> msg) -> Attribute id msg +updateMsg updateMsg_ = + Attribute (\config -> { config | updateMsg = Just updateMsg_ }) + + {-| -} init : id -> State id init initialSort = @@ -192,9 +206,12 @@ combineSorters sorters = {-| -} -view : Config id msg -> List (Column id entry msg) -> List entry -> Html msg -view config columns entries = +view : List (Attribute id msg) -> List (Column id entry msg) -> List entry -> Html msg +view attributes columns entries = let + config = + List.foldl (\(Attribute fn) soFar -> fn soFar) defaultConfig attributes + tableColumns = List.map (buildTableColumn config.updateMsg config.state) columns in @@ -213,9 +230,12 @@ view config columns entries = {-| -} -viewLoading : Config id msg -> List (Column id entry msg) -> Html msg -viewLoading config columns = +viewLoading : List (Attribute id msg) -> List (Column id entry msg) -> Html msg +viewLoading attributes columns = let + config = + List.foldl (\(Attribute fn) soFar -> fn soFar) defaultConfig attributes + tableColumns = List.map (buildTableColumn config.updateMsg config.state) columns in From 36f65569f8f16cee85482265a6b08217c1fa8c7a Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Wed, 29 Mar 2023 09:25:22 -0500 Subject: [PATCH 10/30] update code samples for new API --- component-catalog-app/Examples/SortableTable.elm | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/component-catalog-app/Examples/SortableTable.elm b/component-catalog-app/Examples/SortableTable.elm index c6e1ede2..f822cc7a 100644 --- a/component-catalog-app/Examples/SortableTable.elm +++ b/component-catalog-app/Examples/SortableTable.elm @@ -119,15 +119,16 @@ example = { sectionName = viewName , code = [ moduleName ++ "." ++ viewName - , Code.recordMultiline - [ ( "updateMsg", "SetSortState" ) - , ( "columns", Code.listMultiline columnsCode 2 ) + , Code.listMultiline + [ "SortableTable.updateMsg SetSortState" + , "-- The SortableTable's state should be stored on the model, rather than initialized in the view" + ++ "\n " + ++ "SortableTable.state (SortableTable.init " + ++ Debug.toString model.sortState.column + ++ ")" ] 1 - , Code.newlineWithIndent 1 - , Code.commentInline "The SortableTable's state should be stored on the model, rather than initialized in the view" - , Code.newlineWithIndent 1 - , Code.withParens ("SortableTable.init " ++ Debug.toString model.sortState.column) + , Code.listMultiline columnsCode 1 , finalArgs ] |> String.join "" From ab51be7badb4bb688bc93168bae415b131acca20 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Wed, 29 Mar 2023 09:42:44 -0500 Subject: [PATCH 11/30] add API for setting stickiness --- src/Nri/Ui/SortableTable/V4.elm | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index c7f26e46..55aebe6c 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -2,7 +2,7 @@ module Nri.Ui.SortableTable.V4 exposing ( Column, Sorter, State , init, initDescending , custom, string - , Attribute, updateMsg, state, view, viewLoading + , Attribute, updateMsg, state, stickyHeader, stickyHeaderCustom, StickyConfig, view, viewLoading , invariantSort, simpleSort, combineSorters ) @@ -18,7 +18,7 @@ Changes from V3: @docs Column, Sorter, State @docs init, initDescending @docs custom, string -@docs Attribute, updateMsg, state, view, viewLoading +@docs Attribute, updateMsg, state, stickyHeader, stickyHeaderCustom, StickyConfig, view, viewLoading @docs invariantSort, simpleSort, combineSorters -} @@ -66,6 +66,7 @@ type alias State id = type alias Config id msg = { updateMsg : Maybe (State id -> msg) , state : Maybe (State id) + , stickyHeader : Maybe StickyConfig } @@ -73,6 +74,22 @@ defaultConfig : Config id msg defaultConfig = { updateMsg = Nothing , state = Nothing + , stickyHeader = Nothing + } + + +type alias StickyConfig = + { topOffset : Float + , zIndex : Int + , includeMobile : Bool + } + + +defaultStickyConfig : StickyConfig +defaultStickyConfig = + { topOffset = 0 + , zIndex = 0 + , includeMobile = False } @@ -90,6 +107,16 @@ updateMsg updateMsg_ = Attribute (\config -> { config | updateMsg = Just updateMsg_ }) +stickyHeader : Attribute id msg +stickyHeader = + Attribute (\config -> { config | stickyHeader = Just defaultStickyConfig }) + + +stickyHeaderCustom : StickyConfig -> Attribute id msg +stickyHeaderCustom stickyConfig = + Attribute (\config -> { config | stickyHeader = Just stickyConfig }) + + {-| -} init : id -> State id init initialSort = From e51222f7665628ed6cf3f21f21bbbc7f01f337f5 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Wed, 29 Mar 2023 09:52:06 -0500 Subject: [PATCH 12/30] add documentation --- src/Nri/Ui/SortableTable/V4.elm | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index 55aebe6c..627a700f 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -78,6 +78,19 @@ defaultConfig = } +{-| How the header will be set up to be sticky. + + - `topOffset` controls how far off the top of the viewport the headers will + stick, in pixels. (**Default value:** 0) + - `zIndex` controls where in the stacking context the header will end + up. Useful to prevent elements in rows from appearing over the header. + (**Defualt value:** 0) + - `includeMobile`, if true, will make the header sticky on mobile (narrow) + viewports as well as desktop (wider) ones. Be careful about setting this to + `True`, as it can make it harder for folks on mobile devices to pinch and + zoom, creating accessibility problems. (**Default value:** False) + +-} type alias StickyConfig = { topOffset : Float , zIndex : Int @@ -93,25 +106,42 @@ defaultStickyConfig = } +{-| Customize how the table is rendered, for example by adding sorting or +stickiness. +-} type Attribute id msg = Attribute (Config id msg -> Config id msg) +{-| Sort a column. You can get an initial state with `init` or `initDescending`. +If you make this sorting interactive, you should store the state in your model +and provide it to this function instead of recreating it on every update. +-} state : State id -> Attribute id msg state state_ = Attribute (\config -> { config | state = Just state_ }) +{-| Add interactivity in sorting columns. When this attribute is provided and +sorting is enabled, columns will be sortable by clicking the headers. +-} updateMsg : (State id -> msg) -> Attribute id msg updateMsg updateMsg_ = Attribute (\config -> { config | updateMsg = Just updateMsg_ }) +{-| Make the header sticky (that is, it will stick to the top of the viewport +when it otherwise would have been scrolled off.) You probably will want to set a +background color on the header as well. +-} stickyHeader : Attribute id msg stickyHeader = Attribute (\config -> { config | stickyHeader = Just defaultStickyConfig }) +{-| Does the same thing as `stickyHeader`, but with adaptations for your +specific use. +-} stickyHeaderCustom : StickyConfig -> Attribute id msg stickyHeaderCustom stickyConfig = Attribute (\config -> { config | stickyHeader = Just stickyConfig }) From 8ea612f7c848dc20de7575edf1a992389c44e6e9 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Thu, 30 Mar 2023 17:11:52 -0500 Subject: [PATCH 13/30] fix up tests --- tests/Spec/Nri/Ui/SortableTable.elm | 48 +++++++++++++---------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/tests/Spec/Nri/Ui/SortableTable.elm b/tests/Spec/Nri/Ui/SortableTable.elm index d345037b..bfe805e4 100644 --- a/tests/Spec/Nri/Ui/SortableTable.elm +++ b/tests/Spec/Nri/Ui/SortableTable.elm @@ -3,6 +3,7 @@ module Spec.Nri.Ui.SortableTable exposing (spec) import Expect import Html.Styled import Nri.Ui.SortableTable.V4 as SortableTable +import Nri.Ui.Table.V6 exposing (SortDirection) import Test exposing (..) import Test.Html.Query as Query import Test.Html.Selector as Selector @@ -19,30 +20,23 @@ type alias Person = } -type Msg - = NoOp - - -config : SortableTable.Config Column Person Msg -config = - { updateMsg = \_ -> NoOp - , columns = - [ SortableTable.string - { id = FirstName - , header = "First name" - , value = .firstName - , width = 125 - , cellStyles = \_ -> [] - } - , SortableTable.string - { id = LastName - , header = "Last name" - , value = .lastName - , width = 125 - , cellStyles = \_ -> [] - } - ] - } +columns : List (SortableTable.Column Column Person msg) +columns = + [ SortableTable.string + { id = FirstName + , header = "First name" + , value = .firstName + , width = 125 + , cellStyles = \_ -> [] + } + , SortableTable.string + { id = LastName + , header = "Last name" + , value = .lastName + , width = 125 + , cellStyles = \_ -> [] + } + ] entries : List Person @@ -53,9 +47,9 @@ entries = ] -tableView : SortableTable.State Column -> Query.Single Msg +tableView : SortableTable.State Column -> Query.Single msg tableView sortState = - SortableTable.view config sortState entries + SortableTable.view [ SortableTable.state sortState ] columns entries |> Html.Styled.toUnstyled |> Query.fromHtml @@ -70,10 +64,12 @@ sortByDescending field = SortableTable.initDescending field +ascending : SortDirection ascending = sortBy FirstName |> .sortDirection +descending : SortDirection descending = sortByDescending FirstName |> .sortDirection From 2b6b3dcecfaaf2b4148119157d93544b0d7c28cd Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Thu, 30 Mar 2023 17:17:25 -0500 Subject: [PATCH 14/30] introduce Table.V7 --- .../Examples/AnimatedIcon.elm | 2 +- component-catalog-app/Examples/Block.elm | 2 +- .../Examples/BreadCrumbs.elm | 2 +- component-catalog-app/Examples/Checkbox.elm | 2 +- component-catalog-app/Examples/Fonts.elm | 2 +- .../Examples/Highlighter.elm | 2 +- component-catalog-app/Examples/Menu.elm | 2 +- .../Examples/QuestionBox.elm | 2 +- component-catalog-app/Examples/RingGauge.elm | 2 +- .../Examples/SortableTable.elm | 2 +- component-catalog-app/Examples/Spacing.elm | 2 +- component-catalog-app/Examples/Table.elm | 4 +- component-catalog-app/Examples/Tooltip.elm | 2 +- deprecated-modules.csv | 1 + elm.json | 1 + forbidden-imports.toml | 3 + src/Nri/Ui/SortableTable/V3.elm | 2 +- src/Nri/Ui/SortableTable/V4.elm | 2 +- src/Nri/Ui/Table/V7.elm | 329 ++++++++++++++++++ tests/Spec/Nri/Ui/SortableTable.elm | 2 +- tests/elm-verify-examples.json | 1 + 21 files changed, 352 insertions(+), 17 deletions(-) create mode 100644 src/Nri/Ui/Table/V7.elm diff --git a/component-catalog-app/Examples/AnimatedIcon.elm b/component-catalog-app/Examples/AnimatedIcon.elm index 3b0a6321..0a6e22f1 100644 --- a/component-catalog-app/Examples/AnimatedIcon.elm +++ b/component-catalog-app/Examples/AnimatedIcon.elm @@ -19,7 +19,7 @@ import Nri.Ui.AnimatedIcon.V1 as AnimatedIcon import Nri.Ui.Colors.V1 as Colors import Nri.Ui.Heading.V3 as Heading import Nri.Ui.Svg.V1 as Svg -import Nri.Ui.Table.V6 as Table +import Nri.Ui.Table.V7 as Table moduleName : String diff --git a/component-catalog-app/Examples/Block.elm b/component-catalog-app/Examples/Block.elm index 9c920cd6..b7942761 100644 --- a/component-catalog-app/Examples/Block.elm +++ b/component-catalog-app/Examples/Block.elm @@ -26,7 +26,7 @@ import Nri.Ui.ClickableText.V3 as ClickableText import Nri.Ui.Fonts.V1 as Fonts import Nri.Ui.Heading.V3 as Heading import Nri.Ui.Spacing.V1 as Spacing -import Nri.Ui.Table.V6 as Table +import Nri.Ui.Table.V7 as Table import Nri.Ui.Text.V6 as Text import Nri.Ui.UiIcon.V1 as UiIcon import Task diff --git a/component-catalog-app/Examples/BreadCrumbs.elm b/component-catalog-app/Examples/BreadCrumbs.elm index 73edd070..c1b857be 100644 --- a/component-catalog-app/Examples/BreadCrumbs.elm +++ b/component-catalog-app/Examples/BreadCrumbs.elm @@ -23,7 +23,7 @@ import Nri.Ui.Fonts.V1 as Fonts import Nri.Ui.Heading.V3 as Heading import Nri.Ui.Html.V3 exposing (viewJust) import Nri.Ui.Svg.V1 as Svg exposing (Svg) -import Nri.Ui.Table.V6 as Table +import Nri.Ui.Table.V7 as Table import Nri.Ui.UiIcon.V1 as UiIcon diff --git a/component-catalog-app/Examples/Checkbox.elm b/component-catalog-app/Examples/Checkbox.elm index 5576e3d3..ae81268d 100644 --- a/component-catalog-app/Examples/Checkbox.elm +++ b/component-catalog-app/Examples/Checkbox.elm @@ -21,7 +21,7 @@ import Nri.Ui.Colors.V1 as Colors import Nri.Ui.Fonts.V1 as Fonts import Nri.Ui.Heading.V3 as Heading import Nri.Ui.Svg.V1 as Svg -import Nri.Ui.Table.V6 as Table +import Nri.Ui.Table.V7 as Table moduleName : String diff --git a/component-catalog-app/Examples/Fonts.elm b/component-catalog-app/Examples/Fonts.elm index 7916ea6e..c2bcc7ce 100644 --- a/component-catalog-app/Examples/Fonts.elm +++ b/component-catalog-app/Examples/Fonts.elm @@ -13,7 +13,7 @@ import Html.Styled as Html exposing (Html) import Html.Styled.Attributes exposing (css) import Nri.Ui.ClickableText.V3 as ClickableText import Nri.Ui.Fonts.V1 as Fonts -import Nri.Ui.Table.V6 as Table +import Nri.Ui.Table.V7 as Table import Nri.Ui.Text.V6 as Text diff --git a/component-catalog-app/Examples/Highlighter.elm b/component-catalog-app/Examples/Highlighter.elm index 6aafa63d..f1793599 100644 --- a/component-catalog-app/Examples/Highlighter.elm +++ b/component-catalog-app/Examples/Highlighter.elm @@ -25,7 +25,7 @@ import Nri.Ui.Heading.V3 as Heading import Nri.Ui.Highlightable.V2 as Highlightable exposing (Highlightable) import Nri.Ui.Highlighter.V3 as Highlighter import Nri.Ui.HighlighterTool.V1 as Tool -import Nri.Ui.Table.V6 as Table +import Nri.Ui.Table.V7 as Table import String.Extra diff --git a/component-catalog-app/Examples/Menu.elm b/component-catalog-app/Examples/Menu.elm index 68f4ca1f..15d845f9 100644 --- a/component-catalog-app/Examples/Menu.elm +++ b/component-catalog-app/Examples/Menu.elm @@ -29,7 +29,7 @@ import Nri.Ui.Fonts.V1 as Fonts import Nri.Ui.Heading.V3 as Heading import Nri.Ui.Menu.V4 as Menu import Nri.Ui.Spacing.V1 as Spacing -import Nri.Ui.Table.V6 as Table +import Nri.Ui.Table.V7 as Table import Nri.Ui.TextInput.V7 as TextInput import Nri.Ui.Tooltip.V3 as Tooltip import Nri.Ui.UiIcon.V1 as UiIcon diff --git a/component-catalog-app/Examples/QuestionBox.elm b/component-catalog-app/Examples/QuestionBox.elm index d1ab684e..e2a44184 100644 --- a/component-catalog-app/Examples/QuestionBox.elm +++ b/component-catalog-app/Examples/QuestionBox.elm @@ -33,7 +33,7 @@ import Nri.Ui.MediaQuery.V1 exposing (..) import Nri.Ui.QuestionBox.V4 as QuestionBox import Nri.Ui.Spacing.V1 as Spacing import Nri.Ui.Svg.V1 as Svg -import Nri.Ui.Table.V6 as Table +import Nri.Ui.Table.V7 as Table import Nri.Ui.Text.V6 as Text import Nri.Ui.UiIcon.V1 as UiIcon import Task diff --git a/component-catalog-app/Examples/RingGauge.elm b/component-catalog-app/Examples/RingGauge.elm index 75016a70..2bd1c559 100644 --- a/component-catalog-app/Examples/RingGauge.elm +++ b/component-catalog-app/Examples/RingGauge.elm @@ -20,7 +20,7 @@ import Nri.Ui.Colors.V1 as Colors import Nri.Ui.Heading.V3 as Heading import Nri.Ui.RingGauge.V1 as RingGauge import Nri.Ui.Svg.V1 as Svg -import Nri.Ui.Table.V6 as Table +import Nri.Ui.Table.V7 as Table import Round import SolidColor.Accessibility diff --git a/component-catalog-app/Examples/SortableTable.elm b/component-catalog-app/Examples/SortableTable.elm index f822cc7a..da95832e 100644 --- a/component-catalog-app/Examples/SortableTable.elm +++ b/component-catalog-app/Examples/SortableTable.elm @@ -19,7 +19,7 @@ import Nri.Ui.Colors.V1 as Colors import Nri.Ui.Heading.V3 as Heading import Nri.Ui.SortableTable.V4 as SortableTable exposing (Column) import Nri.Ui.Svg.V1 as Svg exposing (Svg) -import Nri.Ui.Table.V6 as Table +import Nri.Ui.Table.V7 as Table import Nri.Ui.UiIcon.V1 as UiIcon diff --git a/component-catalog-app/Examples/Spacing.elm b/component-catalog-app/Examples/Spacing.elm index 622c0810..24912e9b 100644 --- a/component-catalog-app/Examples/Spacing.elm +++ b/component-catalog-app/Examples/Spacing.elm @@ -21,7 +21,7 @@ import Nri.Ui.Container.V2 as Container import Nri.Ui.Fonts.V1 as Fonts import Nri.Ui.Heading.V3 as Heading import Nri.Ui.Spacing.V1 as Spacing -import Nri.Ui.Table.V6 as Table +import Nri.Ui.Table.V7 as Table import Svg.Styled import Svg.Styled.Attributes diff --git a/component-catalog-app/Examples/Table.elm b/component-catalog-app/Examples/Table.elm index 05322172..e81aae40 100644 --- a/component-catalog-app/Examples/Table.elm +++ b/component-catalog-app/Examples/Table.elm @@ -15,7 +15,7 @@ import Debug.Control.View as ControlView import Example exposing (Example) import Nri.Ui.Button.V10 as Button import Nri.Ui.Heading.V3 as Heading -import Nri.Ui.Table.V6 as Table exposing (Column) +import Nri.Ui.Table.V7 as Table exposing (Column) {-| -} @@ -30,7 +30,7 @@ moduleName = version : Int version = - 6 + 7 {-| -} diff --git a/component-catalog-app/Examples/Tooltip.elm b/component-catalog-app/Examples/Tooltip.elm index de3fdc12..a7564feb 100644 --- a/component-catalog-app/Examples/Tooltip.elm +++ b/component-catalog-app/Examples/Tooltip.elm @@ -25,7 +25,7 @@ import Nri.Ui.ClickableText.V3 as ClickableText import Nri.Ui.Colors.V1 as Colors import Nri.Ui.Heading.V3 as Heading import Nri.Ui.Svg.V1 as Svg -import Nri.Ui.Table.V6 as Table +import Nri.Ui.Table.V7 as Table import Nri.Ui.Tooltip.V3 as Tooltip import Nri.Ui.UiIcon.V1 as UiIcon diff --git a/deprecated-modules.csv b/deprecated-modules.csv index 67e785d9..5ec6b75a 100644 --- a/deprecated-modules.csv +++ b/deprecated-modules.csv @@ -7,5 +7,6 @@ Nri.Ui.QuestionBox.V2,upgrade to V4 Nri.Ui.QuestionBox.V3,upgrade to V4 Nri.Ui.Select.V8,upgrade to V9 Nri.Ui.SortableTable.V3,upgrade to V4 +Nri.Ui.Table.V6,upgrade to V7 Nri.Ui.Tabs.V6,upgrade to V8 Nri.Ui.Tabs.V7,upgrade to V8 diff --git a/elm.json b/elm.json index fc0afc3f..8c8378ba 100644 --- a/elm.json +++ b/elm.json @@ -76,6 +76,7 @@ "Nri.Ui.Svg.V1", "Nri.Ui.Switch.V2", "Nri.Ui.Table.V6", + "Nri.Ui.Table.V7", "Nri.Ui.Tabs.V6", "Nri.Ui.Tabs.V7", "Nri.Ui.Tabs.V8", diff --git a/forbidden-imports.toml b/forbidden-imports.toml index 3d5d14d1..737fa58d 100644 --- a/forbidden-imports.toml +++ b/forbidden-imports.toml @@ -200,6 +200,9 @@ hint = 'upgrade to V5' [forbidden."Nri.Ui.Table.V5"] hint = 'upgrade to V6' +[forbidden."Nri.Ui.Table.V6"] +hint = 'upgrade to V7' + [forbidden."Nri.Ui.Tabs.V6"] hint = 'upgrade to V8' diff --git a/src/Nri/Ui/SortableTable/V3.elm b/src/Nri/Ui/SortableTable/V3.elm index 4882d7c2..dfb2b318 100644 --- a/src/Nri/Ui/SortableTable/V3.elm +++ b/src/Nri/Ui/SortableTable/V3.elm @@ -32,7 +32,7 @@ import Nri.Ui.Colors.V1 import Nri.Ui.CssVendorPrefix.V1 as CssVendorPrefix import Nri.Ui.Fonts.V1 as Fonts import Nri.Ui.Svg.V1 -import Nri.Ui.Table.V6 as Table exposing (SortDirection(..)) +import Nri.Ui.Table.V7 as Table exposing (SortDirection(..)) import Nri.Ui.UiIcon.V1 diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index 627a700f..8e78a8e6 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -34,7 +34,7 @@ import Nri.Ui.Fonts.V1 as Fonts import Nri.Ui.Html.Attributes.V2 exposing (maybe) import Nri.Ui.Html.V3 exposing (viewJust) import Nri.Ui.Svg.V1 -import Nri.Ui.Table.V6 as Table exposing (SortDirection(..)) +import Nri.Ui.Table.V7 as Table exposing (SortDirection(..)) import Nri.Ui.UiIcon.V1 diff --git a/src/Nri/Ui/Table/V7.elm b/src/Nri/Ui/Table/V7.elm new file mode 100644 index 00000000..6b09e36e --- /dev/null +++ b/src/Nri/Ui/Table/V7.elm @@ -0,0 +1,329 @@ +module Nri.Ui.Table.V7 exposing + ( Column, SortDirection(..), custom, string, rowHeader + , view, viewWithoutHeader + , viewLoading, viewLoadingWithoutHeader + ) + +{-| Upgrading from V5: + + - The columns take an additional `sort` property that allows + you to specify ARIA sorting + +@docs Column, SortDirection, custom, string, rowHeader + +@docs view, viewWithoutHeader + +@docs viewLoading, viewLoadingWithoutHeader + +-} + +import Accessibility.Styled.Style as Style +import Css exposing (..) +import Css.Animations +import Html.Styled as Html exposing (..) +import Html.Styled.Attributes as Attributes exposing (css) +import Nri.Ui.Colors.V1 exposing (..) +import Nri.Ui.Fonts.V1 exposing (baseFont) + + +{-| Closed representation of how to render the header and cells of a column +in the table +-} +type Column data msg + = Column (Html msg) (data -> Html msg) Style (data -> List Style) (Maybe SortDirection) CellType + + +{-| Which direction is a table column sorted? Only set these on columns that +actually have an explicit sort! +-} +type SortDirection + = Ascending + | Descending + + +{-| Is this cell a data cell or header cell? +-} +type CellType + = RowHeaderCell + | DataCell + + +cell : CellType -> List (Attribute msg) -> List (Html msg) -> Html msg +cell cellType attrs = + case cellType of + RowHeaderCell -> + th (Attributes.scope "row" :: attrs) + + DataCell -> + td attrs + + +{-| A column that renders some aspect of a value as text +-} +string : + { header : String + , value : data -> String + , width : LengthOrAuto compatible + , cellStyles : data -> List Style + , sort : Maybe SortDirection + } + -> Column data msg +string { header, value, width, cellStyles, sort } = + Column (Html.text header) (value >> Html.text) (Css.width width) cellStyles sort DataCell + + +{-| A column that renders however you want it to +-} +custom : + { header : Html msg + , view : data -> Html msg + , width : LengthOrAuto compatible + , cellStyles : data -> List Style + , sort : Maybe SortDirection + } + -> Column data msg +custom options = + Column options.header options.view (Css.width options.width) options.cellStyles options.sort DataCell + + +{-| A column whose cells are row headers +-} +rowHeader : + { header : Html msg + , view : data -> Html msg + , width : LengthOrAuto compatible + , cellStyles : data -> List Style + , sort : Maybe SortDirection + } + -> Column data msg +rowHeader options = + Column options.header options.view (Css.width options.width) options.cellStyles options.sort RowHeaderCell + + + +-- VIEW + + +{-| Displays a table of data without a header row +-} +viewWithoutHeader : List (Column data msg) -> List data -> Html msg +viewWithoutHeader columns = + tableWithoutHeader [] columns (viewRow columns) + + +{-| Displays a table of data based on the provided column definitions +-} +view : List (Column data msg) -> List data -> Html msg +view columns = + tableWithHeader [] columns (viewRow columns) + + +viewRow : List (Column data msg) -> data -> Html msg +viewRow columns data = + tr + [ css rowStyles ] + (List.map (viewColumn data) columns) + + +viewColumn : data -> Column data msg -> Html msg +viewColumn data (Column _ renderer width cellStyles _ cellType) = + cell cellType + [ css ([ width, verticalAlign middle ] ++ cellStyles data) + ] + [ renderer data ] + + + +-- VIEW LOADING + + +{-| Display a table with the given columns but instead of data, show blocked +out text with an interesting animation. This view lets the user know that +data is on its way and what it will look like when it arrives. +-} +viewLoading : List (Column data msg) -> Html msg +viewLoading columns = + tableWithHeader loadingTableStyles columns (viewLoadingRow columns) (List.range 0 8) + + +{-| Display the loading table without a header row +-} +viewLoadingWithoutHeader : List (Column data msg) -> Html msg +viewLoadingWithoutHeader columns = + tableWithoutHeader loadingTableStyles columns (viewLoadingRow columns) (List.range 0 8) + + +viewLoadingRow : List (Column data msg) -> Int -> Html msg +viewLoadingRow columns index = + tr + [ css rowStyles ] + (List.indexedMap (viewLoadingColumn index) columns) + + +viewLoadingColumn : Int -> Int -> Column data msg -> Html msg +viewLoadingColumn rowIndex colIndex (Column _ _ width _ _ cellType) = + cell cellType + [ css (stylesLoadingColumn rowIndex colIndex width ++ [ verticalAlign middle ] ++ loadingCellStyles) + ] + [ span [ css loadingContentStyles ] [] ] + + +stylesLoadingColumn : Int -> Int -> Style -> List Style +stylesLoadingColumn rowIndex colIndex width = + [ width + , property "animation-delay" (String.fromFloat (toFloat (rowIndex + colIndex) * 0.1) ++ "s") + ] + + + +-- HELP + + +tableWithoutHeader : List Style -> List (Column data msg) -> (a -> Html msg) -> List a -> Html msg +tableWithoutHeader styles columns toRow data = + table styles + [ thead [] [ tr Style.invisible (List.map tableColHeader columns) ] + , tableBody toRow data + ] + + +tableWithHeader : List Style -> List (Column data msg) -> (a -> Html msg) -> List a -> Html msg +tableWithHeader styles columns toRow data = + table styles + [ tableHeader columns + , tableBody toRow data + ] + + +table : List Style -> List (Html msg) -> Html msg +table styles = + Html.table [ css (styles ++ tableStyles) ] + + +tableHeader : List (Column data msg) -> Html msg +tableHeader columns = + thead [] + [ tr [ css headersStyles ] + (List.map tableColHeader columns) + ] + + +tableColHeader : Column data msg -> Html msg +tableColHeader (Column header _ width _ sort _) = + th + [ Attributes.scope "col" + , css (width :: headerStyles) + , Attributes.attribute "aria-sort" <| + case sort of + Nothing -> + "none" + + Just Ascending -> + "ascending" + + Just Descending -> + "descending" + ] + [ header ] + + +tableBody : (a -> Html msg) -> List a -> Html msg +tableBody toRow items = + tbody [] (List.map toRow items) + + + +-- STYLES + + +headersStyles : List Style +headersStyles = + [ borderBottom3 (px 3) solid gray75 + , height (px 45) + , fontSize (px 15) + ] + + +headerStyles : List Style +headerStyles = + [ padding4 (px 15) (px 12) (px 11) (px 12) + , textAlign left + , fontWeight bold + ] + + +rowStyles : List Style +rowStyles = + [ height (px 45) + , fontSize (px 14) + , color gray20 + , pseudoClass "nth-child(odd)" + [ backgroundColor gray96 ] + ] + + +loadingContentStyles : List Style +loadingContentStyles = + [ width (pct 100) + , display inlineBlock + , height (Css.em 1) + , borderRadius (Css.em 1) + , backgroundColor gray75 + ] + + +loadingCellStyles : List Style +loadingCellStyles = + [ batch flashAnimation + , padding2 (px 14) (px 10) + ] + + +loadingTableStyles : List Style +loadingTableStyles = + fadeInAnimation + + +tableStyles : List Style +tableStyles = + [ borderCollapse collapse + , baseFont + , Css.width (Css.pct 100) + ] + + +flash : Css.Animations.Keyframes {} +flash = + Css.Animations.keyframes + [ ( 0, [ Css.Animations.opacity (Css.num 0.6) ] ) + , ( 50, [ Css.Animations.opacity (Css.num 0.2) ] ) + , ( 100, [ Css.Animations.opacity (Css.num 0.6) ] ) + ] + + +fadeIn : Css.Animations.Keyframes {} +fadeIn = + Css.Animations.keyframes + [ ( 0, [ Css.Animations.opacity (Css.num 0) ] ) + , ( 100, [ Css.Animations.opacity (Css.num 1) ] ) + ] + + +flashAnimation : List Css.Style +flashAnimation = + [ animationName flash + , property "animation-duration" "2s" + , property "animation-iteration-count" "infinite" + , opacity (num 0.6) + ] + + +fadeInAnimation : List Css.Style +fadeInAnimation = + [ animationName fadeIn + , property "animation-duration" "0.4s" + , property "animation-delay" "0.2s" + , property "animation-fill-mode" "forwards" + , animationIterationCount (int 1) + , opacity (num 0) + ] diff --git a/tests/Spec/Nri/Ui/SortableTable.elm b/tests/Spec/Nri/Ui/SortableTable.elm index bfe805e4..d31f37c1 100644 --- a/tests/Spec/Nri/Ui/SortableTable.elm +++ b/tests/Spec/Nri/Ui/SortableTable.elm @@ -3,7 +3,7 @@ module Spec.Nri.Ui.SortableTable exposing (spec) import Expect import Html.Styled import Nri.Ui.SortableTable.V4 as SortableTable -import Nri.Ui.Table.V6 exposing (SortDirection) +import Nri.Ui.Table.V7 exposing (SortDirection) import Test exposing (..) import Test.Html.Query as Query import Test.Html.Selector as Selector diff --git a/tests/elm-verify-examples.json b/tests/elm-verify-examples.json index 1e05a052..397f46bc 100644 --- a/tests/elm-verify-examples.json +++ b/tests/elm-verify-examples.json @@ -72,6 +72,7 @@ "Nri.Ui.Svg.V1", "Nri.Ui.Switch.V2", "Nri.Ui.Table.V6", + "Nri.Ui.Table.V7", "Nri.Ui.Tabs.V6", "Nri.Ui.Tabs.V7", "Nri.Ui.Tabs.V8", From 6dedd1df97f3bf3367335168820512f17258a4b9 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Mon, 3 Apr 2023 10:49:51 -0500 Subject: [PATCH 15/30] add list of styles to Table view calls --- .../Examples/AnimatedIcon.elm | 2 +- component-catalog-app/Examples/Block.elm | 2 +- .../Examples/BreadCrumbs.elm | 2 +- component-catalog-app/Examples/Checkbox.elm | 2 +- component-catalog-app/Examples/Fonts.elm | 2 +- .../Examples/Highlighter.elm | 2 +- component-catalog-app/Examples/Menu.elm | 2 +- .../Examples/QuestionBox.elm | 2 +- component-catalog-app/Examples/RingGauge.elm | 2 +- .../Examples/SortableTable.elm | 2 +- component-catalog-app/Examples/Spacing.elm | 4 +-- component-catalog-app/Examples/Table.elm | 11 ++++--- component-catalog-app/Examples/Tooltip.elm | 2 +- src/Nri/Ui/SortableTable/V3.elm | 5 ++- src/Nri/Ui/SortableTable/V4.elm | 7 ++-- src/Nri/Ui/Table/V7.elm | 33 ++++++++++--------- 16 files changed, 42 insertions(+), 40 deletions(-) diff --git a/component-catalog-app/Examples/AnimatedIcon.elm b/component-catalog-app/Examples/AnimatedIcon.elm index 0a6e22f1..7ad16639 100644 --- a/component-catalog-app/Examples/AnimatedIcon.elm +++ b/component-catalog-app/Examples/AnimatedIcon.elm @@ -88,7 +88,7 @@ example = ] } , Heading.h2 [ Heading.plaintext "Example" ] - , Table.view + , Table.view [] [ Table.custom { header = text "Rendered" , view = diff --git a/component-catalog-app/Examples/Block.elm b/component-catalog-app/Examples/Block.elm index b7942761..c4322263 100644 --- a/component-catalog-app/Examples/Block.elm +++ b/component-catalog-app/Examples/Block.elm @@ -251,7 +251,7 @@ example = , Block.labelPosition (Dict.get longId offsets) ] ] - , Table.view + , Table.view [] [ Table.custom { header = text "Pattern name & description" , view = .description >> Markdown.toHtml Nothing >> List.map fromUnstyled >> div [] diff --git a/component-catalog-app/Examples/BreadCrumbs.elm b/component-catalog-app/Examples/BreadCrumbs.elm index c1b857be..1bebde96 100644 --- a/component-catalog-app/Examples/BreadCrumbs.elm +++ b/component-catalog-app/Examples/BreadCrumbs.elm @@ -173,7 +173,7 @@ example = [ Heading.h2 [ Heading.plaintext "viewSecondary Example" ] , viewJust (Tuple.second >> viewSecondaryExample settings.currentRoute) breadCrumbs ] - , Table.view + , Table.view [] [ Table.string { header = "Name" , value = .name diff --git a/component-catalog-app/Examples/Checkbox.elm b/component-catalog-app/Examples/Checkbox.elm index ae81268d..fd87be0c 100644 --- a/component-catalog-app/Examples/Checkbox.elm +++ b/component-catalog-app/Examples/Checkbox.elm @@ -66,7 +66,7 @@ example = , Heading.h2 [ Heading.plaintext "Customizable example" ] , exampleView , Heading.h2 [ Heading.plaintext "Examples" ] - , Table.view + , Table.view [] [ Table.string { header = "State" , value = .state diff --git a/component-catalog-app/Examples/Fonts.elm b/component-catalog-app/Examples/Fonts.elm index c2bcc7ce..adde2717 100644 --- a/component-catalog-app/Examples/Fonts.elm +++ b/component-catalog-app/Examples/Fonts.elm @@ -90,7 +90,7 @@ viewFontFailurePatterns = , Css.textAlign Css.center ] in - Table.view + Table.view [] [ Table.rowHeader { header = Html.text "Example" , view = Html.text << .example diff --git a/component-catalog-app/Examples/Highlighter.elm b/component-catalog-app/Examples/Highlighter.elm index f1793599..ae604968 100644 --- a/component-catalog-app/Examples/Highlighter.elm +++ b/component-catalog-app/Examples/Highlighter.elm @@ -113,7 +113,7 @@ example = ] , Heading.h2 [ Heading.plaintext "Non-interactive examples" ] , Heading.h3 [ Heading.plaintext "These are examples of some different ways the highlighter can appear to users." ] - , Table.view + , Table.view [] [ Table.rowHeader { header = text "Highlighter." , view = .viewName >> text diff --git a/component-catalog-app/Examples/Menu.elm b/component-catalog-app/Examples/Menu.elm index 15d845f9..ac6aece6 100644 --- a/component-catalog-app/Examples/Menu.elm +++ b/component-catalog-app/Examples/Menu.elm @@ -230,7 +230,7 @@ view ellieLinkConfig state = [ Heading.plaintext "Menu types" , Heading.css [ Css.margin2 Spacing.verticalSpacerPx Css.zero ] ] - , Table.view + , Table.view [] [ Table.string { header = "Menu type" , value = .menu diff --git a/component-catalog-app/Examples/QuestionBox.elm b/component-catalog-app/Examples/QuestionBox.elm index e2a44184..06789ab9 100644 --- a/component-catalog-app/Examples/QuestionBox.elm +++ b/component-catalog-app/Examples/QuestionBox.elm @@ -238,7 +238,7 @@ While these visions did appear. ] ] ] - , Table.view + , Table.view [] [ Table.custom { header = text "Pattern name & description" , view = .description >> Markdown.toHtml Nothing >> List.map fromUnstyled >> div [] diff --git a/component-catalog-app/Examples/RingGauge.elm b/component-catalog-app/Examples/RingGauge.elm index 2bd1c559..fc37fbd1 100644 --- a/component-catalog-app/Examples/RingGauge.elm +++ b/component-catalog-app/Examples/RingGauge.elm @@ -103,7 +103,7 @@ example = |> Svg.withWidth (Css.px 200) |> Svg.withHeight (Css.px 200) |> Svg.toHtml - , Table.view + , Table.view [] [ Table.string { header = "Color contrast against" , value = .name diff --git a/component-catalog-app/Examples/SortableTable.elm b/component-catalog-app/Examples/SortableTable.elm index da95832e..65b51676 100644 --- a/component-catalog-app/Examples/SortableTable.elm +++ b/component-catalog-app/Examples/SortableTable.elm @@ -74,7 +74,7 @@ example = |> Svg.withHeight (Css.px 12) |> Svg.toHtml in - [ Table.view + [ Table.view [] [ Table.custom { header = header "X" , view = .x >> Html.text diff --git a/component-catalog-app/Examples/Spacing.elm b/component-catalog-app/Examples/Spacing.elm index 24912e9b..3f2d65b1 100644 --- a/component-catalog-app/Examples/Spacing.elm +++ b/component-catalog-app/Examples/Spacing.elm @@ -237,7 +237,7 @@ view ellieLinkConfig state = , Heading.h2 [ Heading.plaintext "Example", Heading.css [ Css.marginTop Spacing.verticalSpacerPx ] ] , fakePage [ exampleView ] , Heading.h2 [ Heading.plaintext "Content alignment", Heading.css [ Css.marginTop Spacing.verticalSpacerPx ] ] - , Table.view + , Table.view [] [ Table.string { header = "Name" , value = .name @@ -275,7 +275,7 @@ view ellieLinkConfig state = , { name = "centeredContentWithCustomWidth", alignment = "Centered", maxWidth = "(customizable)", sidePadding = "0px" } ] , Heading.h2 [ Heading.plaintext "Constants", Heading.css [ Css.marginTop Spacing.verticalSpacerPx ] ] - , Table.view + , Table.view [] [ Table.string { header = "Name" , value = .name diff --git a/component-catalog-app/Examples/Table.elm b/component-catalog-app/Examples/Table.elm index e81aae40..0da48e1c 100644 --- a/component-catalog-app/Examples/Table.elm +++ b/component-catalog-app/Examples/Table.elm @@ -44,7 +44,7 @@ example = , categories = [ Layout ] , keyboardSupport = [] , preview = - [ Table.view + [ Table.view [] [ Table.string { header = "A" , value = .a @@ -98,6 +98,7 @@ example = { sectionName = moduleName ++ "." ++ viewName , code = (moduleName ++ "." ++ viewName) + ++ " [] " ++ Code.list columnsCode ++ dataStr } @@ -111,16 +112,16 @@ example = , Heading.h2 [ Heading.plaintext "Example" ] , case ( showHeader, isLoading ) of ( True, False ) -> - Table.view columns data + Table.view [] columns data ( False, False ) -> - Table.viewWithoutHeader columns data + Table.viewWithoutHeader [] columns data ( True, True ) -> - Table.viewLoading columns + Table.viewLoading [] columns ( False, True ) -> - Table.viewLoadingWithoutHeader columns + Table.viewLoadingWithoutHeader [] columns ] } diff --git a/component-catalog-app/Examples/Tooltip.elm b/component-catalog-app/Examples/Tooltip.elm index a7564feb..8229e5c6 100644 --- a/component-catalog-app/Examples/Tooltip.elm +++ b/component-catalog-app/Examples/Tooltip.elm @@ -136,7 +136,7 @@ view : EllieLink.Config -> State -> List (Html Msg) view ellieLinkConfig model = [ viewCustomizableExample ellieLinkConfig model.staticExampleSettings , Heading.h2 [ Heading.plaintext "What type of tooltip should I use?" ] - , Table.view + , Table.view [] [ Table.string { header = "Type" , value = .name diff --git a/src/Nri/Ui/SortableTable/V3.elm b/src/Nri/Ui/SortableTable/V3.elm index dfb2b318..a70936b9 100644 --- a/src/Nri/Ui/SortableTable/V3.elm +++ b/src/Nri/Ui/SortableTable/V3.elm @@ -189,8 +189,7 @@ viewLoading config state = tableColumns = List.map (buildTableColumn config.updateMsg state) config.columns in - Table.viewLoading - tableColumns + Table.viewLoading [] tableColumns {-| -} @@ -203,7 +202,7 @@ view config state entries = sorter = findSorter config.columns state.column in - Table.view + Table.view [] tableColumns (List.sortWith (sorter state.sortDirection) entries) diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index 8e78a8e6..9d6d5851 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -278,12 +278,12 @@ view attributes columns entries = sorter = findSorter columns state_.column in - Table.view + Table.view [] tableColumns (List.sortWith (sorter state_.sortDirection) entries) Nothing -> - Table.view tableColumns entries + Table.view [] tableColumns entries {-| -} @@ -296,8 +296,7 @@ viewLoading attributes columns = tableColumns = List.map (buildTableColumn config.updateMsg config.state) columns in - Table.viewLoading - tableColumns + Table.viewLoading [] tableColumns findSorter : List (Column id entry msg) -> id -> Sorter entry diff --git a/src/Nri/Ui/Table/V7.elm b/src/Nri/Ui/Table/V7.elm index 6b09e36e..224668dc 100644 --- a/src/Nri/Ui/Table/V7.elm +++ b/src/Nri/Ui/Table/V7.elm @@ -4,10 +4,13 @@ module Nri.Ui.Table.V7 exposing , viewLoading, viewLoadingWithoutHeader ) -{-| Upgrading from V5: +{-| Upgrading from V6: - - The columns take an additional `sort` property that allows - you to specify ARIA sorting + - If you don't have extra styles for the table, add an empty list to calls + to `view`. + - Consider moving to `SortableTable`, as in V4 a non-interactive table renders + just the same but has additional flexibility in the API and will make future + upgrades easier. @docs Column, SortDirection, custom, string, rowHeader @@ -106,16 +109,16 @@ rowHeader options = {-| Displays a table of data without a header row -} -viewWithoutHeader : List (Column data msg) -> List data -> Html msg -viewWithoutHeader columns = - tableWithoutHeader [] columns (viewRow columns) +viewWithoutHeader : List Style -> List (Column data msg) -> List data -> Html msg +viewWithoutHeader additionalStyles columns = + tableWithoutHeader additionalStyles columns (viewRow columns) {-| Displays a table of data based on the provided column definitions -} -view : List (Column data msg) -> List data -> Html msg -view columns = - tableWithHeader [] columns (viewRow columns) +view : List Style -> List (Column data msg) -> List data -> Html msg +view additionalStyles columns = + tableWithHeader additionalStyles columns (viewRow columns) viewRow : List (Column data msg) -> data -> Html msg @@ -141,16 +144,16 @@ viewColumn data (Column _ renderer width cellStyles _ cellType) = out text with an interesting animation. This view lets the user know that data is on its way and what it will look like when it arrives. -} -viewLoading : List (Column data msg) -> Html msg -viewLoading columns = - tableWithHeader loadingTableStyles columns (viewLoadingRow columns) (List.range 0 8) +viewLoading : List Style -> List (Column data msg) -> Html msg +viewLoading additionalStyles columns = + tableWithHeader (loadingTableStyles ++ additionalStyles) columns (viewLoadingRow columns) (List.range 0 8) {-| Display the loading table without a header row -} -viewLoadingWithoutHeader : List (Column data msg) -> Html msg -viewLoadingWithoutHeader columns = - tableWithoutHeader loadingTableStyles columns (viewLoadingRow columns) (List.range 0 8) +viewLoadingWithoutHeader : List Style -> List (Column data msg) -> Html msg +viewLoadingWithoutHeader additionalStyles columns = + tableWithoutHeader (loadingTableStyles ++ additionalStyles) columns (viewLoadingRow columns) (List.range 0 8) viewLoadingRow : List (Column data msg) -> Int -> Html msg From a1a43f04f0ceeeda633ebe0b3d5073a8cdc71f41 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Mon, 3 Apr 2023 10:52:26 -0500 Subject: [PATCH 16/30] good news: this was done already! --- src/Nri/Ui/SortableTable/V4.elm | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index 9d6d5851..96ead3d3 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -6,11 +6,7 @@ module Nri.Ui.SortableTable.V4 exposing , invariantSort, simpleSort, combineSorters ) -{-| TODO for next major version: - - - add the possibility to pass Aria.sortAscending and Aria.sortDescending attributes to the tag - -Changes from V3: +{-| Changes from V3: - Change to an HTML-like API - Allow the table header to be sticky From ed782c4e9e639c2a6324d243a8d8c47ed007f081 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Mon, 3 Apr 2023 10:56:52 -0500 Subject: [PATCH 17/30] get rid of the mobile flag --- src/Nri/Ui/SortableTable/V4.elm | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index 96ead3d3..d8350aab 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -81,16 +81,14 @@ defaultConfig = - `zIndex` controls where in the stacking context the header will end up. Useful to prevent elements in rows from appearing over the header. (**Defualt value:** 0) - - `includeMobile`, if true, will make the header sticky on mobile (narrow) - viewports as well as desktop (wider) ones. Be careful about setting this to - `True`, as it can make it harder for folks on mobile devices to pinch and - zoom, creating accessibility problems. (**Default value:** False) + +Headers are never sticky on mobile-sized viewports because doing so causes some +accessibility issues with zooming and panning. -} type alias StickyConfig = { topOffset : Float , zIndex : Int - , includeMobile : Bool } @@ -98,7 +96,6 @@ defaultStickyConfig : StickyConfig defaultStickyConfig = { topOffset = 0 , zIndex = 0 - , includeMobile = False } From 342a0306ffef3abafebb4e7c1220931aff7e317d Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Mon, 3 Apr 2023 11:07:24 -0500 Subject: [PATCH 18/30] update the example to use the new stickiness API --- .../Examples/SortableTable.elm | 82 ++++++++++++++++--- 1 file changed, 71 insertions(+), 11 deletions(-) diff --git a/component-catalog-app/Examples/SortableTable.elm b/component-catalog-app/Examples/SortableTable.elm index 65b51676..85b8792d 100644 --- a/component-catalog-app/Examples/SortableTable.elm +++ b/component-catalog-app/Examples/SortableTable.elm @@ -11,6 +11,7 @@ import Code import Css exposing (..) import Debug.Control as Control exposing (Control) import Debug.Control.Extra as ControlExtra +import Debug.Control.Extra exposing (values) import Debug.Control.View as ControlView import Example exposing (Example) import Html.Styled as Html exposing (..) @@ -105,9 +106,23 @@ example = Control.currentValue model.settings attrs = - [ SortableTable.updateMsg SetSortState - , SortableTable.state sortState - ] + List.filterMap identity + [ Just (SortableTable.updateMsg SetSortState) + , Just (SortableTable.state sortState) + , Maybe.map + (\stickiness -> + case stickiness of + Default -> + SortableTable.stickyHeader + + Custom customConfig -> + SortableTable.stickyHeaderCustom customConfig + ) + settings.stickyHeader + ] + + isStickyAtAll = + settings.stickyHeader /= Nothing ( dataCode, data ) = List.unzip dataWithCode @@ -120,13 +135,31 @@ example = , code = [ moduleName ++ "." ++ viewName , Code.listMultiline - [ "SortableTable.updateMsg SetSortState" - , "-- The SortableTable's state should be stored on the model, rather than initialized in the view" - ++ "\n " - ++ "SortableTable.state (SortableTable.init " - ++ Debug.toString model.sortState.column - ++ ")" - ] + (List.filterMap identity + [ Just "SortableTable.updateMsg SetSortState" + , "-- The SortableTable's state should be stored on the model, rather than initialized in the view" + ++ "\n " + ++ "SortableTable.state (SortableTable.init " + ++ Debug.toString model.sortState.column + ++ ")" + |> Just + , Maybe.map + (\stickiness -> + case stickiness of + Default -> + "SortableTable.stickyHeader" + + Custom stickyConfig -> + "SortableTable.stickyHeaderCustom " + ++ Code.recordMultiline + [ ( "topOffset", String.fromFloat stickyConfig.topOffset ) + , ( "zIndex", String.fromInt stickyConfig.zIndex ) + ] + 2 + ) + settings.stickyHeader + ] + ) 1 , Code.listMultiline columnsCode 1 , finalArgs @@ -153,7 +186,15 @@ example = SortableTable.viewLoading attrs columns else - SortableTable.view attrs columns data + SortableTable.view attrs columns + (if isStickyAtAll then + data + |> List.repeat 10 + |> List.concat + + else + data + ) ] } @@ -275,9 +316,15 @@ type alias Settings = , customizableColumnWidth : Int , customizableColumnCellStyles : ( String, List Style ) , loading : Bool + , stickyHeader : Maybe StickyHeader } +type StickyHeader + = Default + | Custom SortableTable.StickyConfig + + controlSettings : Control Settings controlSettings = Control.record Settings @@ -296,6 +343,19 @@ controlSettings = ] ) |> Control.field "Is loading" (Control.bool False) + |> Control.field "Sticky header" + (Control.maybe False + (Control.choice + [ ( "Default", Control.value Default ) + , ( "Custom" + , Control.record SortableTable.StickyConfig + |> Control.field "topOffset" (values String.fromFloat [ 0, 10, 50 ]) + |> Control.field "zIndex" (values String.fromInt [ 0, 1, 5, 10 ]) + |> Control.map Custom + ) + ] + ) + ) type ColumnId From 51a79c82f3166aaa58b03f8f3544f1b9e40ee397 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Mon, 3 Apr 2023 11:21:29 -0500 Subject: [PATCH 19/30] set basic sticky styles on table header --- src/Nri/Ui/SortableTable/V4.elm | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index d8350aab..57c94467 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -21,6 +21,7 @@ module Nri.Ui.SortableTable.V4 exposing import Accessibility.Styled.Aria as Aria import Css exposing (..) +import Css.Global import Html.Styled as Html exposing (Html) import Html.Styled.Attributes exposing (css) import Html.Styled.Events @@ -99,6 +100,18 @@ defaultStickyConfig = } +stickyConfigStyles : StickyConfig -> List Style +stickyConfigStyles { topOffset, zIndex } = + [ Css.Global.children + [ Css.Global.thead + [ Css.position Css.sticky + , Css.top (Css.px topOffset) + , Css.zIndex (Css.int zIndex) + ] + ] + ] + + {-| Customize how the table is rendered, for example by adding sorting or stickiness. -} @@ -262,6 +275,10 @@ view attributes columns entries = config = List.foldl (\(Attribute fn) soFar -> fn soFar) defaultConfig attributes + stickyStyles = + Maybe.map stickyConfigStyles config.stickyHeader + |> Maybe.withDefault [] + tableColumns = List.map (buildTableColumn config.updateMsg config.state) columns in @@ -271,12 +288,12 @@ view attributes columns entries = sorter = findSorter columns state_.column in - Table.view [] + Table.view stickyStyles tableColumns (List.sortWith (sorter state_.sortDirection) entries) Nothing -> - Table.view [] tableColumns entries + Table.view stickyStyles tableColumns entries {-| -} @@ -286,10 +303,14 @@ viewLoading attributes columns = config = List.foldl (\(Attribute fn) soFar -> fn soFar) defaultConfig attributes + stickyStyles = + Maybe.map stickyConfigStyles config.stickyHeader + |> Maybe.withDefault [] + tableColumns = List.map (buildTableColumn config.updateMsg config.state) columns in - Table.viewLoading [] tableColumns + Table.viewLoading stickyStyles tableColumns findSorter : List (Column id entry msg) -> id -> Sorter entry From 396b93e6e43f381559a88d9ad07db50291154348 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Mon, 3 Apr 2023 11:30:09 -0500 Subject: [PATCH 20/30] tweak styles to make the border stick to the right element --- src/Nri/Ui/Table/V7.elm | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Nri/Ui/Table/V7.elm b/src/Nri/Ui/Table/V7.elm index 224668dc..0fca749a 100644 --- a/src/Nri/Ui/Table/V7.elm +++ b/src/Nri/Ui/Table/V7.elm @@ -241,7 +241,12 @@ tableBody toRow items = headersStyles : List Style headersStyles = - [ borderBottom3 (px 3) solid gray75 + [ -- We use a inset box shadown for a bottom border instead of an actual + -- border because with our use of `border-collapse: collapse`, the bottom + -- gray border sticks to the table instead of traveling with the header + -- when the header has `position: sticky` applied. + boxShadow4 inset (px 0) (px -3) gray75 + , paddingBottom (px 3) , height (px 45) , fontSize (px 15) ] From 407df35f3908f5dabb6efc65cc59581e55b529f6 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Mon, 3 Apr 2023 11:30:33 -0500 Subject: [PATCH 21/30] fix typo --- src/Nri/Ui/SortableTable/V4.elm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index 57c94467..506e51f8 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -81,7 +81,7 @@ defaultConfig = stick, in pixels. (**Default value:** 0) - `zIndex` controls where in the stacking context the header will end up. Useful to prevent elements in rows from appearing over the header. - (**Defualt value:** 0) + (**Default value:** 0) Headers are never sticky on mobile-sized viewports because doing so causes some accessibility issues with zooming and panning. From 0fe814d3b80ad7f244ddbc52fb9abdcc6c69c849 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Mon, 3 Apr 2023 11:34:35 -0500 Subject: [PATCH 22/30] set page background color to avoid shine-through --- component-catalog-app/Examples/SortableTable.elm | 6 ++++++ src/Nri/Ui/SortableTable/V4.elm | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/component-catalog-app/Examples/SortableTable.elm b/component-catalog-app/Examples/SortableTable.elm index 85b8792d..70db177c 100644 --- a/component-catalog-app/Examples/SortableTable.elm +++ b/component-catalog-app/Examples/SortableTable.elm @@ -351,6 +351,12 @@ controlSettings = , Control.record SortableTable.StickyConfig |> Control.field "topOffset" (values String.fromFloat [ 0, 10, 50 ]) |> Control.field "zIndex" (values String.fromInt [ 0, 1, 5, 10 ]) + |> Control.field "pageBackgroundColor" + (Control.choice + [ ( "white", Control.value Colors.white) + , ( "gray", Control.value Colors.gray92) + ] + ) |> Control.map Custom ) ] diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index 506e51f8..a4150e14 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -90,6 +90,7 @@ accessibility issues with zooming and panning. type alias StickyConfig = { topOffset : Float , zIndex : Int + , pageBackgroundColor : Css.Color } @@ -97,16 +98,18 @@ defaultStickyConfig : StickyConfig defaultStickyConfig = { topOffset = 0 , zIndex = 0 + , pageBackgroundColor = Nri.Ui.Colors.V1.white } stickyConfigStyles : StickyConfig -> List Style -stickyConfigStyles { topOffset, zIndex } = +stickyConfigStyles { topOffset, zIndex, pageBackgroundColor } = [ Css.Global.children [ Css.Global.thead [ Css.position Css.sticky , Css.top (Css.px topOffset) , Css.zIndex (Css.int zIndex) + , Css.backgroundColor pageBackgroundColor ] ] ] From bf51caa9c5ef7d45611f3ee096d9ba6ec7f3cc87 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Mon, 3 Apr 2023 11:40:05 -0500 Subject: [PATCH 23/30] add missing pageBackgroundColor to example code --- component-catalog-app/Examples/SortableTable.elm | 1 + 1 file changed, 1 insertion(+) diff --git a/component-catalog-app/Examples/SortableTable.elm b/component-catalog-app/Examples/SortableTable.elm index 70db177c..097ef4b1 100644 --- a/component-catalog-app/Examples/SortableTable.elm +++ b/component-catalog-app/Examples/SortableTable.elm @@ -154,6 +154,7 @@ example = ++ Code.recordMultiline [ ( "topOffset", String.fromFloat stickyConfig.topOffset ) , ( "zIndex", String.fromInt stickyConfig.zIndex ) + , ( "pageBackgroundColor", "Css.hex \"" ++ stickyConfig.pageBackgroundColor.value ++ "\"") ] 2 ) From 2ac3725a323347c9890f47425cf32dfa1cb4f006 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Mon, 3 Apr 2023 12:20:57 -0500 Subject: [PATCH 24/30] fix the too-much-padding problem --- src/Nri/Ui/Table/V7.elm | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Nri/Ui/Table/V7.elm b/src/Nri/Ui/Table/V7.elm index 0fca749a..c8831d16 100644 --- a/src/Nri/Ui/Table/V7.elm +++ b/src/Nri/Ui/Table/V7.elm @@ -246,7 +246,6 @@ headersStyles = -- gray border sticks to the table instead of traveling with the header -- when the header has `position: sticky` applied. boxShadow4 inset (px 0) (px -3) gray75 - , paddingBottom (px 3) , height (px 45) , fontSize (px 15) ] From 53b722ea91991bbe07bdb1806213bd625aaf27b6 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Mon, 3 Apr 2023 12:21:11 -0500 Subject: [PATCH 25/30] :art: --- component-catalog-app/Examples/SortableTable.elm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/component-catalog-app/Examples/SortableTable.elm b/component-catalog-app/Examples/SortableTable.elm index 097ef4b1..05ae9b6a 100644 --- a/component-catalog-app/Examples/SortableTable.elm +++ b/component-catalog-app/Examples/SortableTable.elm @@ -10,8 +10,7 @@ import Category exposing (Category(..)) import Code import Css exposing (..) import Debug.Control as Control exposing (Control) -import Debug.Control.Extra as ControlExtra -import Debug.Control.Extra exposing (values) +import Debug.Control.Extra as ControlExtra exposing (values) import Debug.Control.View as ControlView import Example exposing (Example) import Html.Styled as Html exposing (..) @@ -154,7 +153,7 @@ example = ++ Code.recordMultiline [ ( "topOffset", String.fromFloat stickyConfig.topOffset ) , ( "zIndex", String.fromInt stickyConfig.zIndex ) - , ( "pageBackgroundColor", "Css.hex \"" ++ stickyConfig.pageBackgroundColor.value ++ "\"") + , ( "pageBackgroundColor", "Css.hex \"" ++ stickyConfig.pageBackgroundColor.value ++ "\"" ) ] 2 ) @@ -187,7 +186,8 @@ example = SortableTable.viewLoading attrs columns else - SortableTable.view attrs columns + SortableTable.view attrs + columns (if isStickyAtAll then data |> List.repeat 10 @@ -354,8 +354,8 @@ controlSettings = |> Control.field "zIndex" (values String.fromInt [ 0, 1, 5, 10 ]) |> Control.field "pageBackgroundColor" (Control.choice - [ ( "white", Control.value Colors.white) - , ( "gray", Control.value Colors.gray92) + [ ( "white", Control.value Colors.white ) + , ( "gray", Control.value Colors.gray92 ) ] ) |> Control.map Custom From 559a9c3c004595e5b312582922909882901a420c Mon Sep 17 00:00:00 2001 From: charbelrami Date: Mon, 3 Apr 2023 16:17:39 -0300 Subject: [PATCH 26/30] expand the label instead of expanding the radio --- src/Nri/Ui/RadioButton/V4.elm | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Nri/Ui/RadioButton/V4.elm b/src/Nri/Ui/RadioButton/V4.elm index 6ec07a49..a461d098 100644 --- a/src/Nri/Ui/RadioButton/V4.elm +++ b/src/Nri/Ui/RadioButton/V4.elm @@ -312,7 +312,7 @@ view { label, name, value, valueToString, selectedValue } attributes = , css [ position relative , Css.marginLeft (Css.px -2) - , Css.paddingLeft (Css.px 38) + , Css.paddingLeft (Css.px 30) , Css.paddingTop (px 6) , Css.paddingBottom (px 4) , display inlineBlock @@ -383,6 +383,7 @@ view { label, name, value, valueToString, selectedValue } attributes = , Css.property "font-weight" "600" , display inlineBlock , Css.property "transition" "all 0.4s ease" + , paddingLeft (px 8) ] ] [ radioInputIcon @@ -555,9 +556,6 @@ radioInputIcon config = , displayFlex , justifyContent center , alignItems center - , -- this padding creates a hit area "bridge" between the - -- absolutely-positioned icon SVG and the label text - paddingRight (Css.px 8) ] ] [ image From 338885e73fea44ffc27bba7fc7949b6e1234894e Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Tue, 4 Apr 2023 10:36:04 -0500 Subject: [PATCH 27/30] adjust height/margin --- src/Nri/Ui/Table/V7.elm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nri/Ui/Table/V7.elm b/src/Nri/Ui/Table/V7.elm index c8831d16..18995caa 100644 --- a/src/Nri/Ui/Table/V7.elm +++ b/src/Nri/Ui/Table/V7.elm @@ -253,7 +253,7 @@ headersStyles = headerStyles : List Style headerStyles = - [ padding4 (px 15) (px 12) (px 11) (px 12) + [ padding4 (px 13) (px 12) (px 14) (px 12) , textAlign left , fontWeight bold ] From 7643d65ac1ef44a8a509bfd3b4b19f4796edd6b2 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Tue, 4 Apr 2023 11:54:15 -0500 Subject: [PATCH 28/30] make the headers 45px tall by default --- src/Nri/Ui/Table/V7.elm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nri/Ui/Table/V7.elm b/src/Nri/Ui/Table/V7.elm index 18995caa..391affb0 100644 --- a/src/Nri/Ui/Table/V7.elm +++ b/src/Nri/Ui/Table/V7.elm @@ -253,7 +253,7 @@ headersStyles = headerStyles : List Style headerStyles = - [ padding4 (px 13) (px 12) (px 14) (px 12) + [ padding4 (px 11) (px 12) (px 14) (px 12) , textAlign left , fontWeight bold ] From c94f56813b30a4f7ed52850d8fdc1e72088d7f8e Mon Sep 17 00:00:00 2001 From: Tessa Kelly Date: Tue, 4 Apr 2023 11:07:19 -0600 Subject: [PATCH 29/30] Bump --- elm.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/elm.json b/elm.json index 8c8378ba..9ec98466 100644 --- a/elm.json +++ b/elm.json @@ -3,7 +3,7 @@ "name": "NoRedInk/noredink-ui", "summary": "UI Widgets we use at NRI", "license": "BSD-3-Clause", - "version": "22.7.0", + "version": "22.8.0", "exposed-modules": [ "Browser.Events.Extra", "Nri.Ui", @@ -116,4 +116,4 @@ "elm-explorations/test": "1.2.2 <= v < 2.0.0", "tesk9/accessible-html": "5.0.0 <= v < 6.0.0" } -} +} \ No newline at end of file From 0c5345fd41995c31d01a4f132e8730fd608ae572 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Tue, 4 Apr 2023 14:42:45 -0500 Subject: [PATCH 30/30] use the column header in the non-interactive case --- src/Nri/Ui/SortableTable/V4.elm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nri/Ui/SortableTable/V4.elm b/src/Nri/Ui/SortableTable/V4.elm index a4150e14..03f64366 100644 --- a/src/Nri/Ui/SortableTable/V4.elm +++ b/src/Nri/Ui/SortableTable/V4.elm @@ -355,7 +355,7 @@ buildTableColumn maybeUpdateMsg maybeState (Column column) = viewSortHeader (column.sorter /= Nothing) column.header maybeUpdateMsg state_ column.id Nothing -> - Debug.todo "non-sorted header" + column.header , view = column.view , width = Css.px (toFloat column.width) , cellStyles = column.cellStyles