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

419 lines
13 KiB
Elm
Raw Normal View History

2020-07-30 21:12:30 +03:00
module Examples.RadioButton exposing
( example
, State, Msg
)
{-|
@docs example
@docs State, Msg
-}
2021-12-02 21:12:17 +03:00
import Accessibility.Styled.Key as Key
2021-11-09 23:40:10 +03:00
import Browser.Dom as Dom
2020-07-30 21:12:30 +03:00
import Category exposing (Category(..))
import CommonControls exposing (premiumLevel)
2021-11-23 00:43:56 +03:00
import Css
import Debug.Control as Control exposing (Control)
2021-11-22 21:31:17 +03:00
import Debug.Control.Extra as ControlExtra
2020-07-30 21:12:30 +03:00
import Example exposing (Example)
import Html.Styled as Html exposing (..)
2021-11-19 20:01:42 +03:00
import Html.Styled.Attributes as Attributes exposing (css)
2020-07-30 21:12:30 +03:00
import KeyboardSupport exposing (Direction(..), Key(..))
2020-07-30 21:39:16 +03:00
import Nri.Ui.Button.V10 as Button
2021-12-01 21:40:34 +03:00
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Data.PremiumLevel as PremiumLevel exposing (PremiumLevel)
2020-07-30 21:12:30 +03:00
import Nri.Ui.Heading.V2 as Heading
2021-11-09 23:40:10 +03:00
import Nri.Ui.Modal.V11 as Modal
2021-11-16 22:05:59 +03:00
import Nri.Ui.RadioButton.V3 as RadioButton
2021-10-27 20:42:23 +03:00
import Nri.Ui.Text.V6 as Text
2021-11-09 23:40:10 +03:00
import Task
2020-07-30 21:12:30 +03:00
{-| -}
example : Example State Msg
example =
2020-09-09 21:43:10 +03:00
{ name = "RadioButton"
2021-11-16 22:05:59 +03:00
, version = 3
2020-07-30 21:12:30 +03:00
, state = init
, update = update
2020-07-30 21:39:16 +03:00
, subscriptions = subscriptions
2021-12-02 21:12:17 +03:00
, preview = preview
2020-07-30 21:12:30 +03:00
, view = view
2021-09-04 18:47:56 +03:00
, categories = [ Inputs ]
2020-07-30 21:47:32 +03:00
, keyboardSupport =
2020-11-20 21:42:26 +03:00
[ { keys = [ Arrow Left ]
2020-11-07 02:57:10 +03:00
, result = "Move the focus & select the radio button to the left"
}
2020-11-20 21:42:26 +03:00
, { keys = [ Arrow Right ]
2020-11-07 02:57:10 +03:00
, result = "Move the focus & select the radio button to the right"
}
2020-11-20 21:42:26 +03:00
, { keys = [ Space ]
2020-11-07 02:57:10 +03:00
, result = "Select the current radio button"
}
]
2020-07-30 21:12:30 +03:00
}
2021-12-02 21:12:17 +03:00
preview : List (Html Never)
preview =
let
selectedValue =
Just "Selected"
in
[ RadioButton.view
{ label = "Unselected"
, name = "preview-radio-inputs"
, value = "Unselected"
, selectedValue = selectedValue
, valueToString = identity
}
[ RadioButton.custom [ Key.tabbable False ] ]
, RadioButton.view
{ label = "Selected"
, name = "preview-radio-inputs"
, value = "Selected"
, selectedValue = selectedValue
, valueToString = identity
}
[ RadioButton.custom [ Key.tabbable False ] ]
2021-12-02 21:13:49 +03:00
, RadioButton.view
{ label = "Premium"
, name = "preview-radio-inputs"
, value = "Premium"
, selectedValue = selectedValue
, valueToString = identity
}
[ RadioButton.custom [ Key.tabbable False ]
, RadioButton.premium
{ teacherPremiumLevel = PremiumLevel.Free
, contentPremiumLevel = PremiumLevel.PremiumWithWriting
}
]
2021-12-02 21:12:17 +03:00
]
2020-07-30 21:12:30 +03:00
{-| -}
view : State -> List (Html Msg)
2021-11-22 21:31:17 +03:00
view state =
let
selectionSettings =
Control.currentValue state.selectionSettings
in
2021-11-23 00:43:56 +03:00
[ div
2021-11-23 03:30:43 +03:00
[ css [ Css.displayFlex, Css.justifyContent Css.spaceBetween ] ]
2021-11-23 00:43:56 +03:00
[ Control.view SetSelectionSettings state.selectionSettings |> fromUnstyled
2021-11-23 03:30:43 +03:00
, viewExamples selectionSettings state.selectedValue
2021-11-23 00:43:56 +03:00
, viewExamplesCode selectionSettings state.selectedValue
2021-11-22 21:31:17 +03:00
]
2021-11-09 23:40:10 +03:00
, Modal.view
{ title = "Go Premium!"
2020-07-30 21:39:16 +03:00
, wrapMsg = ModalMsg
2021-11-22 21:06:38 +03:00
, content = [ Text.mediumBody [ Text.plaintext "Often, we'll launch a modal showing the benefits of premium when a Premium pennant is clicked." ] ]
2021-11-09 23:40:10 +03:00
, footer =
[ Button.button "Okay"
[ Button.modal
, Button.onClick CloseModal
, Button.id "close-premium-modal"
]
]
, focusTrap =
{ focus = Focus
, firstId = Modal.closeButtonId
, lastId = "close-premium-modal"
}
2020-07-30 21:39:16 +03:00
}
2021-11-09 23:40:10 +03:00
[ Modal.closeButton ]
2021-11-22 21:31:17 +03:00
state.modal
2020-07-30 21:12:30 +03:00
]
2021-11-23 00:43:56 +03:00
viewExamplesCode : SelectionSettings -> Maybe Selection -> Html Msg
viewExamplesCode selectionSettings selectedValue =
let
selectedValueString =
case selectedValue of
Just value ->
"Just " ++ selectionToString value
Nothing ->
"Nothing"
2021-11-23 00:43:56 +03:00
toExampleCode ( kind, settings ) =
"RadioButton.view"
++ ("\n\t{ label = " ++ selectionToString kind)
++ "\n\t, name = \"pets\""
++ ("\n\t, value = " ++ selectionToString kind)
++ ("\n\t, selectedValue = " ++ selectedValueString)
++ "\n\t, valueToString = toString"
++ "\n\t}\n\t[ "
2021-11-23 00:43:56 +03:00
++ String.join "\n\t, " (List.map Tuple.first settings)
++ "\n\t] "
in
Html.code
[ css
[ Css.display Css.block
, Css.marginLeft (Css.px 20)
]
]
[ Html.pre []
[ text
(" " ++ String.join "\n, " (List.map toExampleCode (examples selectionSettings)))
]
]
2021-11-23 00:30:46 +03:00
viewExamples : SelectionSettings -> Maybe Selection -> Html Msg
viewExamples selectionSettings selectedValue =
let
viewExample_ ( kind, settings ) =
RadioButton.view
{ label = selectionToString kind
, name = "pets"
, value = kind
, selectedValue = selectedValue
, valueToString = selectionToString
}
(RadioButton.onSelect Select :: List.map Tuple.second settings)
2021-11-23 00:30:46 +03:00
in
2021-11-23 03:30:43 +03:00
div [ css [ Css.flexBasis (Css.px 300) ] ]
2021-11-23 00:43:56 +03:00
(List.map viewExample_ (examples selectionSettings))
2021-11-23 00:43:56 +03:00
examples :
SelectionSettings
-> List ( Selection, List ( String, RadioButton.Attribute Selection Msg ) )
examples selectionSettings =
[ ( Dogs, selectionSettings.dogs )
, ( Cats, selectionSettings.cats )
]
2021-11-19 02:14:44 +03:00
type Selection
= Dogs
| Cats
selectionToString : Selection -> String
selectionToString selection =
case selection of
Dogs ->
"Dogs"
Cats ->
"Cats"
{-| -}
type alias State =
2021-11-19 02:14:44 +03:00
{ selectedValue : Maybe Selection
2020-07-30 21:39:16 +03:00
, modal : Modal.Model
2021-11-22 21:31:17 +03:00
, selectionSettings : Control SelectionSettings
}
2020-07-30 21:12:30 +03:00
{-| -}
init : State
init =
{ selectedValue = Nothing
2020-07-30 21:39:16 +03:00
, modal = Modal.init
2021-11-22 21:31:17 +03:00
, selectionSettings = initSelectionSettings
}
2020-07-30 21:12:30 +03:00
2021-11-22 21:31:17 +03:00
type alias SelectionSettings =
{ dogs : List ( String, RadioButton.Attribute Selection Msg )
, cats : List ( String, RadioButton.Attribute Selection Msg )
}
2021-11-22 21:31:17 +03:00
initSelectionSettings : Control SelectionSettings
initSelectionSettings =
Control.record SelectionSettings
|> Control.field "Dogs" controlAttributes
|> Control.field "Cats" controlAttributes
controlAttributes : Control (List ( String, RadioButton.Attribute Selection Msg ))
controlAttributes =
ControlExtra.list
|> ControlExtra.optionalListItem "visibility" labelVisibility
|> ControlExtra.optionalListItem "status" disabledOrEnabled
2021-11-22 21:47:58 +03:00
|> ControlExtra.optionalListItem "showPennant" showPennant
|> ControlExtra.optionalListItem "premium"
-- TODO: allow the teacher premium level to vary as well:
(Control.map
(\( contentLevel, clevel ) ->
2021-11-23 00:51:56 +03:00
( "RadioButton.premium { teacherPremiumLevel = PremiumLevel.Premium, contentPremiumLevel = "
++ contentLevel
++ "}"
, RadioButton.premium
{ teacherPremiumLevel = PremiumLevel.Premium
, contentPremiumLevel = clevel
}
)
)
premiumLevel
)
2021-11-22 22:19:10 +03:00
|> ControlExtra.optionalListItem "containerCss"
(Control.choice
[ ( "100% width"
, Control.value
( "RadioButton.containerCss [ Css.width (Css.pct 100) ]"
, RadioButton.containerCss [ Css.width (Css.pct 100) ]
)
)
2021-11-23 00:11:56 +03:00
, ( "10px right margin"
, Control.value
( "RadioButton.containerCss [ Css.marginRight (Css.px 10) ]"
, RadioButton.containerCss [ Css.marginRight (Css.px 10) ]
)
2021-12-01 21:40:34 +03:00
)
]
)
|> ControlExtra.optionalListItem "labelCss"
(Control.choice
[ ( "backgroundColor highlightMagenta"
, Control.value
( "RadioButton.labelCss [ Css.backgroundColor Colors.highlightMagenta ]"
, RadioButton.labelCss [ Css.backgroundColor Colors.highlightMagenta ]
)
)
, ( "1px ochreDark border"
, Control.value
( "RadioButton.labelCss [ Css.border3 (Css.px 1) Css.solid Colors.ochreDark ]"
, RadioButton.labelCss [ Css.border3 (Css.px 1) Css.solid Colors.ochreDark ]
)
2021-11-23 00:11:56 +03:00
)
2021-11-22 22:19:10 +03:00
]
)
|> ControlExtra.optionalListItem "disclosure" controlDisclosure
|> ControlExtra.optionalListItem "errorIf"
(Control.map
(\inError ->
( "RadioButton.errorIf " ++ Debug.toString inError
, RadioButton.errorIf inError
)
)
<|
Control.bool True
)
|> ControlExtra.optionalListItem "errorMessage"
(Control.map
(\message ->
( "RadioButton.errorMessage (Just \"" ++ message ++ "\")"
, RadioButton.errorMessage (Just message)
)
)
<|
Control.string "The statement must be true."
)
|> ControlExtra.optionalListItem "guidance"
(Control.map
(\content ->
( "RadioButton.guidance \"" ++ content ++ "\""
, RadioButton.guidance content
)
)
<|
Control.string "The statement must be true."
)
2021-11-22 21:36:22 +03:00
2021-11-22 22:08:40 +03:00
labelVisibility : Control ( String, RadioButton.Attribute Selection Msg )
labelVisibility =
Control.choice
[ ( "hiddenLabel", Control.value ( "RadioButton.hiddenLabel", RadioButton.hiddenLabel ) )
, ( "visibleLabel", Control.value ( "RadioButton.visibleLabel", RadioButton.visibleLabel ) )
]
2021-11-22 22:08:40 +03:00
2021-11-22 21:36:22 +03:00
disabledOrEnabled : Control ( String, RadioButton.Attribute Selection Msg )
disabledOrEnabled =
Control.choice
[ ( "disabled", Control.value ( "RadioButton.disabled", RadioButton.disabled ) )
, ( "enabled", Control.value ( "RadioButton.enabled", RadioButton.enabled ) )
]
2021-11-22 21:47:58 +03:00
showPennant : Control ( String, RadioButton.Attribute Selection Msg )
showPennant =
Control.value
( "RadioButton.showPennant OpenPremiumModal"
, RadioButton.showPennant (OpenModal "dogs")
)
2021-11-23 00:10:15 +03:00
controlDisclosure : Control ( String, RadioButton.Attribute Selection Msg )
controlDisclosure =
Control.map
(\content ->
( "RadioButton.disclosure [ Text.smallBody [ Text.plaintext \""
++ content
++ "\" ]"
, RadioButton.disclosure [ Text.smallBody [ Text.plaintext content ] ]
)
)
(Control.string "These pets occupy themselves.")
type Msg
2021-11-09 23:40:10 +03:00
= OpenModal String
| ModalMsg Modal.Msg
| CloseModal
2021-11-19 02:14:44 +03:00
| Select Selection
2021-11-22 21:31:17 +03:00
| SetSelectionSettings (Control SelectionSettings)
2021-11-09 23:40:10 +03:00
| Focus String
| Focused (Result Dom.Error ())
2020-07-30 21:12:30 +03:00
{-| -}
update : Msg -> State -> ( State, Cmd Msg )
update msg model =
case msg of
2021-11-09 23:40:10 +03:00
OpenModal returnFocusTo ->
let
( modal, cmd ) =
Modal.open
{ startFocusOn = Modal.closeButtonId
, returnFocusTo = returnFocusTo
}
in
( { model | modal = modal }, Cmd.map ModalMsg cmd )
2020-07-30 21:39:16 +03:00
ModalMsg modalMsg ->
let
( modal, cmd ) =
Modal.update { dismissOnEscAndOverlayClick = True }
modalMsg
model.modal
in
( { model | modal = modal }, Cmd.map ModalMsg cmd )
2021-11-09 23:40:10 +03:00
CloseModal ->
let
( modal, cmd ) =
Modal.close model.modal
in
( { model | modal = modal }, Cmd.map ModalMsg cmd )
Select value ->
( { model | selectedValue = Just value }, Cmd.none )
2021-11-22 21:31:17 +03:00
SetSelectionSettings selectionSettings ->
( { model | selectionSettings = selectionSettings }
, Cmd.none
)
2021-11-09 23:40:10 +03:00
Focus focus ->
( model, Task.attempt Focused (Dom.focus focus) )
Focused _ ->
( model, Cmd.none )
2020-07-30 21:39:16 +03:00
subscriptions : State -> Sub Msg
subscriptions { modal } =
Sub.map ModalMsg (Modal.subscriptions modal)