allow SegmentedControl to be centered

This commit is contained in:
Brian Hicks 2020-08-20 15:58:31 -05:00
parent 95b1592854
commit 9aead358a5
2 changed files with 51 additions and 21 deletions

View File

@ -1,17 +1,18 @@
module Nri.Ui.SegmentedControl.V12 exposing
( Option, view
, Radio, viewRadioGroup
, Width(..)
, Positioning(..), Width(..)
)
{-| Changes from V11:
- allow HTML in labels
- [use idString instead of toString](https://github.com/NoRedInk/noredink-ui/issues/575)
- allow control to be centered
@docs Option, view
@docs Radio, viewRadioGroup
@docs Width
@docs Positioning, Width
-}
@ -36,6 +37,12 @@ import Nri.Ui.Util exposing (dashify)
import TabsInternal
{-| -}
type Positioning
= Left Width
| Center
{-| -}
type Width
= FitContent
@ -58,7 +65,7 @@ type alias Radio value msg =
- `toString`: function to get the radio value as a string
- `options`: the list of options available
- `selected`: if present, the value of the currently-selected option
- `width`: how to size the segmented control
- `positioning`: how to position and size the segmented control
- `legend`:
- value read to screenreader users to explain the radio group's purpose <https://dequeuniversity.com/rules/axe/3.3/radiogroup?application=axeAPI>
- after lowercasing & dashifying, this value is used to group the radio buttons together
@ -68,7 +75,7 @@ viewRadioGroup :
{ onSelect : a -> msg
, options : List (Radio a msg)
, selected : Maybe a
, width : Width
, positioning : Positioning
, legend : String
}
-> Html msg
@ -86,7 +93,7 @@ viewRadioGroup config =
-- is not
(Css.pseudoClass "focus-within"
[ Css.property "outline-style" "auto" ]
:: styles config.width isSelected
:: styles config.positioning isSelected
)
]
[ radio name option.idString isSelected <|
@ -113,7 +120,16 @@ viewRadioGroup config =
div
[ Role.radioGroup
, Aria.labelledBy legendId
, css [ displayFlex, cursor pointer ]
, css
[ displayFlex
, cursor pointer
, case config.positioning of
Left _ ->
justifyContent flexStart
Center ->
justifyContent center
]
]
(p (Attributes.id legendId :: Style.invisible) [ text config.legend ]
:: List.map viewRadio config.options
@ -137,7 +153,7 @@ type alias Option value msg =
- `onFocus` : the message to focus an element by id string
- `options`: the list of options available
- `selected`: the value of the currently-selected option
- `width`: how to size the segmented control
- `positioning`: how to position and 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.
-}
@ -146,7 +162,7 @@ view :
, onFocus : String -> msg
, options : List (Option a msg)
, selected : a
, width : Width
, positioning : Positioning
, toUrl : Maybe (a -> String)
}
-> Html msg
@ -168,8 +184,18 @@ view config =
, onFocus = config.onFocus
, selected = config.selected
, tabs = List.map toInternalTab config.options
, tabListStyles = [ displayFlex, cursor pointer, marginBottom (px 10) ]
, tabStyles = styles config.width
, tabListStyles =
[ displayFlex
, cursor pointer
, marginBottom (px 10)
, case config.positioning of
Left _ ->
justifyContent flexStart
Center ->
justifyContent center
]
, tabStyles = styles config.positioning
}
in
div []
@ -197,20 +223,23 @@ viewIcon icon =
|> Svg.toHtml
styles : Width -> Bool -> List Style
styles width isSelected =
styles : Positioning -> Bool -> List Style
styles positioning isSelected =
[ sharedSegmentStyles
, if isSelected then
focusedSegmentStyles
else
unFocusedSegmentStyles
, case width of
FitContent ->
, case positioning of
Left FitContent ->
Css.batch []
FillContainer ->
Left FillContainer ->
expandingTabStyles
Center ->
Css.batch []
]

View File

@ -51,7 +51,7 @@ example =
{ onSelect = SelectPage
, onFocus = Focus
, selected = state.page
, width = options.width
, positioning = options.positioning
, toUrl = Nothing
, options = List.take options.count (buildOptions options)
}
@ -64,7 +64,7 @@ example =
, onSelect = SelectRadio
, options = List.take options.count (buildRadioOptions options.icon)
, selected = state.optionallySelected
, width = options.width
, positioning = options.positioning
}
]
, categories = [ Widgets, Layout ]
@ -185,7 +185,7 @@ init =
type alias Options =
{ width : SegmentedControl.Width
{ positioning : SegmentedControl.Positioning
, icon : Bool
, count : Int
, longContent : Bool
@ -195,10 +195,11 @@ type alias Options =
optionsControl : Control Options
optionsControl =
Control.record Options
|> Control.field "width"
|> Control.field "positioning"
(Control.choice
[ ( "FitContent", Control.value SegmentedControl.FitContent )
, ( "FillContainer", Control.value SegmentedControl.FillContainer )
[ ( "Left (FitContent)", Control.value (SegmentedControl.Left SegmentedControl.FitContent) )
, ( "Left (FillContainer)", Control.value (SegmentedControl.Left SegmentedControl.FillContainer) )
, ( "Center", Control.value SegmentedControl.Center )
]
)
|> Control.field "icon" (Control.bool True)