mirror of
https://github.com/NoRedInk/noredink-ui.git
synced 2024-11-27 03:14:25 +03:00
💀 remove segmented control v9 and v10
This commit is contained in:
parent
9053c4d283
commit
9c8e475aa8
4
elm.json
4
elm.json
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
@ -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
|
||||
]
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user