💀 remove segmented control v9 and v10

This commit is contained in:
Tessa Kelly 2020-08-17 13:47:27 -07:00
parent 9053c4d283
commit 9c8e475aa8
4 changed files with 1 additions and 615 deletions

View File

@ -44,8 +44,6 @@
"Nri.Ui.Pennant.V2",
"Nri.Ui.PremiumCheckbox.V6",
"Nri.Ui.RadioButton.V1",
"Nri.Ui.SegmentedControl.V9",
"Nri.Ui.SegmentedControl.V10",
"Nri.Ui.SegmentedControl.V11",
"Nri.Ui.Select.V5",
"Nri.Ui.Select.V7",
@ -90,4 +88,4 @@
"avh4/elm-program-test": "3.1.0 <= v < 4.0.0",
"elm-explorations/test": "1.2.0 <= v < 2.0.0"
}
}
}

View File

@ -1,305 +0,0 @@
module Nri.Ui.SegmentedControl.V10 exposing
( Option, view
, SelectOption, viewSelect
, Width(..)
)
{-| Changes from V9:
- hides non-displayed content rather than fully removing from the DOM, allowing for the content the SegmentedControl controls to have overflowY: auto & maintain scroll position
- 💀 removes NavConfig and SelectConfig
- combines `view` and `viewSpa` (for V9 `view` behavior, be sure `toUrl` is Nothing. for V9 `viewSpa` behavior, pass through a Just as `toUrl`)
- add custom attributes hole to the Option (in order to make SegmentedControls compatible with the Modal component)
- combine `css` attributes into one to prevent class-name-order-change css :bug:s
- :bug: fix overflowing-y svg icon issue
@docs Option, view
@docs SelectOption, viewSelect
@docs Width
-}
import Accessibility.Styled exposing (..)
import Accessibility.Styled.Aria as Aria
import Accessibility.Styled.Role as Role
import Accessibility.Styled.Widget as Widget
import Css exposing (..)
import EventExtras
import Html.Styled
import Html.Styled.Attributes as Attributes exposing (css, href)
import Html.Styled.Events as Events
import Html.Styled.Keyed as Keyed
import Nri.Ui
import Nri.Ui.Colors.Extra exposing (withAlpha)
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Fonts.V1 as Fonts
import Nri.Ui.Html.Attributes.V2 as AttributesExtra
import Nri.Ui.Svg.V1 as Svg exposing (Svg)
import Nri.Ui.Util exposing (dashify)
{-| -}
type Width
= FitContent
| FillContainer
{-| -}
type alias SelectOption value msg =
{ value : value
, label : String
, attributes : List (Attribute msg)
, icon : Maybe Svg
}
{-| Creates _just the segmented select_ when you need the ui element itself and
not a page control
- `onClick` : the message to produce when an option is selected (clicked) by the user
- `options`: the list of options available
- `selected`: if present, the value of the currently-selected option
- `width`: how to size the segmented control
-}
viewSelect :
{ onClick : a -> msg
, options : List (SelectOption a msg)
, selected : Maybe a
, width : Width
}
-> Html msg
viewSelect config =
let
viewRadio option =
let
isSelected =
Just option.value == config.selected
in
button
([ Attributes.id (segmentIdFor option)
, css (getStyles { isSelected = isSelected, width = config.width })
, Role.radio
, if isSelected then
Widget.selected True
else
Widget.selected False
, Events.onClick (config.onClick option.value)
]
++ option.attributes
)
[ viewIcon option.icon
, text option.label
]
in
div
[ css
[ displayFlex
, cursor pointer
]
, Role.radioGroup
]
(List.map viewRadio config.options)
{-| -}
type alias Option value msg =
{ value : value
, label : String
, attributes : List (Attribute msg)
, icon : Maybe Svg
, content : Html msg
}
{-|
- `onClick` : the message to produce when an option is selected (clicked) by the user
- `options`: the list of options available
- `selected`: the value of the currently-selected option
- `width`: how to size the segmented control
- `toUrl`: a optional function that takes a `route` and returns the URL of that route. You should always use pass a `toUrl` function when the segmented control options correspond to routes in your SPA.
-}
view :
{ onClick : a -> msg
, options : List (Option a msg)
, selected : a
, width : Width
, toUrl : Maybe (a -> String)
}
-> Html msg
view config =
let
isSelected option =
option.value == config.selected
viewTab option =
case config.toUrl of
Just toUrl ->
-- This is a for a SPA view
Html.Styled.a
(href (toUrl option.value)
:: EventExtras.onClickPreventDefaultForLinkWithHref
(config.onClick option.value)
:: tabAttributes option
++ option.attributes
)
[ viewIcon option.icon
, text option.label
]
Nothing ->
-- This is for a non-SPA view
button
(Events.onClick (config.onClick option.value)
:: tabAttributes option
++ option.attributes
)
[ viewIcon option.icon
, text option.label
]
tabAttributes option =
[ Attributes.id (segmentIdFor option)
, css (getStyles { isSelected = isSelected option, width = config.width })
, Role.tab
, if isSelected option then
Aria.currentPage
else
AttributesExtra.none
]
viewTabPanel option =
tabPanel
[ Aria.labelledBy (segmentIdFor option)
, css
[ paddingTop (px 10)
, if isSelected option then
Css.batch []
else
Css.display none
]
, Widget.hidden (not (isSelected option))
]
[ option.content
]
in
div []
[ tabList [ css [ displayFlex, cursor pointer ] ]
(List.map viewTab config.options)
, Keyed.node "div" [] <|
List.map (\option -> ( keyedNodeIdFor option, viewTabPanel option ))
config.options
]
segmentIdFor : { option | label : String } -> String
segmentIdFor option =
"Nri-Ui-SegmentedControl-Segment-" ++ dashify option.label
keyedNodeIdFor : { option | label : String } -> String
keyedNodeIdFor option =
"Nri-Ui-SegmentedControl-Panel-keyed-node-" ++ dashify option.label
panelIdFor : { option | label : String } -> String
panelIdFor option =
"Nri-Ui-SegmentedControl-Panel-" ++ dashify option.label
viewIcon : Maybe Svg.Svg -> Html msg
viewIcon icon =
case icon of
Nothing ->
text ""
Just svg ->
svg
|> Svg.withWidth (px 18)
|> Svg.withHeight (px 18)
|> Svg.withCss
[ display inlineBlock
, verticalAlign textTop
, lineHeight (px 15)
, marginRight (px 8)
]
|> Svg.toHtml
getStyles : { isSelected : Bool, width : Width } -> List Style
getStyles { isSelected, width } =
[ sharedSegmentStyles
, if isSelected then
focusedSegmentStyles
else
unFocusedSegmentStyles
, case width of
FitContent ->
Css.batch []
FillContainer ->
expandingTabStyles
]
sharedSegmentStyles : Style
sharedSegmentStyles =
[ padding2 (px 6) (px 20)
, height (px 45)
, Fonts.baseFont
, fontSize (px 15)
, fontWeight bold
, lineHeight (px 30)
, margin zero
, firstOfType
[ borderTopLeftRadius (px 8)
, borderBottomLeftRadius (px 8)
, borderLeft3 (px 1) solid Colors.azure
]
, lastOfType
[ borderTopRightRadius (px 8)
, borderBottomRightRadius (px 8)
]
, border3 (px 1) solid Colors.azure
, borderLeft (px 0)
, boxSizing borderBox
, cursor pointer
, property "transition" "background-color 0.2s, color 0.2s, box-shadow 0.2s, border 0.2s, border-width 0s"
, textDecoration none
, hover [ textDecoration none ]
, focus [ textDecoration none ]
]
|> Css.batch
focusedSegmentStyles : Style
focusedSegmentStyles =
[ backgroundColor Colors.glacier
, boxShadow5 inset zero (px 3) zero (withAlpha 0.2 Colors.gray20)
, color Colors.navy
]
|> Css.batch
unFocusedSegmentStyles : Style
unFocusedSegmentStyles =
[ backgroundColor Colors.white
, boxShadow5 inset zero (px -2) zero Colors.azure
, color Colors.azure
, hover [ backgroundColor Colors.frost ]
]
|> Css.batch
expandingTabStyles : Style
expandingTabStyles =
[ flexGrow (int 1)
, textAlign center
]
|> Css.batch

