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
|
2018-03-30 19:03:16 +03:00
|
|
|
@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
|
2020-03-24 03:33:42 +03:00
|
|
|
import Category exposing (Category(..))
|
2020-08-05 04:08:16 +03:00
|
|
|
import Css
|
2019-06-05 02:01:20 +03:00
|
|
|
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)
|
2018-09-10 18:19:15 +03:00
|
|
|
import Html.Styled.Events as Events
|
2020-06-20 00:45:32 +03:00
|
|
|
import KeyboardSupport exposing (Direction(..), Key(..))
|
2019-10-24 21:29:27 +03:00
|
|
|
import Nri.Ui.Colors.V1 as Colors
|
2020-09-05 01:53:19 +03:00
|
|
|
import Nri.Ui.SegmentedControl.V13 as SegmentedControl
|
2019-10-24 23:23:52 +03:00
|
|
|
import Nri.Ui.Svg.V1 as Svg exposing (Svg)
|
2020-09-09 00:06:47 +03:00
|
|
|
import Nri.Ui.Tooltip.V2 as Tooltip
|
2019-10-24 21:08:28 +03:00
|
|
|
import Nri.Ui.UiIcon.V1 as UiIcon
|
2020-08-06 01:03:22 +03:00
|
|
|
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-09-05 01:53:19 +03:00
|
|
|
{ name = "Nri.Ui.SegmentedControl.V13"
|
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-09-09 00:35:36 +03:00
|
|
|
{ focusAndSelect = FocusAndSelectPage
|
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-09-09 00:06:47 +03:00
|
|
|
, options = List.take options.count (buildOptions options state.pageTooltip)
|
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)
|
2020-05-20 21:34:34 +03:00
|
|
|
, selected = state.optionallySelected
|
2020-08-20 23:58:31 +03:00
|
|
|
, positioning = options.positioning
|
2020-05-20 21:30:43 +03:00
|
|
|
}
|
2020-03-31 22:43:32 +03:00
|
|
|
]
|
2020-08-05 04:00:58 +03:00
|
|
|
, categories = [ Widgets, Layout ]
|
2020-06-20 00:16:10 +03:00
|
|
|
, atomicDesignType = Molecule
|
2020-08-05 03:58:29 +03:00
|
|
|
, 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"
|
|
|
|
}
|
2020-08-05 03:58:29 +03:00
|
|
|
]
|
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-09-09 00:06:47 +03:00
|
|
|
buildOptions : { options | icon : Bool, longContent : Bool, tooltips : Bool } -> Maybe Page -> List (SegmentedControl.Option Page Msg)
|
|
|
|
buildOptions { icon, longContent, tooltips } openTooltip =
|
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-09-09 00:06:47 +03:00
|
|
|
, tabTooltip =
|
|
|
|
if tooltips then
|
|
|
|
[ Tooltip.plaintext (Debug.toString value)
|
|
|
|
, Tooltip.onHover (PageTooltip value)
|
|
|
|
, Tooltip.open (openTooltip == Just value)
|
|
|
|
]
|
|
|
|
|
|
|
|
else
|
|
|
|
[]
|
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
|
2020-08-20 23:43:57 +03:00
|
|
|
, idString = String.fromInt value
|
2020-08-05 04:17:24 +03:00
|
|
|
, attributes = []
|
2019-10-24 22:29:21 +03:00
|
|
|
}
|
2020-08-05 07:28:01 +03:00
|
|
|
|
|
|
|
ifIcon icon =
|
|
|
|
if keepIcon then
|
|
|
|
Just icon
|
|
|
|
|
|
|
|
else
|
|
|
|
Nothing
|
2019-10-24 22:29:21 +03:00
|
|
|
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
|
|
|
|
]
|
2019-10-24 22:29:21 +03:00
|
|
|
|
|
|
|
|
|
|
|
{-| -}
|
|
|
|
type alias State =
|
2020-08-05 05:30:24 +03:00
|
|
|
{ page : Page
|
2020-09-09 00:06:47 +03:00
|
|
|
, pageTooltip : Maybe Page
|
2020-07-29 21:00:05 +03:00
|
|
|
, optionallySelected : Maybe Int
|
2019-10-24 22:29:21 +03:00
|
|
|
, 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
|
2020-09-09 00:06:47 +03:00
|
|
|
, pageTooltip = Nothing
|
2020-05-20 21:34:34 +03:00
|
|
|
, optionallySelected = Nothing
|
2019-10-24 22:29:21 +03:00
|
|
|
, optionsControl = optionsControl
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
type alias Options =
|
2020-08-20 23:58:31 +03:00
|
|
|
{ positioning : SegmentedControl.Positioning
|
2019-10-24 22:29:21 +03:00
|
|
|
, icon : Bool
|
2020-07-29 21:10:49 +03:00
|
|
|
, count : Int
|
2020-08-05 07:35:10 +03:00
|
|
|
, longContent : Bool
|
2020-09-09 00:06:47 +03:00
|
|
|
, tooltips : Bool
|
2018-03-24 05:05:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-10-24 22:29:21 +03:00
|
|
|
optionsControl : Control Options
|
|
|
|
optionsControl =
|
|
|
|
Control.record Options
|
2020-08-20 23:58:31 +03:00
|
|
|
|> Control.field "positioning"
|
2019-10-24 22:29:21 +03:00
|
|
|
(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 )
|
2019-10-24 22:29:21 +03:00
|
|
|
]
|
|
|
|
)
|
2020-08-05 07:36:15 +03:00
|
|
|
|> 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)
|
2020-09-09 00:35:36 +03:00
|
|
|
|> Control.field "tooltips" (Control.bool True)
|
2019-10-24 22:29:21 +03:00
|
|
|
|
|
|
|
|
|
|
|
{-| -}
|
|
|
|
type Msg
|
2020-09-09 00:35:36 +03:00
|
|
|
= FocusAndSelectPage { select : Page, focus : Maybe String }
|
2020-08-06 01:19:09 +03:00
|
|
|
| Focused (Result Dom.Error ())
|
2020-09-09 00:06:47 +03:00
|
|
|
| PageTooltip Page Bool
|
2020-08-06 01:25:26 +03:00
|
|
|
| SelectRadio Int
|
2019-10-24 22:29:21 +03:00
|
|
|
| ChangeOptions (Control Options)
|
2019-10-24 21:29:27 +03:00
|
|
|
|
|
|
|
|
2018-03-24 05:05:34 +03:00
|
|
|
{-| -}
|
|
|
|
update : Msg -> State -> ( State, Cmd Msg )
|
|
|
|
update msg state =
|
|
|
|
case msg of
|
2020-09-09 00:35:36 +03:00
|
|
|
FocusAndSelectPage { select, focus } ->
|
|
|
|
( { state | page = select }
|
|
|
|
, Maybe.map (Task.attempt Focused << Dom.focus) focus
|
|
|
|
|> Maybe.withDefault Cmd.none
|
2020-08-06 01:19:09 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
Focused _ ->
|
|
|
|
( state
|
|
|
|
, Cmd.none
|
|
|
|
)
|
|
|
|
|
2020-09-09 00:06:47 +03:00
|
|
|
PageTooltip page isOpen ->
|
|
|
|
( { state
|
|
|
|
| pageTooltip =
|
|
|
|
if isOpen then
|
|
|
|
Just page
|
|
|
|
|
|
|
|
else
|
|
|
|
Nothing
|
|
|
|
}
|
|
|
|
, Cmd.none
|
|
|
|
)
|
|
|
|
|
2020-08-06 01:25:26 +03:00
|
|
|
SelectRadio id ->
|
2020-05-20 21:58:21 +03:00
|
|
|
( { state | optionallySelected = Just id }
|
2018-09-10 18:19:15 +03:00
|
|
|
, Cmd.none
|
|
|
|
)
|
|
|
|
|
2019-06-05 02:01:20 +03:00
|
|
|
ChangeOptions newOptions ->
|
|
|
|
( { state | optionsControl = newOptions }
|
|
|
|
, Cmd.none
|
|
|
|
)
|