mirror of
https://github.com/NoRedInk/noredink-ui.git
synced 2024-11-27 13:02:42 +03:00
Style the 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.
This commit is contained in:
parent
dd164e3e57
commit
7ebb488786
113
src/Nri/Ui/SegmentedControl/V2.elm
Normal file
113
src/Nri/Ui/SegmentedControl/V2.elm
Normal file
@ -0,0 +1,113 @@
|
||||
module Nri.Ui.SegmentedControl.V2 exposing (Config, Option, styles, view)
|
||||
|
||||
{-|
|
||||
|
||||
@docs Config, Option, styles, view
|
||||
|
||||
-}
|
||||
|
||||
import Accessibility exposing (..)
|
||||
import Accessibility.Role as Role
|
||||
import Css exposing (..)
|
||||
import Css.Foreign exposing (Snippet, adjacentSiblings, children, class, descendants, each, everything, media, selector, withClass)
|
||||
import Html
|
||||
import Html.Attributes
|
||||
import Html.Events
|
||||
import Nri.Ui.Colors.Extra exposing (withAlpha)
|
||||
import Nri.Ui.Colors.V1 as Colors
|
||||
import Nri.Ui.CssFlexBoxWithVendorPrefix as FlexBox
|
||||
import Nri.Ui.Fonts.V1
|
||||
import Nri.Ui.Styles.V1
|
||||
|
||||
|
||||
{-| -}
|
||||
type alias Config a msg =
|
||||
{ onClick : a -> msg
|
||||
, options : List (Option a)
|
||||
, selected : a
|
||||
}
|
||||
|
||||
|
||||
{-| -}
|
||||
type alias Option a =
|
||||
{ value : a
|
||||
, label : String
|
||||
, id : String
|
||||
}
|
||||
|
||||
|
||||
{-| -}
|
||||
view : Config a msg -> Html.Html msg
|
||||
view config =
|
||||
config.options
|
||||
|> List.map
|
||||
(\option ->
|
||||
Html.div
|
||||
[ Html.Attributes.id option.id
|
||||
, Role.tab
|
||||
, Html.Events.onClick (config.onClick option.value)
|
||||
, styles.class
|
||||
[ Tab
|
||||
, focusedClass option.value config.selected
|
||||
]
|
||||
]
|
||||
[ Html.text option.label
|
||||
]
|
||||
)
|
||||
|> div [ Role.tabList, styles.class [ SegmentedControl ] ]
|
||||
|
||||
|
||||
focusedClass : a -> a -> CssClass
|
||||
focusedClass value selected =
|
||||
if value == selected then
|
||||
Focused
|
||||
else
|
||||
Unfocused
|
||||
|
||||
|
||||
type CssClass
|
||||
= SegmentedControl
|
||||
| Tab
|
||||
| Focused
|
||||
| Unfocused
|
||||
|
||||
|
||||
{-| -}
|
||||
styles : Nri.Ui.Styles.V1.Styles Never CssClass msg
|
||||
styles =
|
||||
Nri.Ui.Styles.V1.styles "Nri-Ui-SegmentedControl-V2-"
|
||||
[ Css.Foreign.class SegmentedControl
|
||||
[ FlexBox.displayFlex
|
||||
, cursor pointer
|
||||
]
|
||||
, Css.Foreign.class Tab
|
||||
[ padding2 (px 6) (px 20)
|
||||
, height (px 45)
|
||||
, Nri.Ui.Fonts.V1.baseFont
|
||||
, fontSize (px 15)
|
||||
, fontWeight bold
|
||||
, lineHeight (px 30)
|
||||
, firstChild
|
||||
[ borderTopLeftRadius (px 8)
|
||||
, borderBottomLeftRadius (px 8)
|
||||
, borderLeft3 (px 1) solid Colors.azure
|
||||
]
|
||||
, lastChild
|
||||
[ borderTopRightRadius (px 8)
|
||||
, borderBottomRightRadius (px 8)
|
||||
]
|
||||
, border3 (px 1) solid Colors.azure
|
||||
, borderLeft (px 0)
|
||||
, boxSizing borderBox
|
||||
]
|
||||
, Css.Foreign.class Focused
|
||||
[ color Colors.gray20
|
||||
, backgroundColor Colors.glacier
|
||||
, boxShadow5 inset zero (px 3) zero (withAlpha 0.2 Colors.gray20)
|
||||
, borderBottom3 (px 1) solid Colors.azure
|
||||
]
|
||||
, Css.Foreign.class Unfocused
|
||||
[ borderBottom3 (px 3) solid Colors.azure
|
||||
, color Colors.azure
|
||||
]
|
||||
]
|
Loading…
Reference in New Issue
Block a user