diff --git a/src/Nri/Ui/SortableTable/V1.elm b/src/Nri/Ui/SortableTable/V1.elm new file mode 100644 index 00000000..207558d2 --- /dev/null +++ b/src/Nri/Ui/SortableTable/V1.elm @@ -0,0 +1,99 @@ +module Nri.Ui.SortableTable.V1 exposing (Direction(..), arrow, arrowActive, arrows, downArrow, sortActive, sortButton, sortHeader, sortInactive, upArrow) + +import Css exposing (..) +import Css.File exposing (Stylesheet, UniqueClass, stylesheet, uniqueClass) +import Css.Global exposing (Snippet, adjacentSiblings, children, class, descendants, each, everything, media, selector, withClass) +import Css.VendorPrefixed +import FlexBoxWithVendorPrefix as FlexBox +import Nri.Ui.Colors.V1 + + +sortHeader : UniqueClass +sortHeader = + uniqueClass + [ FlexBox.displayFlex + , FlexBox.alignItems FlexBox.center + , FlexBox.justifyContent FlexBox.spaceBetween + , cursor pointer + , Css.VendorPrefixed.property "user-select" "none" + ] + + +sortButton : UniqueClass +sortButton = + uniqueClass + [ padding (px 2) + , color Nri.Ui.Colors.V1.gray75 + ] + + +sortInactive : UniqueClass +sortInactive = + uniqueClass + [ fontWeight normal ] + + +sortActive : UniqueClass +sortActive = + uniqueClass + [ fontWeight bold ] + + +arrows : UniqueClass +arrows = + uniqueClass + [ FlexBox.displayFlex + , FlexBox.flexDirection FlexBox.column + , FlexBox.alignItems FlexBox.center + , FlexBox.justifyContent FlexBox.center + ] + + +type Direction + = Up + | Down + + +arrow : Direction -> UniqueClass +arrow direction = + let + result = + case direction of + Up -> + [] + + Down -> + [ transform <| rotate (deg 180) ] + in + uniqueClass + [ width (px 8) + , height (px 6) + , position relative + , margin2 (px 1) zero + , children + [ selector "svg" + ([ position absolute + , top zero + , left zero + ] + ++ result + ) + ] + ] + + +upArrow : UniqueClass +upArrow = + arrow Up + + +downArrow : UniqueClass +downArrow = + arrow Down + + +arrowActive : UniqueClass +arrowActive = + uniqueClass + [ color Nri.Ui.Colors.V1.azure + ] diff --git a/styleguide-app/Examples/SortableTable.elm b/styleguide-app/Examples/SortableTable.elm new file mode 100644 index 00000000..f4865195 --- /dev/null +++ b/styleguide-app/Examples/SortableTable.elm @@ -0,0 +1,94 @@ +module Examples.SortableTable exposing (Msg, State, example, init, update) + +{-| + + @docs Msg, State, example, init, update + +-} + +import Html +import ModuleExample as ModuleExample exposing (Category(..), ModuleExample) +import Nri.Ui.SortableTable.V1 as SortableTable + + +type Column + = FirstName + | LastName + | Coins + + +{-| -} +type Msg + = NoOp + | SetSortState (SortableTable.State Column) + + +{-| -} +type alias State = + { sortState : SortableTable.State Column } + + +{-| -} +example : (Msg -> msg) -> State -> ModuleExample msg +example parentMessage { sortState } = + { filename = "Nri.Ui.SortableTable.V1" + , category = Layout + , content = + let + config = + { updateMsg = SetSortState + , columns = + [ SortableTable.string + { id = FirstName + , header = "First name" + , value = .firstName + , width = 125 + } + , SortableTable.string + { id = LastName + , header = "Last name" + , value = .lastName + , width = 125 + } + , SortableTable.custom + { id = Coins + , header = Html.text "Coins" + , view = .coins >> String.fromInt >> Html.text + , sorter = SortableTable.simpleSort .coins + , width = 125 + } + ] + } + + data = + [ { firstName = "First1", lastName = "Last1", coins = 1 } + , { firstName = "First2", lastName = "Last2", coins = 2 } + , { firstName = "First3", lastName = "Last3", coins = 3 } + , { firstName = "First4", lastName = "Last4", coins = 4 } + , { firstName = "First5", lastName = "Last5", coins = 5 } + ] + in + [ Html.h4 [] [ Html.text "With sortable headers" ] + , SortableTable.view config sortState data + , Html.h4 [] [ Html.text "Loading" ] + , SortableTable.viewLoading config sortState + ] + |> List.map (Html.map parentMessage) + } + + +{-| -} +init : State +init = + { sortState = SortableTable.init FirstName } + + +{-| -} +update : Msg -> State -> ( State, Cmd Msg ) +update msg state = + case msg of + NoOp -> + ( state, Cmd.none ) + + SetSortState sortState -> + ( { state | sortState = sortState }, Cmd.none ) diff --git a/styleguide-app/NriModules.elm b/styleguide-app/NriModules.elm index e757c83f..9fc646f9 100644 --- a/styleguide-app/NriModules.elm +++ b/styleguide-app/NriModules.elm @@ -17,6 +17,7 @@ import Examples.SegmentedControl import Examples.Select import Examples.Slide import Examples.SlideModal +import Examples.SortableTable import Examples.Table import Examples.Tabs import Examples.Text @@ -44,6 +45,7 @@ type alias ModuleStates = , modalExampleState : Examples.Modal.State , slideModalExampleState : Examples.SlideModal.State , slideExampleState : Examples.Slide.State + , sortableTableState : Examples.SortableTable.State , tabsExampleState : Examples.Tabs.Tab } @@ -64,6 +66,7 @@ init = , modalExampleState = Examples.Modal.init , slideModalExampleState = Examples.SlideModal.init , slideExampleState = Examples.Slide.init + , sortableTableState = Examples.SortableTable.init , tabsExampleState = Examples.Tabs.First } @@ -84,6 +87,7 @@ type Msg | ModalExampleMsg Examples.Modal.Msg | SlideModalExampleMsg Examples.SlideModal.Msg | SlideExampleMsg Examples.Slide.Msg + | SortableTableMsg Examples.SortableTable.Msg | TabsExampleMsg Examples.Tabs.Tab | NoOp @@ -221,6 +225,15 @@ update outsideMsg moduleStates = , Cmd.map SlideExampleMsg cmd ) + SortableTableMsg msg -> + let + ( sortableTableState, cmd ) = + Examples.SortableTable.update msg moduleStates.sortableTableState + in + ( { moduleStates | sortableTableState = sortableTableState } + , Cmd.map SortableTableMsg cmd + ) + TabsExampleMsg tab -> ( { moduleStates | tabsExampleState = tab } , Cmd.none @@ -272,6 +285,7 @@ nriThemedModules model = , Examples.Modal.example ModalExampleMsg model.modalExampleState , Examples.SlideModal.example SlideModalExampleMsg model.slideModalExampleState , Examples.Slide.example SlideExampleMsg model.slideExampleState + , Examples.SortableTable.example SortableTableMsg model.sortableTableState , Examples.Tabs.example TabsExampleMsg model.tabsExampleState ]