View File

@ -1,305 +0,0 @@
module Nri.Ui.SegmentedControl.V9 exposing (NavConfig, Option, Width(..), view, viewSpa, SelectConfig, viewSelect)
{-|
@docs NavConfig, Option, Width, view, viewSpa, SelectConfig, viewSelect
Changes from V7:
- remove dependence on Nri.Ui.Icon.V5
- fix icons overlowing the segmented control
-}
import Accessibility.Styled exposing (..)
import Accessibility.Styled.Aria as Aria
import Accessibility.Styled.Role as Role
import Accessibility.Styled.Widget as Widget
import Css exposing (..)
import EventExtras
import Html.Styled
import Html.Styled.Attributes as Attr exposing (css, href)
import Html.Styled.Events as Events
import Nri.Ui
import Nri.Ui.Colors.Extra exposing (withAlpha)
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Fonts.V1 as Fonts
import Nri.Ui.Svg.V1 as Svg exposing (Svg)
import Nri.Ui.Util exposing (dashify)
{-|
- `onClick` : the message to produce when an option is selected (clicked) by the user
- `options`: the list of options available
- `selected`: the value of the currently-selected option
- `width`: how to size the segmented control
- `content`: the panel content for the selected option
-}
type alias NavConfig a msg =
{ onClick : a -> msg
, options : List (Option a)
, selected : a
, width : Width
, content : Html msg
}
{-|
- `onClick` : the message to produce when an option is selected (clicked) by the user
- `options`: the list of options available
- `selected`: if present, the value of the currently-selected option
- `width`: how to size the segmented control
-}
type alias SelectConfig a msg =
{ onClick : a -> msg
, options : List (Option a)
, selected : Maybe a
, width : Width
}
{-| -}
type alias Option a =
{ value : a
, icon : Maybe Svg
, label : String
}
{-| -}
type Width
= FitContent
| FillContainer
{-| -}
view : NavConfig a msg -> Html msg
view config =
viewHelper Nothing config
{-| Creates a segmented control that supports SPA navigation.
You should always use this instead of `view` when building a SPA
and the segmented control options correspond to routes in the SPA.
The first parameter is a function that takes a `route` and returns the URL of that route.
-}
viewSpa : (route -> String) -> NavConfig route msg -> Html msg
viewSpa toUrl config =
viewHelper (Just toUrl) config
{-| Creates _just the segmented select_ when you need the ui element itself and
not a page control
-}
viewSelect : SelectConfig a msg -> Html msg
viewSelect config =
div
[ css
[ displayFlex
, cursor pointer
]
, Role.radioGroup
]
(List.map
(viewSegment
{ onClick = config.onClick
, selected = config.selected
, width = config.width
, selectedAttribute = Widget.selected True
, maybeToUrl = Nothing
}
Role.radio
)
config.options
)
viewHelper : Maybe (a -> String) -> NavConfig a msg -> Html msg
viewHelper maybeToUrl config =
let
selected =
config.options
|> List.filter (\o -> o.value == config.selected)
|> List.head
in
div []
[ tabList
[ css
[ displayFlex
, cursor pointer
]
]
(List.map
(viewSegment
{ onClick = config.onClick
, selected = Just config.selected
, width = config.width
, selectedAttribute = Aria.currentPage
, maybeToUrl = maybeToUrl
}
Role.tab
)
config.options
)
, tabPanel
(List.filterMap identity
[ Maybe.map (Aria.labelledBy << segmentIdFor) selected
, Just <| css [ paddingTop (px 10) ]
]
)
[ config.content
]
]
segmentIdFor : Option a -> String
segmentIdFor option =
"Nri-Ui-SegmentedControl-Segment-" ++ dashify option.label
panelIdFor : Option a -> String
panelIdFor option =
"Nri-Ui-SegmentedControl-Panel-" ++ dashify option.label
viewSegment :
{ onClick : a -> msg
, selected : Maybe a
, width : Width
, selectedAttribute : Attribute msg
, maybeToUrl : Maybe (a -> String)
}
-> Html.Styled.Attribute msg
-> Option a
-> Html msg
viewSegment config ariaRole option =
let
idValue =
segmentIdFor option
element attrs children =
case config.maybeToUrl of
Nothing ->
-- This is for a non-SPA view
button
(Events.onClick (config.onClick option.value)
:: attrs
)
children
Just toUrl ->
-- This is a for a SPA view
Html.Styled.a
(href (toUrl option.value)
:: EventExtras.onClickPreventDefaultForLinkWithHref
(config.onClick option.value)
:: attrs
)
children
in
element
(List.concat
[ [ Attr.id idValue
, ariaRole
, css sharedSegmentStyles
]
, if Just option.value == config.selected then
[ css focusedSegmentStyles
, config.selectedAttribute
]
else
[ css unFocusedSegmentStyles ]
, case config.width of
FitContent ->
[]
FillContainer ->
[ css expandingTabStyles ]
]
)
[ case option.icon of
Nothing ->
text ""
Just svg ->
span
[ css
[ maxWidth (px 18)
, width (px 18)
, maxHeight (px 18)
, height (px 18)
, display inlineBlock
, verticalAlign textTop
, lineHeight (px 15)
, marginRight (px 8)
]
]
[ Svg.toHtml svg ]
, text option.label
]
sharedSegmentStyles : List Style
sharedSegmentStyles =
[ padding2 (px 6) (px 20)
, height (px 45)
, Fonts.baseFont
, fontSize (px 15)
, fontWeight bold
, lineHeight (px 30)
, margin zero
, firstOfType
[ borderTopLeftRadius (px 8)
, borderBottomLeftRadius (px 8)
, borderLeft3 (px 1) solid Colors.azure
]
, lastOfType
[ borderTopRightRadius (px 8)
, borderBottomRightRadius (px 8)
]
, border3 (px 1) solid Colors.azure
, borderLeft (px 0)
, boxSizing borderBox
, cursor pointer
, property "transition" "background-color 0.2s, color 0.2s, box-shadow 0.2s, border 0.2s, border-width 0s"
, textDecoration none
, hover
[ textDecoration none
]
, focus
[ textDecoration none
]
]
focusedSegmentStyles : List Style
focusedSegmentStyles =
[ backgroundColor Colors.glacier
, boxShadow5 inset zero (px 3) zero (withAlpha 0.2 Colors.gray20)
, color Colors.navy
]
unFocusedSegmentStyles : List Style
unFocusedSegmentStyles =
[ backgroundColor Colors.white
, boxShadow5 inset zero (px -2) zero Colors.azure
, color Colors.azure
, hover
[ backgroundColor Colors.frost
]
]
expandingTabStyles : List Style
expandingTabStyles =
[ flexGrow (int 1)
, textAlign center
]

View File

@ -40,8 +40,6 @@
"Nri.Ui.Pennant.V2",
"Nri.Ui.PremiumCheckbox.V6",
"Nri.Ui.RadioButton.V1",
"Nri.Ui.SegmentedControl.V9",
"Nri.Ui.SegmentedControl.V10",
"Nri.Ui.SegmentedControl.V11",
"Nri.Ui.Select.V5",
"Nri.Ui.Select.V7",