@@ -1,51 +1,136 @@
11module Element.Input exposing
2− ( button
2+ ( focusedOnLoad
3+ , button
34 , checkbox, defaultCheckbox
4− , text, Placeholder, placeholder
5+ , text, multiline
6+ , Placeholder, placeholder
57 , username, newPassword, currentPassword, email, search, spellChecked
6− , multiline
78 , slider, Thumb, thumb, defaultThumb
89 , radio, radioRow, Option, option, optionWith, OptionState(..)
910 , Label, labelAbove, labelBelow, labelLeft, labelRight, labelHidden
10− , focusedOnLoad
1111 )
1212
13−{-|
13+{-| Input elements have a lot of constraints!
14+
15+We want all of our input elements to:
16+
17+ - _Always be accessible_
18+ - _Behave intuitively_
19+ - _Be completely restyleable_
20+
21+While these three goals may seem pretty obvious, Html and CSS have made it surprisingly difficult to achieve!
22+
23+And incredibly difficult for develoeprs to remember all the tricks necessary to make things work. If you've every tried to make a `<textarea>` be the height of it's content or restyle a radio button while maintaining accessibility, you may be familiar!
24+
25+This module is intended to be accessible by default. You shouldn't have to wade through docs, articles, and books to find out [exactly how accessible your html actually is](https://www.powermapper.com/tests/screen-readers/aria/index.html).
26+
27+
28+# Focus Styling
29+
30+All Elements can be styled on focus by using [`Element.focusStyle`](Element#focusStyle) to set a global focus style or [`Element.focused`](Element#focused) to set a focus style individually for an element.
31+
32+@docs focusedOnLoad
33+
34+
35+# Buttons
1436
1537@docs button
1638
39+
40+# Checkboxes
41+
42+A checkbox requires you to store a `Bool` in your model.
43+
44+This is also the first input element that has a [`required label`](#Label).
45+
46+ import Element exposing (text)
47+ import Element.Input as Input
48+
49+ type Msg
50+ = GuacamoleChecked Bool
51+
52+ view model =
53+ Input.checkbox []
54+ { onChange = GuacamoleChecked
55+ , icon = Input.defaultCheckbox
56+ , checked = model.guacamole
57+ , label =
58+ Input.labelRight []
59+ (text "Do you want Guacamole?")
60+ }
61+
1762@docs checkbox, defaultCheckbox
1863
1964
20−## Text Input
65+# Text
2166
22−@docs text, Placeholder, placeholder
67+@docs text, multiline
2368
24−We can also give a hint about what type of content our text field contains. This will allow things like autofill to work correctly.
69+@docs Placeholder, placeholder
2570
26−@docs username, newPassword, currentPassword, email, search, spellChecked
2771
72+## Text with autofill
2873
29−## Multiline Text
74+If we want to play nicely with a browser's ability to autofill a form, we need to be able to give it a hint about what we're expecting.
75+
76+The following inputs are very similar to `Input.text`, but they give the browser a hint to allow autofill to work correctly.
77+
78+@docs username, newPassword, currentPassword, email, search, spellChecked
3079
31−@docs multiline
3280
81+# Sliders
3382
34−## Slider
83+A slider is great for choosing between a range of numerical values.
84+
85+ - **thumb** - The icon that you click and drag to change the value.
86+ - **track** - The line behind the thumb denoting where you can slide to.
3587
3688@docs slider, Thumb, thumb, defaultThumb
3789
3890
39−## Radio Buttons
91+# Radio Selection
92+
93+The fact that we still call this a radio selection is fascinating. I can't remember the last time I actually used an honest-to-goodness button on a radio. Chalk it up along with the floppy disk save icon or the word [Dashboard](https://en.wikipedia.org/wiki/Dashboard).
94+
95+Perhaps a better name would be `Input.chooseOne`, because this allows you to select one of a set of options!
96+
97+Nevertheless, here we are. Here's how you put one together
98+
99+ Input.radio
100+ [ padding 10
101+ , spacing 20
102+ ]
103+ { onChange = ChooseLunch
104+ , selected = Just model.lunch
105+ , label = Input.labelAbove [] (text "Lunch")
106+ , options =
107+ [ Input.option Burrito (text "Burrito")
108+ , Input.option Taco (text "Taco!")
109+ , Input.option Gyro (text "Gyro")
110+ ]
111+ }
112+
113+**Note** we're using `Input.option`, which will render the default radio icon you're probably used to. If you want compeltely custom styling, use `Input.optionWith`!
40114
41115@docs radio, radioRow, Option, option, optionWith, OptionState
42116
43117
44−## Labels
118+# Labels
119+
120+Every input has a required `Label`.
45121
46122@docs Label, labelAbove, labelBelow, labelLeft, labelRight, labelHidden
47123
48−@docs focusedOnLoad
124+
125+# Form Elements
126+
127+You might be wondering where something like `<form>` is.
128+
129+What I've found is that most people who want `<form>` usually want it for the [implicit submission behavior](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#implicit-submission) or to be clearer, they want to do something when the `Enter` key is pressed.
130+
131+Instead of implicit submission behavior, [try making an `onEnter` event handler like in this Ellie Example](https://ellie-app.com/5X6jBKtxzdpa1). Then everything is explicit!
132+
133+And no one has to look up obtuse html documentation to understand the behavior of their code :).
49134
50135-}
51136
@@ -97,8 +182,7 @@ type LabelLocation
97182 | Below
98183
99184
100−{-| Every input has a required `label`.
101−-}
185+{-| -}
102186type Label msg
103187 = Label LabelLocation (List (Attribute msg)) (Element msg)
104188 | HiddenLabel String
@@ -156,14 +240,24 @@ hiddenLabelAttribute label =
156240
157241{-| A standard button.
158242
159−The `onPress` handler will be fired either `onClick` or when the element is focused and the enter key has been pressed.
243+The `onPress` handler will be fired either `onClick` or when the element is focused and the `Enter` key has been pressed.
160244
245+ import Element exposing (rgb255, text)
246+ import Element.Background as Background
161247 import Element.Input as Input
162248
163− Input.button []
164− { onPress = ClickMsg
165− , label = text "My Button"
166− }
249+ blue =
250+ Element.rgb255 238 238 238
251+
252+ myButton =
253+ Input.button
254+ [ Background.color blue
255+ , Element.focused
256+ [ Background.color purple ]
257+ ]
258+ { onPress = ClickMsg
259+ , label = text "My Button"
260+ }
167261
168262`onPress` takes a `Maybe msg`. If you provide the value `Nothing`, then the button will be disabled.
169263
@@ -237,7 +331,14 @@ type alias Checkbox msg =
237331 }
238332
239333
240−{-| -}
334+{-|
335+
336+ - **onChange** - The `Msg` to send.
337+ - **icon** - The checkbox icon to show. This can be whatever you'd like, but `Input.defaultCheckbox` is included to get you started.
338+ - **checked** - The current checked state.
339+ - **label** - The [`Label`](#Label) for this checkbox
340+
341+-}
241342checkbox :
242343 List (Attribute msg)
243344 ->
@@ -343,7 +444,9 @@ defaultThumb =
343444 )
344445 ]
345446 { onChange = AdjustValue
346− , label = Input.labelAbove [] (text "My Slider Value")
447+ , label =
448+ Input.labelAbove []
449+ (text "My Slider Value")
347450 , min = 0
348451 , max = 75
349452 , step = Nothing
@@ -360,7 +463,7 @@ The slider can be vertical or horizontal depending on the width/height of the sl
360463 - `height (px someHeight)` and `width (px someWidth)` where `someHeight` > `someWidth` will also do it.
361464 - otherwise, the slider will be horizontal.
362465
363−**Note:** If you want a slider for an `Int` value:
466+**Note** If you want a slider for an `Int` value:
364467
365468 - set `step` to be `Just 1`, or some other whole value
366469 - `value = toFloat model.myInt`
@@ -1068,7 +1171,7 @@ search =
10681171
10691172It's `newPassword` instead of just `password` because it gives the browser a hint on what type of password input it is.
10701173
1071−A password takes all the arguments a normal `Input.text` would, and also `show`, which will remove the password mask (e.g. `****` vs `pass1234`)
1174+A password takes all the arguments a normal `Input.text` would, and also **show**, which will remove the password mask (e.g. `****` vs `pass1234`)
10721175
10731176-}
10741177newPassword :
@@ -1168,7 +1271,11 @@ email =
11681271 }
11691272
11701273
1171−{-| -}
1274+{-| A multiline text input.
1275+
1276+By default it will have a minimum height of one line and resize based on it's contents.
1277+
1278+-}
11721279multiline :
11731280 List (Attribute msg)
11741281 ->
@@ -1254,8 +1361,7 @@ applyLabel attrs label input =
12541361 (Internal.Unkeyed [ labelElement, input ])
12551362
12561363
1257−{-| Add choices to your radio and select menus.
1258−-}
1364+{-| -}
12591365type Option value msg
12601366 = Option value (OptionState -> Element msg)
12611367
@@ -1267,35 +1373,21 @@ type OptionState
12671373 | Selected
12681374
12691375
1270−{-| -}
1376+{-| Add a choice to your radio element. This will be rendered with the default radio icon.
1377+-}
12711378option : value -> Element msg -> Option value msg
12721379option val txt =
12731380 Option val (defaultRadioOption txt)
12741381
12751382
1276−{-| -}
1383+{-| Customize exactly what your radio option should look like in different states.
1384+-}
12771385optionWith : value -> (OptionState -> Element msg) -> Option value msg
12781386optionWith val view =
12791387 Option val view
12801388
12811389
1282−{-|
1283−
1284− Input.radio
1285− [ padding 10
1286− , spacing 20
1287− ]
1288− { onChange = ChooseLunch
1289− , selected = Just model.lunch
1290− , label = Input.labelAbove [] (text "Lunch")
1291− , options =
1292− [ Input.option Burrito (text "Burrito")
1293− , Input.option Taco (text "Taco!")
1294− , Input.option Gyro (text "Gyro")
1295− ]
1296− }
1297−
1298−-}
1390+{-| -}
12991391radio :
13001392 List (Attribute msg)
13011393 ->
@@ -1776,7 +1868,11 @@ autofill =
17761868 Internal.Attr << Html.Attributes.attribute "autocomplete"
17771869
17781870
1779−{-| -}
1871+{-| Attach this attribute to any `Input` that you would like to be automatically focused when the page loads.
1872+
1873+You should only have a maximum of one per page.
1874+
1875+-}
17801876focusedOnLoad : Attribute msg
17811877focusedOnLoad =
17821878 Internal.Attr <| Html.Attributes.autofocus True
@@ -1803,7 +1899,11 @@ defaultTextPadding =
18031899 Element.paddingXY 12 12
18041900
18051901
1806−{-| -}
1902+{-| The blue default checked box icon.
1903+
1904+You'll likely want to make your own checkbox at some point that fits your design.
1905+
1906+-}
18071907defaultCheckbox : Bool -> Element msg
18081908defaultCheckbox checked =
18091909 Element.el
@@ -1821,7 +1921,7 @@ defaultCheckbox checked =
18211921
18221922 else
18231923 Element.rgb (211 / 255) (211 / 255) (211 / 255)
1824− , Border.shadow <|
1924+ , Border.shadow
18251925 { offset = ( 0, 0 )
18261926 , blur = 1
18271927 , size = 1