noredink-ui/styleguide-app/NriModules.elm

198 lines
6.2 KiB
Elm
Raw Normal View History

2018-02-13 00:32:38 +03:00
module NriModules exposing (ModuleStates, Msg, init, nriThemedModules, styles, subscriptions, update)
import Assets exposing (assets)
import DEPRECATED.Css.File exposing (Stylesheet, compile, stylesheet)
2018-04-30 14:24:03 +03:00
import Examples.Button
2018-03-17 01:58:00 +03:00
import Examples.Colors
import Examples.Dropdown
2018-03-17 01:27:38 +03:00
import Examples.Fonts
Extract `Nri.Icon` from the monolith The recommendation is to break the styles API rather than the view API when moving something out of the monolith into this repo. `Nri.Icon` is not really setup for that sort of breakage. If we would prefer to have the styles break rather than the view, that will take more work. Work that can be done independent of the extraction. The transition in the monolith ought to look something like: ```elm module Nri.Icon exposing (..) import Html exposing (Html) import Nri.SvgSprite import Nri.Ui.Icon.V1 exposing (Assets, IconType) icon : { alt : String, icon : IconType } -> Html msg icon config = Nri.Ui.Icon.V1.icon assets assets : Assets {} assets = { activity = Nri.SvgSprite.activity , arrowDown = Nri.SvgSprite.arrowDown , attention_svg = Nri.Assets.attention_svg ... } ``` So hopefully, the change is still very small on the monolith side. There's maybe a bigger concern than which API breaks. `Nri.Icon` has some behavior for a11y. We could definitely change the internals over during the extraction. But, since all of these changes are value-level changes, it's very likely that we'll break something in the process. That's a bigger concern because instead of affecting the handful of Engineers working at NRI, we would be affecting the millions of people using the site. We shouldn't fear making those kinds of changes. However, we should make them when we can give them the appropriate attention they deserve. Not when one person is trying to move as fast as possible to avoid race conditions of moving modules between repos.
2018-03-29 03:34:56 +03:00
import Examples.Icon
2018-05-01 18:34:16 +03:00
import Examples.Page
2018-03-24 05:05:34 +03:00
import Examples.SegmentedControl
2018-04-17 01:39:57 +03:00
import Examples.Select
import Examples.Table
2018-03-17 01:27:38 +03:00
import Examples.Text
import Examples.Text.Writing
2018-03-01 02:51:49 +03:00
import Examples.TextArea as TextAreaExample
2018-02-13 00:32:38 +03:00
import Html exposing (Html, img)
import Html.Attributes exposing (..)
import ModuleExample exposing (Category(..), ModuleExample)
import Navigation
2018-04-30 14:14:20 +03:00
import Nri.Ui.Button.V2 as Button
2018-04-16 23:12:17 +03:00
import Nri.Ui.Dropdown.V1
import Nri.Ui.Icon.V2
Style the segmented control tabs directly tl;dr; Use a class for each variant instead of overriding one variant. Before, we relied on CSS specificity in an unclear way. The `Focused` class was applying properly because it was ordered later than the `Tab` class in the stylesheet. The ordering that is important is the ordering in `styles` value. Since `elm-css` generates the stylesheet in the order of the lists, the `Focused` rule would be generated after the `Tab` rule. Meaning the `Focused` rule would take precedence over the `Tab` rule if an element had both classes as it was defined later in the stylesheet. There are some concerns with this approach: 1. It's not readily apparent that the ordering in `styles` is important. It is pretty easy to change the ordering of the list and have it break the styling. 2. We rely on `elm-css` to generate the stylesheet in a specific order. If it changes the order of rules it generates, we're almost surely going to break the styling. 3. Altering styles for tabs that are not focused is even less intuitive. Since the specificity is the same, you might not know why a given rule applies (or doesn't apply). Rather, we can eschew the specificity/precedence issues by applying a different class to each tab. The stuff that is the same can stay on the `Tab` class, and the stuff that differs can be on different classes. We are now able to set the background color for `Unfocused` tabs. We were relying on the control being placed atop a white background. When we moved to using the control atop a non-whitebackground, it showed that the `Unfocused` tabs had a transparent backround. All of our designs show `Unfocused` tabs with a white backround. See https://github.com/NoRedInk/noredink-ui/pull/14 for more information.
2018-03-30 18:51:29 +03:00
import Nri.Ui.SegmentedControl.V5
import Nri.Ui.Select.V2
2018-02-21 17:49:12 +03:00
import Nri.Ui.Text.V1 as Text
2018-03-01 02:51:49 +03:00
import Nri.Ui.TextArea.V1 as TextArea
2018-02-13 00:32:38 +03:00
import String.Extra
type alias ModuleStates =
2018-04-30 14:14:20 +03:00
{ buttonExampleState : Examples.Button.State
, dropdownState : Examples.Dropdown.State Examples.Dropdown.Value
, segmentedControlState : Examples.SegmentedControl.State
2018-04-17 01:39:57 +03:00
, selectState : Examples.Select.State Examples.Select.Value
, tableExampleState : Examples.Table.State
2018-03-24 05:05:34 +03:00
, textAreaExampleState : TextAreaExample.State
2018-03-01 02:51:49 +03:00
}
2018-02-13 00:32:38 +03:00
init : ModuleStates
init =
2018-04-30 14:14:20 +03:00
{ buttonExampleState = Examples.Button.init assets
, dropdownState = Examples.Dropdown.init
, segmentedControlState = Examples.SegmentedControl.init
2018-04-17 01:39:57 +03:00
, selectState = Examples.Select.init
, tableExampleState = Examples.Table.init
2018-03-24 05:05:34 +03:00
, textAreaExampleState = TextAreaExample.init
2018-03-01 02:51:49 +03:00
}
2018-02-13 00:32:38 +03:00
type Msg
2018-04-30 14:14:20 +03:00
= ButtonExampleMsg Examples.Button.Msg
| DropdownMsg Examples.Dropdown.Msg
| SegmentedControlMsg Examples.SegmentedControl.Msg
2018-04-17 01:39:57 +03:00
| SelectMsg Examples.Select.Msg
2018-03-24 05:05:34 +03:00
| ShowItWorked String String
| TableExampleMsg Examples.Table.Msg
2018-03-01 02:51:49 +03:00
| TextAreaExampleMsg TextAreaExample.Msg
2018-02-13 00:32:38 +03:00
| NoOp
update : Msg -> ModuleStates -> ( ModuleStates, Cmd Msg )
update msg moduleStates =
case msg of
2018-04-30 14:14:20 +03:00
ButtonExampleMsg msg ->
let
( buttonExampleState, cmd ) =
Examples.Button.update msg moduleStates.buttonExampleState
in
2018-04-30 14:24:03 +03:00
( { moduleStates | buttonExampleState = buttonExampleState }
, Cmd.map ButtonExampleMsg cmd
)
2018-04-30 14:14:20 +03:00
DropdownMsg msg ->
let
( dropdownState, cmd ) =
Examples.Dropdown.update msg moduleStates.dropdownState
in
2018-04-30 14:24:03 +03:00
( { moduleStates | dropdownState = dropdownState }
, Cmd.map DropdownMsg cmd
)
2018-03-24 05:05:34 +03:00
SegmentedControlMsg msg ->
let
( segmentedControlState, cmd ) =
Examples.SegmentedControl.update msg moduleStates.segmentedControlState
in
2018-04-30 14:24:03 +03:00
( { moduleStates | segmentedControlState = segmentedControlState }
, Cmd.map SegmentedControlMsg cmd
)
2018-03-24 05:05:34 +03:00
2018-04-17 01:39:57 +03:00
SelectMsg msg ->
let
( selectState, cmd ) =
Examples.Select.update msg moduleStates.selectState
in
2018-04-30 14:24:03 +03:00
( { moduleStates | selectState = selectState }
, Cmd.map SelectMsg cmd
)
2018-04-17 01:39:57 +03:00
2018-02-13 00:32:38 +03:00
ShowItWorked group message ->
let
_ =
Debug.log group message
in
2018-04-30 14:24:03 +03:00
( moduleStates, Cmd.none )
2018-03-01 02:51:49 +03:00
TableExampleMsg msg ->
let
( tableExampleState, cmd ) =
Examples.Table.update msg moduleStates.tableExampleState
in
2018-04-30 14:24:03 +03:00
( { moduleStates | tableExampleState = tableExampleState }
, Cmd.map TableExampleMsg cmd
)
2018-03-01 02:51:49 +03:00
TextAreaExampleMsg msg ->
let
( textAreaExampleState, cmd ) =
TextAreaExample.update msg moduleStates.textAreaExampleState
in
2018-04-30 14:24:03 +03:00
( { moduleStates | textAreaExampleState = textAreaExampleState }
, Cmd.map TextAreaExampleMsg cmd
)
2018-02-13 00:32:38 +03:00
NoOp ->
( moduleStates, Cmd.none )
subscriptions : ModuleStates -> Sub Msg
subscriptions moduleStates =
Sub.batch
[]
{-| A container with a visually-apparent size for demonstrating how style guide components
fill their parents.
-}
container : Int -> List (Html msg) -> Html msg
container width children =
Html.div
[ Html.Attributes.class "demo-container"
, style [ ( "width", toString width ++ "px" ) ]
]
children
nriThemedModules : ModuleStates -> List (ModuleExample Msg)
nriThemedModules model =
2018-04-30 14:14:20 +03:00
[ Examples.Button.example assets (exampleMessages ButtonExampleMsg) model.buttonExampleState
, Examples.Dropdown.example DropdownMsg model.dropdownState
, Examples.Icon.example
2018-05-01 18:34:16 +03:00
, Examples.Page.example NoOp
, Examples.SegmentedControl.example SegmentedControlMsg model.segmentedControlState
2018-04-17 01:39:57 +03:00
, Examples.Select.example SelectMsg model.selectState
2018-03-24 05:05:34 +03:00
, Examples.Text.example
2018-03-17 01:27:38 +03:00
, Examples.Text.Writing.example
, Examples.Fonts.example
, Examples.Table.example TableExampleMsg model.tableExampleState
2018-03-01 02:51:49 +03:00
, TextAreaExample.example TextAreaExampleMsg model.textAreaExampleState
2018-03-17 01:58:00 +03:00
, Examples.Colors.example
2018-02-13 00:32:38 +03:00
]
exampleMessages : (msg -> Msg) -> String -> ModuleExample.ModuleMessages msg Msg
exampleMessages exampleMessageWrapper exampleName =
{ noOp = NoOp
, showItWorked = ShowItWorked exampleName
, wrapper = exampleMessageWrapper
}
route : Navigation.Location -> Maybe String
route location =
location.hash
|> String.dropLeft 1
|> String.Extra.nonEmpty
styles : List Stylesheet
styles =
List.concat
[ -- NOTE: these will go away as the modules' styles are integrated with Nri.Css.Site.elm
[ ModuleExample.styles
]
Extract `Nri.Icon` from the monolith The recommendation is to break the styles API rather than the view API when moving something out of the monolith into this repo. `Nri.Icon` is not really setup for that sort of breakage. If we would prefer to have the styles break rather than the view, that will take more work. Work that can be done independent of the extraction. The transition in the monolith ought to look something like: ```elm module Nri.Icon exposing (..) import Html exposing (Html) import Nri.SvgSprite import Nri.Ui.Icon.V1 exposing (Assets, IconType) icon : { alt : String, icon : IconType } -> Html msg icon config = Nri.Ui.Icon.V1.icon assets assets : Assets {} assets = { activity = Nri.SvgSprite.activity , arrowDown = Nri.SvgSprite.arrowDown , attention_svg = Nri.Assets.attention_svg ... } ``` So hopefully, the change is still very small on the monolith side. There's maybe a bigger concern than which API breaks. `Nri.Icon` has some behavior for a11y. We could definitely change the internals over during the extraction. But, since all of these changes are value-level changes, it's very likely that we'll break something in the process. That's a bigger concern because instead of affecting the handful of Engineers working at NRI, we would be affecting the millions of people using the site. We shouldn't fear making those kinds of changes. However, we should make them when we can give them the appropriate attention they deserve. Not when one person is trying to move as fast as possible to avoid race conditions of moving modules between repos.
2018-03-29 03:34:56 +03:00
, (Examples.Icon.styles |> .css) ()
2018-05-01 18:34:16 +03:00
, (Examples.Page.styles |> .css) ()
, (Examples.SegmentedControl.styles |> .css) ()
2018-04-30 14:14:20 +03:00
, (Button.styles |> .css) assets
2018-04-16 23:12:17 +03:00
, (Nri.Ui.Dropdown.V1.styles |> .css) ()
, (Nri.Ui.Icon.V2.styles |> .css) ()
Style the segmented control tabs directly tl;dr; Use a class for each variant instead of overriding one variant. Before, we relied on CSS specificity in an unclear way. The `Focused` class was applying properly because it was ordered later than the `Tab` class in the stylesheet. The ordering that is important is the ordering in `styles` value. Since `elm-css` generates the stylesheet in the order of the lists, the `Focused` rule would be generated after the `Tab` rule. Meaning the `Focused` rule would take precedence over the `Tab` rule if an element had both classes as it was defined later in the stylesheet. There are some concerns with this approach: 1. It's not readily apparent that the ordering in `styles` is important. It is pretty easy to change the ordering of the list and have it break the styling. 2. We rely on `elm-css` to generate the stylesheet in a specific order. If it changes the order of rules it generates, we're almost surely going to break the styling. 3. Altering styles for tabs that are not focused is even less intuitive. Since the specificity is the same, you might not know why a given rule applies (or doesn't apply). Rather, we can eschew the specificity/precedence issues by applying a different class to each tab. The stuff that is the same can stay on the `Tab` class, and the stuff that differs can be on different classes. We are now able to set the background color for `Unfocused` tabs. We were relying on the control being placed atop a white background. When we moved to using the control atop a non-whitebackground, it showed that the `Unfocused` tabs had a transparent backround. All of our designs show `Unfocused` tabs with a white backround. See https://github.com/NoRedInk/noredink-ui/pull/14 for more information.
2018-03-30 18:51:29 +03:00
, (Nri.Ui.SegmentedControl.V5.styles |> .css) ()
, (Nri.Ui.Select.V2.styles |> .css) ()
2018-02-21 17:49:12 +03:00
, (Text.styles |> .css) ()
2018-03-01 02:51:49 +03:00
, (TextArea.styles |> .css) assets
2018-02-13 00:32:38 +03:00
]