git.iko.soy/typeable/elm-ui
on master help sign in
Expand on `Input` documentation.
20f721aMatthew Griffith
src/Element/Input.elm+151−51
@@ -1,51 +1,136 @@
1module Element.Input exposing
1module Element.Input exposing
2+ ( focusedOnLoad
2− ( button
3+ , button
3 , checkbox, defaultCheckbox
4 , checkbox, defaultCheckbox
5+ , text, multiline
4− , text, Placeholder, placeholder
6+ , Placeholder, placeholder
5 , username, newPassword, currentPassword, email, search, spellChecked
7 , username, newPassword, currentPassword, email, search, spellChecked
6− , multiline
7 , slider, Thumb, thumb, defaultThumb
8 , slider, Thumb, thumb, defaultThumb
8 , radio, radioRow, Option, option, optionWith, OptionState(..)
9 , radio, radioRow, Option, option, optionWith, OptionState(..)
9 , Label, labelAbove, labelBelow, labelLeft, labelRight, labelHidden
10 , Label, labelAbove, labelBelow, labelLeft, labelRight, labelHidden
10− , focusedOnLoad
11 )
11 )
12
12
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
14
36
15@docs button
37@docs button
16
38
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+
17@docs checkbox, defaultCheckbox
62@docs checkbox, defaultCheckbox
18
63
19
64
20−## Text Input
65+# Text
21
66
22−@docs text, Placeholder, placeholder
67+@docs text, multiline
23
68
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
25
70
26−@docs username, newPassword, currentPassword, email, search, spellChecked
27
71
72+## Text with autofill
28
73
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
30
79
31−@docs multiline
32
80
81+# Sliders
33
82
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.
35
87
36@docs slider, Thumb, thumb, defaultThumb
88@docs slider, Thumb, thumb, defaultThumb
37
89
38
90
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`!
40
114
41@docs radio, radioRow, Option, option, optionWith, OptionState
115@docs radio, radioRow, Option, option, optionWith, OptionState
42
116
43
117
44−## Labels
118+# Labels
119+
120+Every input has a required `Label`.
45
121
46@docs Label, labelAbove, labelBelow, labelLeft, labelRight, labelHidden
122@docs Label, labelAbove, labelBelow, labelLeft, labelRight, labelHidden
47
123
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 :).
49
134
50-}
135-}
51
136
@@ -97,8 +182,7 @@ type LabelLocation
97 | Below
182 | Below
98
183
99
184
100−{-| Every input has a required `label`.
101−-}
185+{-| -}
102type Label msg
186type Label msg
103 = Label LabelLocation (List (Attribute msg)) (Element msg)
187 = Label LabelLocation (List (Attribute msg)) (Element msg)
104 | HiddenLabel String
188 | HiddenLabel String
@@ -156,14 +240,24 @@ hiddenLabelAttribute label =
156
240
157{-| A standard button.
241{-| A standard button.
158
242
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.
160
244
245+ import Element exposing (rgb255, text)
246+ import Element.Background as Background
161 import Element.Input as Input
247 import Element.Input as Input
162
248
249+ blue =
250+ Element.rgb255 238 238 238
251+
252+ myButton =
163− Input.button []
253+ Input.button
254+ [ Background.color blue
255+ , Element.focused
256+ [ Background.color purple ]
257+ ]
164− { onPress = ClickMsg
258+ { onPress = ClickMsg
165− , label = text "My Button"
259+ , label = text "My Button"
166− }
260+ }
167
261
168`onPress` takes a `Maybe msg`. If you provide the value `Nothing`, then the button will be disabled.
262`onPress` takes a `Maybe msg`. If you provide the value `Nothing`, then the button will be disabled.
169
263
@@ -237,7 +331,14 @@ type alias Checkbox msg =
237 }
331 }
238
332
239
333
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+-}
241checkbox :
342checkbox :
242 List (Attribute msg)
343 List (Attribute msg)
243 ->
344 ->
@@ -343,7 +444,9 @@ defaultThumb =
343 )
444 )
344 ]
445 ]
345 { onChange = AdjustValue
446 { onChange = AdjustValue
447+ , label =
448+ Input.labelAbove []
346− , label = Input.labelAbove [] (text "My Slider Value")
449+ (text "My Slider Value")
347 , min = 0
450 , min = 0
348 , max = 75
451 , max = 75
349 , step = Nothing
452 , step = Nothing
@@ -360,7 +463,7 @@ The slider can be vertical or horizontal depending on the width/height of the sl
360 - `height (px someHeight)` and `width (px someWidth)` where `someHeight` > `someWidth` will also do it.
463 - `height (px someHeight)` and `width (px someWidth)` where `someHeight` > `someWidth` will also do it.
361 - otherwise, the slider will be horizontal.
464 - otherwise, the slider will be horizontal.
362
465
363−**Note:** If you want a slider for an `Int` value:
466+**Note** If you want a slider for an `Int` value:
364
467
365 - set `step` to be `Just 1`, or some other whole value
468 - set `step` to be `Just 1`, or some other whole value
366 - `value = toFloat model.myInt`
469 - `value = toFloat model.myInt`
@@ -1068,7 +1171,7 @@ search =
1068
1171
1069It's `newPassword` instead of just `password` because it gives the browser a hint on what type of password input it is.
1172It's `newPassword` instead of just `password` because it gives the browser a hint on what type of password input it is.
1070
1173
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`)
1072
1175
1073-}
1176-}
1074newPassword :
1177newPassword :
@@ -1168,7 +1271,11 @@ email =
1168 }
1271 }
1169
1272
1170
1273
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+
1171−{-| -}
1278+-}
1172multiline :
1279multiline :
1173 List (Attribute msg)
1280 List (Attribute msg)
1174 ->
1281 ->
@@ -1254,8 +1361,7 @@ applyLabel attrs label input =
1254 (Internal.Unkeyed [ labelElement, input ])
1361 (Internal.Unkeyed [ labelElement, input ])
1255
1362
1256
1363
1257−{-| Add choices to your radio and select menus.
1258−-}
1364+{-| -}
1259type Option value msg
1365type Option value msg
1260 = Option value (OptionState -> Element msg)
1366 = Option value (OptionState -> Element msg)
1261
1367
@@ -1267,35 +1373,21 @@ type OptionState
1267 | Selected
1373 | Selected
1268
1374
1269
1375
1376+{-| Add a choice to your radio element. This will be rendered with the default radio icon.
1270−{-| -}
1377+-}
1271option : value -> Element msg -> Option value msg
1378option : value -> Element msg -> Option value msg
1272option val txt =
1379option val txt =
1273 Option val (defaultRadioOption txt)
1380 Option val (defaultRadioOption txt)
1274
1381
1275
1382
1383+{-| Customize exactly what your radio option should look like in different states.
1276−{-| -}
1384+-}
1277optionWith : value -> (OptionState -> Element msg) -> Option value msg
1385optionWith : value -> (OptionState -> Element msg) -> Option value msg
1278optionWith val view =
1386optionWith val view =
1279 Option val view
1387 Option val view
1280
1388
1281
1389
1282−{-|
1390+{-| -}
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−-}
1299radio :
1391radio :
1300 List (Attribute msg)
1392 List (Attribute msg)
1301 ->
1393 ->
@@ -1776,7 +1868,11 @@ autofill =
1776 Internal.Attr << Html.Attributes.attribute "autocomplete"
1868 Internal.Attr << Html.Attributes.attribute "autocomplete"
1777
1869
1778
1870
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+
1779−{-| -}
1875+-}
1780focusedOnLoad : Attribute msg
1876focusedOnLoad : Attribute msg
1781focusedOnLoad =
1877focusedOnLoad =
1782 Internal.Attr <| Html.Attributes.autofocus True
1878 Internal.Attr <| Html.Attributes.autofocus True
@@ -1803,7 +1899,11 @@ defaultTextPadding =
1803 Element.paddingXY 12 12
1899 Element.paddingXY 12 12
1804
1900
1805
1901
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+
1806−{-| -}
1906+-}
1807defaultCheckbox : Bool -> Element msg
1907defaultCheckbox : Bool -> Element msg
1808defaultCheckbox checked =
1908defaultCheckbox checked =
1809 Element.el
1909 Element.el
@@ -1821,7 +1921,7 @@ defaultCheckbox checked =
1821
1921
1822 else
1922 else
1823 Element.rgb (211 / 255) (211 / 255) (211 / 255)
1923 Element.rgb (211 / 255) (211 / 255) (211 / 255)
1824− , Border.shadow <|
1924+ , Border.shadow
1825 { offset = ( 0, 0 )
1925 { offset = ( 0, 0 )
1826 , blur = 1
1926 , blur = 1
1827 , size = 1
1927 , size = 1