@@ -1,51 +1,136 @@
1module Element.Input exposing
1module Element.Input exposing
3 , checkbox, defaultCheckbox
4 , checkbox, defaultCheckbox
4− , text, Placeholder, placeholder
6+ , Placeholder, placeholder
5 , username, newPassword, currentPassword, email, search, spellChecked
7 , username, newPassword, currentPassword, email, search, spellChecked
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
13−{-|
13+{-| Input elements have a lot of constraints!
15+We want all of our input elements to:
17+ - _Always be accessible_
18+ - _Behave intuitively_
19+ - _Be completely restyleable_
21+While these three goals may seem pretty obvious, Html and CSS have made it surprisingly difficult to achieve!
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!
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).
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.
15@docs button
37@docs button
42+A checkbox requires you to store a `Bool` in your model.
44+This is also the first input element that has a [`required label`](#Label).
46+ import Element exposing (text)
47+ import Element.Input as Input
50+ = GuacamoleChecked Bool
54+ { onChange = GuacamoleChecked
55+ , icon = Input.defaultCheckbox
56+ , checked = model.guacamole
59+ (text "Do you want Guacamole?")
17@docs checkbox, defaultCheckbox
62@docs checkbox, defaultCheckbox
20−## Text Input
65+# Text
22−@docs text, Placeholder, placeholder
67+@docs text, multiline
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
26−@docs username, newPassword, currentPassword, email, search, spellChecked
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.
76+The following inputs are very similar to `Input.text`, but they give the browser a hint to allow autofill to work correctly.
78+@docs username, newPassword, currentPassword, email, search, spellChecked
34−## Slider
83+A slider is great for choosing between a range of numerical values.
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.
36@docs slider, Thumb, thumb, defaultThumb
88@docs slider, Thumb, thumb, defaultThumb
39−## Radio Buttons
91+# Radio Selection
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).
95+Perhaps a better name would be `Input.chooseOne`, because this allows you to select one of a set of options!
97+Nevertheless, here we are. Here's how you put one together
103+ { onChange = ChooseLunch
104+ , selected = Just model.lunch
105+ , label = Input.labelAbove [] (text "Lunch")
107+ [ Input.option Burrito (text "Burrito")
108+ , Input.option Taco (text "Taco!")
109+ , Input.option Gyro (text "Gyro")
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`!
41@docs radio, radioRow, Option, option, optionWith, OptionState
115@docs radio, radioRow, Option, option, optionWith, OptionState
120+Every input has a required `Label`.
46@docs Label, labelAbove, labelBelow, labelLeft, labelRight, labelHidden
122@docs Label, labelAbove, labelBelow, labelLeft, labelRight, labelHidden
48−@docs focusedOnLoad
124+
127+You might be wondering where something like `<form>` is.
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.
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!
133+And no one has to look up obtuse html documentation to understand the behavior of their code :).
@@ -97,8 +182,7 @@ type LabelLocation
100−{-| Every input has a required `label`.
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 =
157{-| A standard button.
241{-| A standard button.
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.
245+ import Element exposing (rgb255, text)
246+ import Element.Background as Background
161 import Element.Input as Input
247 import Element.Input as Input
250+ Element.rgb255 238 238 238
163− Input.button []
253+ Input.button
254+ [ Background.color blue
256+ [ Background.color purple ]
164− { onPress = ClickMsg
258+ { onPress = ClickMsg
165− , label = text "My Button"
259+ , label = text "My Button"
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.
@@ -237,7 +331,14 @@ type alias Checkbox msg =
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
241checkbox :
342checkbox :
242 List (Attribute msg)
343 List (Attribute msg)
@@ -343,7 +444,9 @@ defaultThumb =
345 { onChange = AdjustValue
446 { onChange = AdjustValue
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.
363−**Note:** If you want a slider for an `Int` value:
466+**Note** If you want a slider for an `Int` value:
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 =
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.
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`)
1074newPassword :
1177newPassword :
@@ -1168,7 +1271,11 @@ email =
1274+{-| A multiline text input.
1276+By default it will have a minimum height of one line and resize based on it's contents.
1172multiline :
1279multiline :
1173 List (Attribute msg)
1280 List (Attribute msg)
@@ -1254,8 +1361,7 @@ applyLabel attrs label input =
1254 (Internal.Unkeyed [ labelElement, input ])
1361 (Internal.Unkeyed [ labelElement, input ])
1257−{-| Add choices to your radio and select menus.
1259type Option value msg
1365type Option value msg
1260 = Option value (OptionState -> Element msg)
1366 = Option value (OptionState -> Element msg)
@@ -1267,35 +1373,21 @@ type OptionState
1267 | Selected
1373 | Selected
1376+{-| Add a choice to your radio element. This will be rendered with the default radio icon.
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)
1383+{-| Customize exactly what your radio option should look like in different states.
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
1288− { onChange = ChooseLunch
1289− , selected = Just model.lunch
1290− , label = Input.labelAbove [] (text "Lunch")
1292− [ Input.option Burrito (text "Burrito")
1293− , Input.option Taco (text "Taco!")
1294− , Input.option Gyro (text "Gyro")
1300 List (Attribute msg)
1392 List (Attribute msg)
@@ -1776,7 +1868,11 @@ autofill =
1776 Internal.Attr << Html.Attributes.attribute "autocomplete"
1868 Internal.Attr << Html.Attributes.attribute "autocomplete"
1871+{-| Attach this attribute to any `Input` that you would like to be automatically focused when the page loads.
1873+You should only have a maximum of one per page.
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
1902+{-| The blue default checked box icon.
1904+You'll likely want to make your own checkbox at some point that fits your design.
1807defaultCheckbox : Bool -> Element msg
1907defaultCheckbox : Bool -> Element msg
1808defaultCheckbox checked =
1908defaultCheckbox checked =
1809 Element.el
1909 Element.el
@@ -1821,7 +1921,7 @@ defaultCheckbox checked =
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