noredink-ui/styleguide-app/Examples/SegmentedControl.elm

250 lines
7.1 KiB
Elm
Raw Normal View History

2018-09-26 17:02:10 +03:00
module Examples.SegmentedControl exposing
2020-03-31 22:43:32 +03:00
( Msg, State
2018-09-26 17:02:10 +03:00
, example
)
2018-03-24 05:05:34 +03:00
{-|
2020-03-31 22:43:32 +03:00
@docs Msg, State
@docs example
2018-03-24 05:05:34 +03:00
-}
2020-08-05 03:52:30 +03:00
import Accessibility.Styled as Html exposing (Html)
2020-06-19 23:41:28 +03:00
import AtomicDesignType exposing (AtomicDesignType(..))
2020-08-06 01:19:09 +03:00
import Browser.Dom as Dom
import Category exposing (Category(..))
2020-08-05 04:08:16 +03:00
import Css
import Debug.Control as Control exposing (Control)
2020-03-31 23:20:03 +03:00
import Example exposing (Example)
2020-08-05 04:08:16 +03:00
import Html.Styled.Attributes as Attributes exposing (css)
import Html.Styled.Events as Events
import KeyboardSupport exposing (Direction(..), Key(..))
import Nri.Ui.Colors.V1 as Colors
2020-08-20 23:06:21 +03:00
import Nri.Ui.SegmentedControl.V12 as SegmentedControl
2019-10-24 23:23:52 +03:00
import Nri.Ui.Svg.V1 as Svg exposing (Svg)
2019-10-24 21:08:28 +03:00
import Nri.Ui.UiIcon.V1 as UiIcon
import String exposing (toLower)
2020-08-06 01:19:09 +03:00
import Task
2018-03-24 05:05:34 +03:00
{-| -}
2020-03-31 23:20:03 +03:00
example : Example State Msg
2020-03-31 22:43:32 +03:00
example =
2020-08-20 23:06:21 +03:00
{ name = "Nri.Ui.SegmentedControl.V12"
2020-03-31 22:43:32 +03:00
, state = init
, update = update
2020-03-31 22:48:26 +03:00
, subscriptions = \_ -> Sub.none
2020-03-31 22:43:32 +03:00
, view =
\state ->
let
options =
Control.currentValue state.optionsControl
in
[ Control.view ChangeOptions state.optionsControl
|> Html.fromUnstyled
2020-08-05 04:08:16 +03:00
, Html.h3 [ css [ Css.marginBottom Css.zero ] ]
[ Html.code [] [ Html.text "view" ] ]
, Html.p [ css [ Css.marginTop (Css.px 1) ] ]
2020-08-06 00:03:48 +03:00
[ Html.text "Use in cases where it would also be reasonable to use Tabs." ]
2020-08-05 03:52:30 +03:00
, SegmentedControl.view
2020-08-06 01:19:09 +03:00
{ onSelect = SelectPage
, onFocus = Focus
2020-08-05 05:30:24 +03:00
, selected = state.page
2020-08-20 23:58:31 +03:00
, positioning = options.positioning
2020-08-05 05:06:28 +03:00
, toUrl = Nothing
2020-08-05 07:35:10 +03:00
, options = List.take options.count (buildOptions options)
2020-03-31 22:43:32 +03:00
}
2020-08-05 04:08:16 +03:00
, Html.h3 [ css [ Css.marginBottom Css.zero ] ]
2020-08-05 23:20:48 +03:00
[ Html.code [] [ Html.text "viewRadioGroup" ] ]
2020-08-05 04:08:16 +03:00
, Html.p [ css [ Css.marginTop (Css.px 1) ] ]
2020-08-06 00:03:48 +03:00
[ Html.text "Use in cases where it would be reasonable to use radio buttons for the same purpose." ]
2020-08-05 23:20:48 +03:00
, SegmentedControl.viewRadioGroup
2020-08-06 02:22:33 +03:00
{ legend = "SegmentedControls 'viewSelectRadio' example"
2020-08-06 01:25:26 +03:00
, onSelect = SelectRadio
2020-08-05 23:20:48 +03:00
, options = List.take options.count (buildRadioOptions options.icon)
, selected = state.optionallySelected
2020-08-20 23:58:31 +03:00
, positioning = options.positioning
}
2020-03-31 22:43:32 +03:00
]
, categories = [ Widgets, Layout ]
2020-06-20 00:16:10 +03:00
, atomicDesignType = Molecule
, keyboardSupport =
2020-08-06 01:58:40 +03:00
[ { keys = [ KeyboardSupport.Tab ]
, result = "Move focus to the currently-selected Control's content"
}
, { keys = [ Arrow KeyboardSupport.Left ]
, result = "Select the Control to the left of the current selection"
}
, { keys = [ Arrow KeyboardSupport.Right ]
, result = "Select the Control to the right of the current selection"
}
]
2018-03-24 05:05:34 +03:00
}
2020-08-05 05:30:24 +03:00
type Page
= Flag
| Sprout
| Star
| Sapling
| Attention
| Tree
| Premium
| Activity
2020-08-05 07:35:10 +03:00
buildOptions : { options | icon : Bool, longContent : Bool } -> List (SegmentedControl.Option Page Msg)
buildOptions { icon, longContent } =
2020-08-05 05:30:24 +03:00
let
2020-08-05 07:35:10 +03:00
buildOption value icon_ =
{ icon =
if icon then
Just icon_
else
Nothing
2020-08-20 23:13:35 +03:00
, label = Html.text (Debug.toString value)
2020-08-05 05:30:24 +03:00
, value = value
2020-08-20 23:41:50 +03:00
, idString = toLower (Debug.toString value)
2020-08-05 05:30:24 +03:00
, attributes = []
2020-08-05 07:35:10 +03:00
, content =
if longContent then
Html.div
[ css
[ Css.maxHeight (Css.px 100)
, Css.overflowY Css.auto
]
]
[ Html.p [] [ Html.text <| "Content for " ++ Debug.toString value ]
, Html.ol [] <|
List.map (\i -> Html.li [] [ Html.text (Debug.toString value) ])
(List.range 1 20)
]
else
Html.text <| "Content for " ++ Debug.toString value
2020-08-05 05:30:24 +03:00
}
in
2020-08-05 07:28:01 +03:00
[ buildOption Flag UiIcon.flag
, buildOption Sprout UiIcon.sprout
, buildOption Star UiIcon.star
, buildOption Sapling UiIcon.sapling
, buildOption Attention <| Svg.withColor Colors.greenDark UiIcon.attention
, buildOption Tree UiIcon.tree
, buildOption Premium UiIcon.premiumLock
, buildOption Activity <| Svg.withColor Colors.purple UiIcon.activity
2020-07-29 21:10:49 +03:00
]
2020-08-05 23:20:48 +03:00
buildRadioOptions : Bool -> List (SegmentedControl.Radio Int msg)
buildRadioOptions keepIcon =
2020-08-05 05:06:28 +03:00
let
2020-08-05 07:28:01 +03:00
buildOption value icon =
{ icon = ifIcon icon
2020-08-20 23:17:45 +03:00
, label = Html.text ("Source " ++ Debug.toString (value + 1))
2020-08-05 07:28:01 +03:00
, value = value
, idString = String.fromInt value
2020-08-05 04:17:24 +03:00
, attributes = []
}
2020-08-05 07:28:01 +03:00
ifIcon icon =
if keepIcon then
Just icon
else
Nothing
in
2020-08-05 07:28:01 +03:00
List.indexedMap buildOption
[ UiIcon.leaderboard
, UiIcon.person
, UiIcon.performance
, UiIcon.gift
, UiIcon.document
, UiIcon.key
, UiIcon.badge
, UiIcon.hat
]
{-| -}
type alias State =
2020-08-05 05:30:24 +03:00
{ page : Page
, optionallySelected : Maybe Int
, optionsControl : Control Options
}
2018-03-24 05:05:34 +03:00
{-| -}
2019-10-24 21:08:28 +03:00
init : State
init =
2020-08-05 05:30:24 +03:00
{ page = Flag
, optionallySelected = Nothing
, optionsControl = optionsControl
}
type alias Options =
2020-08-20 23:58:31 +03:00
{ positioning : SegmentedControl.Positioning
, icon : Bool
2020-07-29 21:10:49 +03:00
, count : Int
2020-08-05 07:35:10 +03:00
, longContent : Bool
2018-03-24 05:05:34 +03:00
}
optionsControl : Control Options
optionsControl =
Control.record Options
2020-08-20 23:58:31 +03:00
|> Control.field "positioning"
(Control.choice
2020-08-20 23:58:31 +03:00
[ ( "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)
2020-07-29 21:10:49 +03:00
|> Control.field "count"
(Control.choice
(List.map (\i -> ( String.fromInt i, Control.value i )) (List.range 2 8))
)
2020-08-05 07:35:10 +03:00
|> Control.field "long content" (Control.bool False)
{-| -}
type Msg
2020-08-06 01:19:09 +03:00
= Focus String
| Focused (Result Dom.Error ())
| SelectPage Page
2020-08-06 01:25:26 +03:00
| SelectRadio Int
| ChangeOptions (Control Options)
2018-03-24 05:05:34 +03:00
{-| -}
update : Msg -> State -> ( State, Cmd Msg )
update msg state =
case msg of
2020-08-06 01:19:09 +03:00
Focus id ->
( state
, Task.attempt Focused (Dom.focus id)
)
Focused _ ->
( state
, Cmd.none
)
2020-08-05 05:30:24 +03:00
SelectPage page ->
( { state | page = page }
2020-05-20 21:58:21 +03:00
, Cmd.none
)
2020-05-20 22:23:13 +03:00
2020-08-06 01:25:26 +03:00
SelectRadio id ->
2020-05-20 21:58:21 +03:00
( { state | optionallySelected = Just id }
, Cmd.none
)
ChangeOptions newOptions ->
( { state | optionsControl = newOptions }
, Cmd.none
)