From 03c084597315b524183d4f1da3039560e14daec9 Mon Sep 17 00:00:00 2001 From: Aaron VonderHaar Date: Tue, 31 Mar 2020 13:04:36 -0700 Subject: [PATCH 1/5] Update TextInput example to use Debug.Control --- src/Nri/Ui/TextInput/V5.elm | 6 +- styleguide-app/Examples/TextInput.elm | 149 ++++++++++---------------- 2 files changed, 61 insertions(+), 94 deletions(-) diff --git a/src/Nri/Ui/TextInput/V5.elm b/src/Nri/Ui/TextInput/V5.elm index 583959b4..9c25b162 100644 --- a/src/Nri/Ui/TextInput/V5.elm +++ b/src/Nri/Ui/TextInput/V5.elm @@ -2,7 +2,7 @@ module Nri.Ui.TextInput.V5 exposing ( Model , view, writing , generateId - , number, float, text, password + , InputType, number, float, text, password ) {-| @@ -19,12 +19,12 @@ module Nri.Ui.TextInput.V5 exposing ## Input types -@docs number, float, text, password +@docs InputType, number, float, text, password -} import Accessibility.Styled.Style as Accessibility -import Css exposing (batch, center, position, px, relative, textAlign) +import Css exposing (center, position, px, relative, textAlign) import Css.Global import Html.Styled as Html exposing (..) import Html.Styled.Attributes as Attributes exposing (..) diff --git a/styleguide-app/Examples/TextInput.elm b/styleguide-app/Examples/TextInput.elm index aae8492d..f0fada68 100644 --- a/styleguide-app/Examples/TextInput.elm +++ b/styleguide-app/Examples/TextInput.elm @@ -6,9 +6,10 @@ module Examples.TextInput exposing (Msg, State, example, init, update) -} +import Accessibility.Styled as Html exposing (..) import Category exposing (Category(..)) +import Debug.Control as Control exposing (Control) import Dict exposing (Dict) -import Html.Styled as Html import ModuleExample exposing (ModuleExample) import Nri.Ui.Heading.V2 as Heading import Nri.Ui.TextInput.V5 as TextInput @@ -21,6 +22,7 @@ type Msg | SetNumberInput (Maybe Int) | SetFloatInput (Maybe Float) | SetPassword String + | UpdateControl (Control ExampleConfig) {-| -} @@ -29,147 +31,103 @@ type alias State = , floatInputValue : Maybe Float , textInputValues : Dict Id String , passwordInputValue : String + , control : Control ExampleConfig + } + + +type alias ExampleConfig = + { showLabel : Bool + , label : String + , isInError : Bool + , placeholder : String } {-| -} example : (Msg -> msg) -> State -> ModuleExample msg example parentMessage state = + let + exampleConfig = + Control.currentValue state.control + in { name = "Nri.Ui.TextInput.V5" , categories = Set.fromList Category.sorter <| List.singleton Inputs , content = [ Html.map parentMessage <| Html.div [] - [ TextInput.view - { label = "Criterion" - , isInError = False - , placeholder = "For example, \"Something!!\"" + [ Control.view UpdateControl state.control + |> Html.fromUnstyled + , Heading.h3 [] [ text "TextInput.view { type_ = TextInput.text }" ] + , TextInput.view + { label = exampleConfig.label + , isInError = exampleConfig.isInError + , placeholder = exampleConfig.placeholder + , showLabel = exampleConfig.showLabel , value = Maybe.withDefault "" <| Dict.get 1 state.textInputValues , onInput = SetTextInput 1 , onBlur = Nothing , autofocus = False , type_ = TextInput.text - , showLabel = True } - , Html.br [] [] + , Heading.h3 [] [ text "... type_ = TextInput.number" ] , TextInput.view - { label = "Points" - , isInError = False - , placeholder = "enter a number" + { label = exampleConfig.label + , isInError = exampleConfig.isInError + , placeholder = exampleConfig.placeholder + , showLabel = exampleConfig.showLabel , value = state.numberInputValue , onInput = SetNumberInput , onBlur = Nothing , autofocus = False , type_ = TextInput.number - , showLabel = True } - , Html.br [] [] + , Heading.h3 [] [ text "... type_ = TextInput.float" ] , TextInput.view - { label = "Points (decimal)" - , isInError = False - , placeholder = "enter a decimal" + { label = exampleConfig.label + , isInError = exampleConfig.isInError + , placeholder = exampleConfig.placeholder + , showLabel = exampleConfig.showLabel , value = state.floatInputValue , onInput = SetFloatInput , onBlur = Nothing , autofocus = False , type_ = TextInput.float - , showLabel = True } - , Html.br [] [] + , Heading.h3 [] [ text "... type_ = TextInput.password" ] , TextInput.view - { label = "Password" - , isInError = False - , placeholder = "" + { label = exampleConfig.label + , isInError = exampleConfig.isInError + , placeholder = exampleConfig.placeholder + , showLabel = exampleConfig.showLabel , value = state.passwordInputValue , onInput = SetPassword , onBlur = Nothing , autofocus = False , type_ = TextInput.password - , showLabel = True } - , Html.br [] [] - , TextInput.view - { label = "Error" - , isInError = True - , placeholder = "Wrong!" - , value = state.numberInputValue - , onInput = SetNumberInput - , onBlur = Nothing - , autofocus = False - , type_ = TextInput.number - , showLabel = True - } - , Heading.h3 [] [ Html.text "invisible label" ] - , TextInput.view - { label = "Invisible label text input" - , isInError = False - , placeholder = "For example, \"Something!!\"" - , value = Maybe.withDefault "" <| Dict.get 2 state.textInputValues - , onInput = SetTextInput 2 - , onBlur = Nothing - , autofocus = False - , type_ = TextInput.text - , showLabel = False - } - , Html.br [] [] - , TextInput.view - { label = "Invisible label text input with error" - , placeholder = "Everything you type is wrong!" - , value = Maybe.withDefault "" <| Dict.get 3 state.textInputValues - , onInput = SetTextInput 3 - , onBlur = Nothing - , isInError = True - , autofocus = False - , type_ = TextInput.text - , showLabel = False - } - , Heading.h3 [] [ Html.text "Writing Style" ] + , Heading.h3 [] [ Html.text "TextInput.writing { type_ = TextInput.text }" ] , TextInput.writing - { label = "Writing!" - , isInError = False - , placeholder = "Writing is good for me and my family" + { label = exampleConfig.label + , isInError = exampleConfig.isInError + , placeholder = exampleConfig.placeholder , value = Maybe.withDefault "" <| Dict.get 4 state.textInputValues , onInput = SetTextInput 4 , onBlur = Nothing , autofocus = False , type_ = TextInput.text - , showLabel = True + , showLabel = exampleConfig.showLabel } - , Html.br [] [] + , Heading.h3 [] [ text "onBlur demonstration" ] , TextInput.writing - { label = "Writing with errors!" - , isInError = True - , placeholder = "Oopsie!" - , value = Maybe.withDefault "" <| Dict.get 5 state.textInputValues - , onInput = SetTextInput 5 - , onBlur = Nothing - , autofocus = False - , type_ = TextInput.text - , showLabel = True - } - , Html.br [] [] - , TextInput.writing - { label = "Writing without labels!" - , isInError = False - , placeholder = "No label on this writing input!" - , value = Maybe.withDefault "" <| Dict.get 6 state.textInputValues - , onInput = SetTextInput 6 - , onBlur = Nothing - , autofocus = False - , type_ = TextInput.text - , showLabel = False - } - , Html.br [] [] - , TextInput.writing - { label = "Writing onBlur demonstration!" - , isInError = False - , placeholder = "Click away to blur!" + { label = exampleConfig.label + , isInError = exampleConfig.isInError + , placeholder = exampleConfig.placeholder , value = Maybe.withDefault "" <| Dict.get 7 state.textInputValues , onInput = SetTextInput 7 , onBlur = Just (SetTextInput 7 "Blurred!") , autofocus = False , type_ = TextInput.text - , showLabel = True + , showLabel = exampleConfig.showLabel } ] ] @@ -183,6 +141,12 @@ init = , floatInputValue = Nothing , textInputValues = Dict.empty , passwordInputValue = "" + , control = + Control.record ExampleConfig + |> Control.field "showLabel" (Control.bool True) + |> Control.field "label" (Control.string "Assignment name") + |> Control.field "isInError" (Control.bool False) + |> Control.field "placeholder" (Control.string "Learning with commas") } @@ -202,6 +166,9 @@ update msg state = SetPassword password -> ( { state | passwordInputValue = password }, Cmd.none ) + UpdateControl newControl -> + ( { state | control = newControl }, Cmd.none ) + -- INTERNAL From f18656157c2118372f5a1a86fcf5aee570014bb2 Mon Sep 17 00:00:00 2001 From: Aaron VonderHaar Date: Tue, 31 Mar 2020 13:19:56 -0700 Subject: [PATCH 2/5] Add TextInput.V5.email input type --- src/Nri/Ui/TextInput/V5.elm | 41 +++++++++++++++++++++++++-- styleguide-app/Examples/TextInput.elm | 24 ++++++++++++---- 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/Nri/Ui/TextInput/V5.elm b/src/Nri/Ui/TextInput/V5.elm index 9c25b162..07151253 100644 --- a/src/Nri/Ui/TextInput/V5.elm +++ b/src/Nri/Ui/TextInput/V5.elm @@ -2,7 +2,7 @@ module Nri.Ui.TextInput.V5 exposing ( Model , view, writing , generateId - , InputType, number, float, text, password + , InputType, number, float, text, password, email ) {-| @@ -19,7 +19,7 @@ module Nri.Ui.TextInput.V5 exposing ## Input types -@docs InputType, number, float, text, password +@docs InputType, number, float, text, password, email -} @@ -54,6 +54,8 @@ type InputType value { toString : value -> String , fromString : String -> value , fieldType : String + , inputMode : Maybe String + , autocomplete : Maybe String } @@ -65,6 +67,8 @@ text = { toString = identity , fromString = identity , fieldType = "text" + , inputMode = Nothing + , autocomplete = Nothing } @@ -76,6 +80,8 @@ number = { toString = Maybe.map String.fromInt >> Maybe.withDefault "" , fromString = String.toInt , fieldType = "number" + , inputMode = Nothing + , autocomplete = Nothing } @@ -87,6 +93,8 @@ float = { toString = Maybe.map String.fromFloat >> Maybe.withDefault "" , fromString = String.toFloat , fieldType = "number" + , inputMode = Nothing + , autocomplete = Nothing } @@ -98,6 +106,26 @@ password = { toString = identity , fromString = identity , fieldType = "password" + , inputMode = Nothing + , autocomplete = Just "current-password" + } + + +{-| An input that is optimized for email entry + +NOTE: this uses `inputmode="email"` so that mobile devices will use the email keyboard, +but not `type="email"` because that would enable browser-provided validation which is inconsistent and at odds +with our validation UI. + +-} +email : InputType String +email = + InputType + { toString = identity + , fromString = identity + , fieldType = "text" + , inputMode = Just "email" + , autocomplete = Just "email" } @@ -128,6 +156,11 @@ view_ theme model = else [] + + maybeAttr attr maybeValue = + maybeValue + |> Maybe.map attr + |> Maybe.withDefault Extra.none in div [ Attributes.css [ position relative ] @@ -151,9 +184,11 @@ view_ theme model = , placeholder model.placeholder , value (inputType.toString model.value) , onInput (inputType.fromString >> model.onInput) - , Maybe.withDefault Extra.none (Maybe.map Events.onBlur model.onBlur) + , maybeAttr Events.onBlur model.onBlur , autofocus model.autofocus , type_ inputType.fieldType + , maybeAttr (attribute "inputmode") inputType.inputMode + , maybeAttr (attribute "autocomplete") inputType.autocomplete , class "override-sass-styles" , Attributes.attribute "aria-invalid" <| if model.isInError then diff --git a/styleguide-app/Examples/TextInput.elm b/styleguide-app/Examples/TextInput.elm index f0fada68..5dcfa8c7 100644 --- a/styleguide-app/Examples/TextInput.elm +++ b/styleguide-app/Examples/TextInput.elm @@ -29,7 +29,7 @@ type Msg type alias State = { numberInputValue : Maybe Int , floatInputValue : Maybe Float - , textInputValues : Dict Id String + , stringInputValues : Dict Id String , passwordInputValue : String , control : Control ExampleConfig } @@ -63,7 +63,7 @@ example parentMessage state = , isInError = exampleConfig.isInError , placeholder = exampleConfig.placeholder , showLabel = exampleConfig.showLabel - , value = Maybe.withDefault "" <| Dict.get 1 state.textInputValues + , value = Maybe.withDefault "" <| Dict.get 1 state.stringInputValues , onInput = SetTextInput 1 , onBlur = Nothing , autofocus = False @@ -105,12 +105,24 @@ example parentMessage state = , autofocus = False , type_ = TextInput.password } + , Heading.h3 [] [ text "... type_ = TextInput.email" ] + , TextInput.view + { label = exampleConfig.label + , isInError = exampleConfig.isInError + , placeholder = exampleConfig.placeholder + , showLabel = exampleConfig.showLabel + , value = Maybe.withDefault "" <| Dict.get 2 state.stringInputValues + , onInput = SetTextInput 2 + , onBlur = Nothing + , autofocus = False + , type_ = TextInput.email + } , Heading.h3 [] [ Html.text "TextInput.writing { type_ = TextInput.text }" ] , TextInput.writing { label = exampleConfig.label , isInError = exampleConfig.isInError , placeholder = exampleConfig.placeholder - , value = Maybe.withDefault "" <| Dict.get 4 state.textInputValues + , value = Maybe.withDefault "" <| Dict.get 4 state.stringInputValues , onInput = SetTextInput 4 , onBlur = Nothing , autofocus = False @@ -122,7 +134,7 @@ example parentMessage state = { label = exampleConfig.label , isInError = exampleConfig.isInError , placeholder = exampleConfig.placeholder - , value = Maybe.withDefault "" <| Dict.get 7 state.textInputValues + , value = Maybe.withDefault "" <| Dict.get 7 state.stringInputValues , onInput = SetTextInput 7 , onBlur = Just (SetTextInput 7 "Blurred!") , autofocus = False @@ -139,7 +151,7 @@ init : State init = { numberInputValue = Nothing , floatInputValue = Nothing - , textInputValues = Dict.empty + , stringInputValues = Dict.empty , passwordInputValue = "" , control = Control.record ExampleConfig @@ -155,7 +167,7 @@ update : Msg -> State -> ( State, Cmd Msg ) update msg state = case msg of SetTextInput id textInputValue -> - ( { state | textInputValues = Dict.insert id textInputValue state.textInputValues }, Cmd.none ) + ( { state | stringInputValues = Dict.insert id textInputValue state.stringInputValues }, Cmd.none ) SetNumberInput numberInputValue -> ( { state | numberInputValue = numberInputValue }, Cmd.none ) From 3cdf2cbcb0131219b0928cdc591c38c59c58f55b Mon Sep 17 00:00:00 2001 From: Aaron VonderHaar Date: Tue, 31 Mar 2020 13:26:35 -0700 Subject: [PATCH 3/5] Fix ARIA in examples --- styleguide-app/Examples/TextInput.elm | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/styleguide-app/Examples/TextInput.elm b/styleguide-app/Examples/TextInput.elm index 5dcfa8c7..1ac6f647 100644 --- a/styleguide-app/Examples/TextInput.elm +++ b/styleguide-app/Examples/TextInput.elm @@ -59,7 +59,7 @@ example parentMessage state = |> Html.fromUnstyled , Heading.h3 [] [ text "TextInput.view { type_ = TextInput.text }" ] , TextInput.view - { label = exampleConfig.label + { label = exampleConfig.label ++ " (text)" , isInError = exampleConfig.isInError , placeholder = exampleConfig.placeholder , showLabel = exampleConfig.showLabel @@ -71,7 +71,7 @@ example parentMessage state = } , Heading.h3 [] [ text "... type_ = TextInput.number" ] , TextInput.view - { label = exampleConfig.label + { label = exampleConfig.label ++ " (number)" , isInError = exampleConfig.isInError , placeholder = exampleConfig.placeholder , showLabel = exampleConfig.showLabel @@ -83,7 +83,7 @@ example parentMessage state = } , Heading.h3 [] [ text "... type_ = TextInput.float" ] , TextInput.view - { label = exampleConfig.label + { label = exampleConfig.label ++ " (float)" , isInError = exampleConfig.isInError , placeholder = exampleConfig.placeholder , showLabel = exampleConfig.showLabel @@ -95,7 +95,7 @@ example parentMessage state = } , Heading.h3 [] [ text "... type_ = TextInput.password" ] , TextInput.view - { label = exampleConfig.label + { label = exampleConfig.label ++ " (password)" , isInError = exampleConfig.isInError , placeholder = exampleConfig.placeholder , showLabel = exampleConfig.showLabel @@ -107,7 +107,7 @@ example parentMessage state = } , Heading.h3 [] [ text "... type_ = TextInput.email" ] , TextInput.view - { label = exampleConfig.label + { label = exampleConfig.label ++ " (email)" , isInError = exampleConfig.isInError , placeholder = exampleConfig.placeholder , showLabel = exampleConfig.showLabel @@ -119,7 +119,7 @@ example parentMessage state = } , Heading.h3 [] [ Html.text "TextInput.writing { type_ = TextInput.text }" ] , TextInput.writing - { label = exampleConfig.label + { label = exampleConfig.label ++ " (writing)" , isInError = exampleConfig.isInError , placeholder = exampleConfig.placeholder , value = Maybe.withDefault "" <| Dict.get 4 state.stringInputValues @@ -131,7 +131,7 @@ example parentMessage state = } , Heading.h3 [] [ text "onBlur demonstration" ] , TextInput.writing - { label = exampleConfig.label + { label = exampleConfig.label ++ " (onBlur)" , isInError = exampleConfig.isInError , placeholder = exampleConfig.placeholder , value = Maybe.withDefault "" <| Dict.get 7 state.stringInputValues From f964a2e2d50e57cb7733f46d5a1ecea391cfc9e9 Mon Sep 17 00:00:00 2001 From: Aaron VonderHaar Date: Fri, 10 Apr 2020 14:53:33 -0700 Subject: [PATCH 4/5] Upgrade to avh4/elm-debug-controls@2.2.1 --- script/format-axe-report.sh | 2 +- styleguide-app/elm.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/script/format-axe-report.sh b/script/format-axe-report.sh index 52918ad3..0523a72d 100755 --- a/script/format-axe-report.sh +++ b/script/format-axe-report.sh @@ -12,7 +12,7 @@ jq -r -f script/axe-report.jq "$JSON_FILE" # Hey there! Did this script tell you to check out this file because the # expected error count went down? Well done! Just change this number to the new # value. -TARGET_ERRORS=12 +TARGET_ERRORS=1 # ideally we'd fail on any failures, but we have had a bunch build up over time! # So right now, we need to fail if the error count is not exactly what we diff --git a/styleguide-app/elm.json b/styleguide-app/elm.json index ba78aacb..78a77c4f 100644 --- a/styleguide-app/elm.json +++ b/styleguide-app/elm.json @@ -7,7 +7,7 @@ "elm-version": "0.19.0", "dependencies": { "direct": { - "avh4/elm-debug-controls": "2.0.0", + "avh4/elm-debug-controls": "2.2.1", "elm/browser": "1.0.1", "elm/core": "1.0.2", "elm/html": "1.0.0", From 6d8eccd1410b69f3f1077a08045340c35800a276 Mon Sep 17 00:00:00 2001 From: Aaron VonderHaar Date: Fri, 10 Apr 2020 14:54:59 -0700 Subject: [PATCH 5/5] Upgrade styleguide-app dependencies --- styleguide-app/elm.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/styleguide-app/elm.json b/styleguide-app/elm.json index 78a77c4f..214e9bd0 100644 --- a/styleguide-app/elm.json +++ b/styleguide-app/elm.json @@ -8,8 +8,8 @@ "dependencies": { "direct": { "avh4/elm-debug-controls": "2.2.1", - "elm/browser": "1.0.1", - "elm/core": "1.0.2", + "elm/browser": "1.0.2", + "elm/core": "1.0.5", "elm/html": "1.0.0", "elm/json": "1.1.3", "elm/parser": "1.1.0", @@ -18,7 +18,7 @@ "elm/url": "1.0.0", "elm-community/string-extra": "4.0.1", "pablohirafuji/elm-markdown": "2.0.5", - "rtfeldman/elm-css": "16.0.0", + "rtfeldman/elm-css": "16.0.1", "rtfeldman/elm-sorter-experiment": "2.1.1", "tesk9/accessible-html": "4.0.0", "tesk9/accessible-html-with-css": "2.1.1", @@ -27,11 +27,11 @@ "wernerdegroot/listzipper": "4.0.0" }, "indirect": { - "NoRedInk/datetimepicker-legacy": "1.0.1", + "NoRedInk/datetimepicker-legacy": "1.0.4", "Skinney/murmur3": "2.0.8", "elm/time": "1.0.0", "elm/virtual-dom": "1.0.2", - "justinmimbs/date": "3.1.2", + "justinmimbs/date": "3.2.0", "justinmimbs/time-extra": "1.1.0", "rtfeldman/elm-hex": "1.0.0" }