mirror of
https://github.com/NoRedInk/noredink-ui.git
synced 2024-12-18 19:21:29 +03:00
commit
e72a635126
@ -7,6 +7,7 @@ Nri.Ui.RadioButton.V2,upgrade to V4
|
||||
Nri.Ui.RadioButton.V3,upgrade to V4
|
||||
Nri.Ui.SideNav.V1,upgrade to V3
|
||||
Nri.Ui.SideNav.V2,upgrade to V3
|
||||
Nri.Ui.Switch.V1,upgrade to V2
|
||||
Nri.Ui.Table.V4,upgrade to V5
|
||||
Nri.Ui.Tabs.V6,upgrade to V7
|
||||
Nri.Ui.Tooltip.V1,upgrade to V2
|
||||
|
|
1
elm.json
1
elm.json
@ -61,6 +61,7 @@
|
||||
"Nri.Ui.Sprite.V1",
|
||||
"Nri.Ui.Svg.V1",
|
||||
"Nri.Ui.Switch.V1",
|
||||
"Nri.Ui.Switch.V2",
|
||||
"Nri.Ui.Table.V4",
|
||||
"Nri.Ui.Table.V5",
|
||||
"Nri.Ui.Tabs.V6",
|
||||
|
@ -114,6 +114,9 @@ hint = 'upgrade to V3'
|
||||
[forbidden."Nri.Ui.SideNav.V2"]
|
||||
hint = 'upgrade to V3'
|
||||
|
||||
[forbidden."Nri.Ui.Switch.V1"]
|
||||
hint = 'upgrade to V2'
|
||||
|
||||
[forbidden."Nri.Ui.Table.V4"]
|
||||
hint = 'upgrade to V5'
|
||||
|
||||
|
@ -73,7 +73,6 @@ describe('UI tests', function () {
|
||||
// Loading's color contrast check seems to change behavior depending on whether Percy snapshots are taken or not
|
||||
'Loading': ['color-contrast'],
|
||||
'RadioButton': ['duplicate-id'],
|
||||
'Switch': ['aria-allowed-attr'],
|
||||
}
|
||||
|
||||
const specialProcessing = {
|
||||
|
@ -1,6 +1,7 @@
|
||||
module Nri.Ui.Colors.Extra exposing
|
||||
( toCssColor, fromCssColor
|
||||
, withAlpha
|
||||
, toCssString
|
||||
)
|
||||
|
||||
{-| Helpers for working with colors.
|
||||
@ -10,6 +11,7 @@ module Nri.Ui.Colors.Extra exposing
|
||||
|
||||
@docs toCssColor, fromCssColor
|
||||
@docs withAlpha
|
||||
@docs toCssString
|
||||
|
||||
-}
|
||||
|
||||
@ -44,3 +46,9 @@ withAlpha 0.5 grassland -- "{ value = "rgba(86, 191, 116, 0.5)", color = Compati
|
||||
withAlpha : Float -> Css.Color -> Css.Color
|
||||
withAlpha alpha { red, green, blue } =
|
||||
Css.rgba red green blue alpha
|
||||
|
||||
|
||||
{-| -}
|
||||
toCssString : Css.Color -> String
|
||||
toCssString =
|
||||
SolidColor.toRGBString << fromCssColor
|
||||
|
@ -21,11 +21,10 @@ import Css exposing (..)
|
||||
import Html.Styled as Html exposing (Html)
|
||||
import Html.Styled.Attributes exposing (css)
|
||||
import Html.Styled.Events
|
||||
import Nri.Ui.Colors.Extra
|
||||
import Nri.Ui.Colors.Extra exposing (toCssString)
|
||||
import Nri.Ui.Colors.V1
|
||||
import Nri.Ui.CssVendorPrefix.V1 as CssVendorPrefix
|
||||
import Nri.Ui.Table.V5
|
||||
import SolidColor
|
||||
import Svg.Styled as Svg
|
||||
import Svg.Styled.Attributes as SvgAttributes
|
||||
|
||||
@ -363,8 +362,3 @@ sortArrow direction active =
|
||||
[ Svg.polygon [ SvgAttributes.points "0 6 4 0 8 6 0 6" ] []
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
toCssString : Css.Color -> String
|
||||
toCssString =
|
||||
SolidColor.toRGBString << Nri.Ui.Colors.Extra.fromCssColor
|
||||
|
381
src/Nri/Ui/Switch/V2.elm
Normal file
381
src/Nri/Ui/Switch/V2.elm
Normal file
@ -0,0 +1,381 @@
|
||||
module Nri.Ui.Switch.V2 exposing
|
||||
( view
|
||||
, Attribute
|
||||
, selected
|
||||
, containerCss, labelCss, custom, nriDescription, testId
|
||||
, onSwitch, disabled
|
||||
)
|
||||
|
||||
{-|
|
||||
|
||||
|
||||
# Changes from V1:
|
||||
|
||||
- Fixes invalid ARIA use, [conformance requirements](https://www.w3.org/TR/html-aria/#docconformance)
|
||||
- labels should only support strings (this is the only way they're actually used in practice)
|
||||
- extends API to be more consistent with other form/control components
|
||||
- Use Colors values instead of hardcoded hex strings
|
||||
- Move the status (selected or not selected) to the list api
|
||||
- REQUIRE label and id always
|
||||
- Move custom attributes to the container
|
||||
- change disabled to take a bool (which I think is the slighty more common pattern)
|
||||
|
||||
@docs view
|
||||
|
||||
|
||||
### Attributes
|
||||
|
||||
@docs Attribute
|
||||
@docs selected
|
||||
@docs containerCss, labelCss, custom, nriDescription, testId
|
||||
@docs onSwitch, disabled
|
||||
|
||||
-}
|
||||
|
||||
import Accessibility.Styled as Html exposing (Html)
|
||||
import Accessibility.Styled.Widget as Widget
|
||||
import Css exposing (Color, Style)
|
||||
import Css.Global as Global
|
||||
import Css.Media
|
||||
import Html.Styled.Attributes as Attributes
|
||||
import Html.Styled.Events as Events
|
||||
import Nri.Ui.Colors.Extra exposing (toCssString)
|
||||
import Nri.Ui.Colors.V1 as Colors
|
||||
import Nri.Ui.Fonts.V1 as Fonts
|
||||
import Nri.Ui.Html.Attributes.V2 as Extra
|
||||
import Nri.Ui.Svg.V1 exposing (Svg)
|
||||
import Svg.Styled as Svg
|
||||
import Svg.Styled.Attributes as SvgAttributes
|
||||
|
||||
|
||||
{-| -}
|
||||
type Attribute msg
|
||||
= Attribute (Config msg -> Config msg)
|
||||
|
||||
|
||||
{-| What is the status of the Switch, selected or not?
|
||||
-}
|
||||
selected : Bool -> Attribute msg
|
||||
selected isSelected =
|
||||
Attribute <| \config -> { config | isSelected = isSelected }
|
||||
|
||||
|
||||
{-| Specify what happens when the switch is toggled.
|
||||
-}
|
||||
onSwitch : (Bool -> msg) -> Attribute msg
|
||||
onSwitch onSwitch_ =
|
||||
Attribute <| \config -> { config | onSwitch = Just onSwitch_ }
|
||||
|
||||
|
||||
{-| Explicitly specify that you want this switch to be disabled. If you don't
|
||||
specify `onSwitch`, this is the default, but it's provided so you don't have
|
||||
to resort to `filterMap` or similar to build a clean list of attributes.
|
||||
-}
|
||||
disabled : Bool -> Attribute msg
|
||||
disabled isDisabled =
|
||||
Attribute <| \config -> { config | isDisabled = isDisabled }
|
||||
|
||||
|
||||
{-| Pass custom attributes through to be attached to the underlying input.
|
||||
|
||||
Do NOT use this helper to add css styles, as they may not be applied the way
|
||||
you want/expect if underlying styles change.
|
||||
Instead, please use `containerCss` or `labelCss`.
|
||||
|
||||
-}
|
||||
custom : List (Html.Attribute Never) -> Attribute msg
|
||||
custom custom_ =
|
||||
Attribute <| \config -> { config | custom = config.custom ++ custom_ }
|
||||
|
||||
|
||||
{-| -}
|
||||
nriDescription : String -> Attribute msg
|
||||
nriDescription description =
|
||||
custom [ Extra.nriDescription description ]
|
||||
|
||||
|
||||
{-| -}
|
||||
testId : String -> Attribute msg
|
||||
testId id_ =
|
||||
custom [ Extra.testId id_ ]
|
||||
|
||||
|
||||
{-| Adds CSS to the Switch container.
|
||||
-}
|
||||
containerCss : List Css.Style -> Attribute msg
|
||||
containerCss styles =
|
||||
Attribute <| \config -> { config | containerCss = config.containerCss ++ styles }
|
||||
|
||||
|
||||
{-| Adds CSS to the element containing the label text.
|
||||
|
||||
Note that these styles don't apply to the literal HTML label element, since it contains the icon SVG as well.
|
||||
|
||||
-}
|
||||
labelCss : List Css.Style -> Attribute msg
|
||||
labelCss styles =
|
||||
Attribute <| \config -> { config | labelCss = config.labelCss ++ styles }
|
||||
|
||||
|
||||
type alias Config msg =
|
||||
{ onSwitch : Maybe (Bool -> msg)
|
||||
, containerCss : List Style
|
||||
, labelCss : List Style
|
||||
, isDisabled : Bool
|
||||
, isSelected : Bool
|
||||
, custom : List (Html.Attribute Never)
|
||||
}
|
||||
|
||||
|
||||
defaultConfig : Config msg
|
||||
defaultConfig =
|
||||
{ onSwitch = Nothing
|
||||
, containerCss = []
|
||||
, labelCss = []
|
||||
, isDisabled = False
|
||||
, isSelected = False
|
||||
, custom = []
|
||||
}
|
||||
|
||||
|
||||
{-| Render a switch. The boolean here indicates whether the switch is on
|
||||
or not.
|
||||
-}
|
||||
view : { label : String, id : String } -> List (Attribute msg) -> Html msg
|
||||
view { label, id } attrs =
|
||||
let
|
||||
config =
|
||||
List.foldl (\(Attribute update) -> update) defaultConfig attrs
|
||||
|
||||
notOperable =
|
||||
config.onSwitch == Nothing || config.isDisabled
|
||||
in
|
||||
Html.label
|
||||
([ Attributes.id (id ++ "-container")
|
||||
, Attributes.css
|
||||
[ Css.display Css.inlineFlex
|
||||
, Css.alignItems Css.center
|
||||
, Css.position Css.relative
|
||||
, Css.pseudoClass "focus-within"
|
||||
[ Global.descendants
|
||||
[ Global.class "switch-slider"
|
||||
[ stroke Colors.azure
|
||||
, Css.property "stroke-width" "3px"
|
||||
]
|
||||
]
|
||||
]
|
||||
, Css.cursor
|
||||
(if notOperable then
|
||||
Css.notAllowed
|
||||
|
||||
else
|
||||
Css.pointer
|
||||
)
|
||||
, Css.batch config.containerCss
|
||||
]
|
||||
, Attributes.for id
|
||||
]
|
||||
++ List.map (Attributes.map never) config.custom
|
||||
)
|
||||
[ viewCheckbox
|
||||
{ id = id
|
||||
, onCheck = config.onSwitch
|
||||
, isDisabled = config.isDisabled
|
||||
, selected = config.isSelected
|
||||
}
|
||||
, Nri.Ui.Svg.V1.toHtml
|
||||
(viewSwitch
|
||||
{ id = id
|
||||
, isSelected = config.isSelected
|
||||
, isDisabled = notOperable
|
||||
}
|
||||
)
|
||||
, Html.span
|
||||
[ Attributes.css
|
||||
[ Css.fontWeight (Css.int 600)
|
||||
, Css.color Colors.navy
|
||||
, Css.paddingLeft (Css.px 5)
|
||||
, Fonts.baseFont
|
||||
, Css.batch config.labelCss
|
||||
]
|
||||
]
|
||||
[ Html.text label ]
|
||||
]
|
||||
|
||||
|
||||
viewCheckbox :
|
||||
{ id : String
|
||||
, onCheck : Maybe (Bool -> msg)
|
||||
, selected : Bool
|
||||
, isDisabled : Bool
|
||||
}
|
||||
-> Html msg
|
||||
viewCheckbox config =
|
||||
Html.checkbox config.id
|
||||
(Just config.selected)
|
||||
[ Attributes.id config.id
|
||||
, Attributes.css
|
||||
[ Css.position Css.absolute
|
||||
, Css.top (Css.px 10)
|
||||
, Css.left (Css.px 10)
|
||||
, Css.zIndex (Css.int 0)
|
||||
, Css.opacity (Css.num 0)
|
||||
]
|
||||
, case ( config.onCheck, config.isDisabled ) of
|
||||
( Just onCheck, False ) ->
|
||||
Events.onCheck onCheck
|
||||
|
||||
_ ->
|
||||
Widget.disabled True
|
||||
]
|
||||
|
||||
|
||||
viewSwitch :
|
||||
{ id : String
|
||||
, isSelected : Bool
|
||||
, isDisabled : Bool
|
||||
}
|
||||
-> Svg
|
||||
viewSwitch config =
|
||||
let
|
||||
shadowFilterId =
|
||||
config.id ++ "-shadow-filter"
|
||||
|
||||
shadowBoxId =
|
||||
config.id ++ "-shadow-box"
|
||||
in
|
||||
Svg.svg
|
||||
[ SvgAttributes.width "43"
|
||||
, SvgAttributes.height "32"
|
||||
, SvgAttributes.viewBox "0 0 43 32"
|
||||
, SvgAttributes.css
|
||||
[ Css.zIndex (Css.int 1)
|
||||
, if config.isDisabled then
|
||||
Css.opacity (Css.num 0.4)
|
||||
|
||||
else
|
||||
Css.opacity (Css.num 1)
|
||||
]
|
||||
]
|
||||
[ Svg.defs []
|
||||
[ Svg.filter
|
||||
[ SvgAttributes.id shadowFilterId
|
||||
, SvgAttributes.width "105%"
|
||||
, SvgAttributes.height "106.7%"
|
||||
, SvgAttributes.x "-2.5%"
|
||||
, SvgAttributes.y "-3.3%"
|
||||
, SvgAttributes.filterUnits "objectBoundingBox"
|
||||
]
|
||||
[ Svg.feOffset
|
||||
[ SvgAttributes.dy "2"
|
||||
, SvgAttributes.in_ "SourceAlpha"
|
||||
, SvgAttributes.result "shadowOffsetInner1"
|
||||
]
|
||||
[]
|
||||
, Svg.feComposite
|
||||
[ SvgAttributes.in_ "shadowOffsetInner1"
|
||||
, SvgAttributes.in2 "SourceAlpha"
|
||||
, SvgAttributes.k2 "-1"
|
||||
, SvgAttributes.k3 "1"
|
||||
, SvgAttributes.operator "arithmetic"
|
||||
, SvgAttributes.result "shadowInnerInner1"
|
||||
]
|
||||
[]
|
||||
, Svg.feColorMatrix
|
||||
[ SvgAttributes.in_ "shadowInnerInner1"
|
||||
, SvgAttributes.values "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
|
||||
]
|
||||
[]
|
||||
]
|
||||
, Svg.rect
|
||||
[ SvgAttributes.id shadowBoxId
|
||||
, SvgAttributes.width "40"
|
||||
, SvgAttributes.height "30"
|
||||
, SvgAttributes.x "0"
|
||||
, SvgAttributes.y "0"
|
||||
, SvgAttributes.rx "15"
|
||||
]
|
||||
[]
|
||||
]
|
||||
, Svg.g
|
||||
[ SvgAttributes.fill "none"
|
||||
, SvgAttributes.fillRule "even-odd"
|
||||
, SvgAttributes.transform "translate(1, 1)"
|
||||
]
|
||||
[ Svg.g []
|
||||
[ Svg.use
|
||||
[ SvgAttributes.xlinkHref ("#" ++ shadowBoxId)
|
||||
, SvgAttributes.css
|
||||
[ if config.isSelected then
|
||||
Css.fill Colors.glacier
|
||||
|
||||
else
|
||||
Css.fill Colors.gray92
|
||||
, transition "fill 0.2s"
|
||||
]
|
||||
]
|
||||
[]
|
||||
, Svg.use
|
||||
[ SvgAttributes.xlinkHref ("#" ++ shadowBoxId)
|
||||
, SvgAttributes.fill "#000"
|
||||
, SvgAttributes.filter ("url(#" ++ shadowFilterId ++ ")")
|
||||
]
|
||||
[]
|
||||
]
|
||||
, Svg.g
|
||||
[ SvgAttributes.css
|
||||
[ if config.isSelected then
|
||||
Css.transform (Css.translateX (Css.px 11))
|
||||
|
||||
else
|
||||
Css.transform (Css.translateX (Css.px 0))
|
||||
, transition "transform 0.2s ease-in-out"
|
||||
]
|
||||
]
|
||||
[ Svg.circle
|
||||
[ SvgAttributes.cx "15"
|
||||
, SvgAttributes.cy "15"
|
||||
, SvgAttributes.r "14.5"
|
||||
, SvgAttributes.fill "#FFF"
|
||||
, SvgAttributes.css
|
||||
[ if config.isSelected then
|
||||
stroke Colors.azure
|
||||
|
||||
else
|
||||
stroke Colors.gray75
|
||||
, transition "stroke 0.1s"
|
||||
]
|
||||
, SvgAttributes.class "switch-slider"
|
||||
]
|
||||
[]
|
||||
, Svg.path
|
||||
[ SvgAttributes.strokeLinecap "round"
|
||||
, SvgAttributes.strokeLinejoin "round"
|
||||
, SvgAttributes.strokeWidth "3"
|
||||
, SvgAttributes.d "M8 15.865L12.323 20 21.554 10"
|
||||
, SvgAttributes.css
|
||||
[ if config.isSelected then
|
||||
stroke Colors.azure
|
||||
|
||||
else
|
||||
stroke Colors.white
|
||||
, transition "stroke 0.2s"
|
||||
]
|
||||
]
|
||||
[]
|
||||
]
|
||||
]
|
||||
]
|
||||
|> Nri.Ui.Svg.V1.fromHtml
|
||||
|
||||
|
||||
stroke : Color -> Style
|
||||
stroke color =
|
||||
Css.property "stroke" (toCssString color)
|
||||
|
||||
|
||||
transition : String -> Css.Style
|
||||
transition transitionRules =
|
||||
Css.Media.withMediaQuery
|
||||
[ "(prefers-reduced-motion: no-preference)" ]
|
||||
[ Css.property "transition" transitionRules ]
|
@ -1,4 +1,4 @@
|
||||
module Debug.Control.View exposing (codeFromList, codeFromListWithIndentLevel, view)
|
||||
module Debug.Control.View exposing (codeFromList, codeFromListWithHardcoded, codeFromListWithIndentLevel, view)
|
||||
|
||||
import Css exposing (..)
|
||||
import Css.Media exposing (withMedia)
|
||||
@ -97,6 +97,13 @@ viewSection name children =
|
||||
)
|
||||
|
||||
|
||||
codeFromListWithHardcoded : List String -> List ( String, a ) -> String
|
||||
codeFromListWithHardcoded hardcodes elements =
|
||||
List.map (\v -> ( v, () )) hardcodes
|
||||
++ List.map (Tuple.mapSecond (always ())) elements
|
||||
|> codeFromList
|
||||
|
||||
|
||||
codeFromList : List ( String, a ) -> String
|
||||
codeFromList =
|
||||
codeFromListWithIndentLevel 1
|
||||
|
@ -8,71 +8,137 @@ module Examples.Switch exposing (Msg, State, example)
|
||||
|
||||
import Accessibility.Styled.Key as Key
|
||||
import Category
|
||||
import CommonControls
|
||||
import Debug.Control as Control exposing (Control)
|
||||
import Debug.Control.Extra as ControlExtra
|
||||
import Debug.Control.View as ControlView
|
||||
import Example exposing (Example)
|
||||
import Html.Styled as Html
|
||||
import Nri.Ui.Heading.V2 as Heading
|
||||
import Nri.Ui.Switch.V1 as Switch
|
||||
import KeyboardSupport exposing (Key(..))
|
||||
import Nri.Ui.Switch.V2 as Switch
|
||||
|
||||
|
||||
moduleName : String
|
||||
moduleName =
|
||||
"Switch"
|
||||
|
||||
|
||||
version : Int
|
||||
version =
|
||||
2
|
||||
|
||||
|
||||
example : Example State Msg
|
||||
example =
|
||||
{ name = moduleName
|
||||
, version = version
|
||||
, state = init
|
||||
, update = update
|
||||
, subscriptions = \_ -> Sub.none
|
||||
, preview =
|
||||
[ Switch.view { label = "Toggle Off", id = "preview-switch-a" }
|
||||
[ Switch.selected False
|
||||
, Switch.custom [ Key.tabbable False ]
|
||||
]
|
||||
, Switch.view { label = "Toggle On", id = "preview-switch-b" }
|
||||
[ Switch.selected True
|
||||
, Switch.custom [ Key.tabbable False ]
|
||||
]
|
||||
]
|
||||
, view =
|
||||
\ellieLinkConfig state ->
|
||||
let
|
||||
currentValue =
|
||||
Control.currentValue state.settings
|
||||
in
|
||||
[ ControlView.view
|
||||
{ ellieLinkConfig = ellieLinkConfig
|
||||
, name = moduleName
|
||||
, version = version
|
||||
, update = UpdateSettings
|
||||
, settings = state.settings
|
||||
, mainType = "RootHtml.Html msg"
|
||||
, extraImports = []
|
||||
, toExampleCode =
|
||||
\{ label, attributes } ->
|
||||
[ { sectionName = "Example"
|
||||
, code =
|
||||
moduleName
|
||||
++ ".view"
|
||||
++ " \""
|
||||
++ label
|
||||
++ "\"\t"
|
||||
++ ControlView.codeFromListWithHardcoded
|
||||
[ "Switch.selected "
|
||||
++ Debug.toString state.selected
|
||||
++ "\n-- , Switch.onSwitch Switch -- <- you'll need to wire in a Msg for the Switch to work"
|
||||
]
|
||||
attributes
|
||||
}
|
||||
]
|
||||
}
|
||||
, Switch.view { label = currentValue.label, id = "view-switch-example" }
|
||||
(Switch.selected state.selected
|
||||
:: Switch.onSwitch Switch
|
||||
:: List.map Tuple.second currentValue.attributes
|
||||
)
|
||||
]
|
||||
, categories = [ Category.Inputs ]
|
||||
, keyboardSupport =
|
||||
[ { keys = [ Space ]
|
||||
, result = "Toggle the Switch state"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
{-| -}
|
||||
type alias State =
|
||||
Bool
|
||||
{ selected : Bool
|
||||
, settings : Control Settings
|
||||
}
|
||||
|
||||
|
||||
init : State
|
||||
init =
|
||||
{ selected = True
|
||||
, settings = controlSettings
|
||||
}
|
||||
|
||||
|
||||
type alias Settings =
|
||||
{ label : String
|
||||
, attributes : List ( String, Switch.Attribute Msg )
|
||||
}
|
||||
|
||||
|
||||
controlSettings : Control Settings
|
||||
controlSettings =
|
||||
Control.record Settings
|
||||
|> Control.field "label" (Control.string "Show pandas in results")
|
||||
|> Control.field "attributes" initAttributes
|
||||
|
||||
|
||||
initAttributes : Control (List ( String, Switch.Attribute msg ))
|
||||
initAttributes =
|
||||
ControlExtra.list
|
||||
|> CommonControls.disabledListItem moduleName Switch.disabled
|
||||
|
||||
|
||||
{-| -}
|
||||
type Msg
|
||||
= Switch Bool
|
||||
| UpdateSettings (Control Settings)
|
||||
|
||||
|
||||
example : Example State Msg
|
||||
example =
|
||||
{ name = "Switch"
|
||||
, version = 1
|
||||
, state = True
|
||||
, update = \(Switch new) _ -> ( new, Cmd.none )
|
||||
, subscriptions = \_ -> Sub.none
|
||||
, preview =
|
||||
[ Switch.view
|
||||
[ Switch.label (Html.text "Toggle On")
|
||||
, Switch.custom [ Key.tabbable False ]
|
||||
]
|
||||
False
|
||||
, Switch.view
|
||||
[ Switch.label (Html.text "Toggle Off")
|
||||
, Switch.custom [ Key.tabbable False ]
|
||||
]
|
||||
True
|
||||
]
|
||||
, view =
|
||||
\ellieLinkConfig interactiveIsOn ->
|
||||
[ Heading.h2 [ Heading.style Heading.Subhead ] [ Html.text "Interactive" ]
|
||||
, Switch.view
|
||||
[ Switch.onSwitch Switch
|
||||
, Switch.id "switch-interactive"
|
||||
, Switch.label
|
||||
(if interactiveIsOn then
|
||||
Html.text "On"
|
||||
update : Msg -> State -> ( State, Cmd Msg )
|
||||
update msg state =
|
||||
case msg of
|
||||
Switch bool ->
|
||||
( { state | selected = bool }
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
else
|
||||
Html.text "Off"
|
||||
)
|
||||
]
|
||||
interactiveIsOn
|
||||
, Heading.h2 [ Heading.style Heading.Subhead ] [ Html.text "Disabled (On)" ]
|
||||
, Switch.view
|
||||
[ Switch.disabled
|
||||
, Switch.id "switch-disabled-on"
|
||||
, Switch.label (Html.text "Permanently on")
|
||||
]
|
||||
True
|
||||
, Heading.h2 [ Heading.style Heading.Subhead ] [ Html.text "Disabled (Off)" ]
|
||||
, Switch.view
|
||||
[ Switch.disabled
|
||||
, Switch.id "switch-disabled-off"
|
||||
, Switch.label (Html.text "Permanently off")
|
||||
]
|
||||
False
|
||||
]
|
||||
, categories = [ Category.Inputs ]
|
||||
, keyboardSupport = [{- TODO -}]
|
||||
}
|
||||
UpdateSettings settings ->
|
||||
( { state | settings = settings }
|
||||
, Cmd.none
|
||||
)
|
||||
|
@ -1,6 +1,5 @@
|
||||
module SwitchExampleSpec exposing (suite)
|
||||
|
||||
import Accessibility.Aria as Aria
|
||||
import ProgramTest exposing (..)
|
||||
import Routes exposing (Route)
|
||||
import Test exposing (..)
|
||||
@ -20,17 +19,11 @@ suite =
|
||||
\() ->
|
||||
app route
|
||||
|> ensureViewHas [ text "Nri.Ui.Switch" ]
|
||||
-- switch starts with aria-checked=true and text "On"
|
||||
|> ensureViewHas
|
||||
[ attribute (Aria.checked (Just True))
|
||||
, text "On"
|
||||
]
|
||||
-- switch starts with checked=true
|
||||
|> ensureViewHas [ checked True ]
|
||||
-- user can click the first switch
|
||||
|> check "switch-interactive" "On" False
|
||||
-- the switch now has aria-checked=false and text "Off"
|
||||
|> ensureViewHas
|
||||
[ attribute (Aria.checked (Just False))
|
||||
, text "Off"
|
||||
]
|
||||
|> check "view-switch-example" "Show pandas in results" False
|
||||
-- the switch now has checked=false
|
||||
|> ensureViewHas [ checked False ]
|
||||
|> done
|
||||
]
|
||||
|
@ -57,6 +57,7 @@
|
||||
"Nri.Ui.Sprite.V1",
|
||||
"Nri.Ui.Svg.V1",
|
||||
"Nri.Ui.Switch.V1",
|
||||
"Nri.Ui.Switch.V2",
|
||||
"Nri.Ui.Table.V4",
|
||||
"Nri.Ui.Table.V5",
|
||||
"Nri.Ui.Tabs.V6",
|
||||
|
Loading…
Reference in New Issue
Block a user