@@ -1,186 +1,51 @@
1module Element.Input exposing
1module Element.Input exposing
4 , checkbox, defaultCheckbox
3 , checkbox, defaultCheckbox
6− , Placeholder, placeholder
4+ , text, Placeholder, placeholder
7 , username, newPassword, currentPassword, email, search, spellChecked
5 , username, newPassword, currentPassword, email, search, spellChecked
8 , slider, Thumb, thumb, defaultThumb
7 , slider, Thumb, thumb, defaultThumb
9 , radio, radioRow, Option, option, optionWith, OptionState(..)
8 , radio, radioRow, Option, option, optionWith, OptionState(..)
10 , Label, labelAbove, labelBelow, labelLeft, labelRight, labelHidden
9 , Label, labelAbove, labelBelow, labelLeft, labelRight, labelHidden
13−{-| Input elements have a lot of constraints!
13+{-|
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 developers 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.
37@docs button
15@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?")
62@docs checkbox, defaultCheckbox
17@docs checkbox, defaultCheckbox
65−# Text
20+## Text Input
69−@docs Placeholder, placeholder
72−## Text with autofill
22+@docs text, Placeholder, placeholder
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.
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.
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
26@docs username, newPassword, currentPassword, email, search, spellChecked
81−# Sliders
29+## Multiline Text
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.
88−@docs slider, Thumb, thumb, defaultThumb
91−# Radio Selection
31+@docs multiline
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!
34+## Slider
97−Nevertheless, here we are. Here's how you put one together
36+@docs slider, Thumb, thumb, defaultThumb
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`!
39+## Radio Buttons
115@docs radio, radioRow, Option, option, optionWith, OptionState
41@docs radio, radioRow, Option, option, optionWith, OptionState
120−Every input has a required `Label`.
122@docs Label, labelAbove, labelBelow, labelLeft, labelRight, labelHidden
46@docs Label, labelAbove, labelBelow, labelLeft, labelRight, labelHidden
124−
48+@docs focusedOnLoad
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 :).
138−Presently, elm-ui does not expose a replacement for `<input type="file">`; in the meantime, an `Input.button` and `elm/file`'s `File.Select` may meet your needs.
143−You also might be wondering how to disable an input.
145−Disabled inputs can be a little problematic for user experience, and doubly so for accessibility. This is because it's now your priority to inform the user _why_ some field is disabled.
147−If an input is truly disabled, meaning it's not focusable or doesn't send off a `Msg`, you actually lose your ability to help the user out! For those wary about accessibility [this is a big problem.](https://ux.stackexchange.com/questions/103239/should-disabled-elements-be-focusable-for-accessibility-purposes)
149−Here are some alternatives to think about that don't involve explicitly disabling an input.
151−**Disabled Buttons** - Change the `Msg` it fires, the text that is rendered, and optionally set a `Region.description` which will be available to screen readers.
153− import Element.Input as Input
154− import Element.Region as Region
159− [ Background.color blue
162− Just SaveButtonPressed
164− text "Save blog post"
169− [ Background.color grey
170− , Region.description
171− "A publish date is required before saving a blogpost."
174− Just DisabledSaveButtonPressed
179−Consider showing a hint if `DisabledSaveButtonPressed` is sent.
181−For other inputs such as `Input.text`, consider simply rendering it in a normal `paragraph` or `el` if it's not editable.
183−Alternatively, see if it's reasonable to _not_ display an input if you'd normally disable it. Is there an option where it's only visible when it's editable?
@@ -232,33 +97,13 @@ type LabelLocation
100+{-| Every input has a required `label`.
236type Label msg
102type Label msg
237 = Label LabelLocation (List (Attribute msg)) (Element msg)
103 = Label LabelLocation (List (Attribute msg)) (Element msg)
238 | HiddenLabel String
104 | HiddenLabel String
241−isStacked : Label msg -> Bool
263labelRight : List (Attribute msg) -> Element msg -> Label msg
108labelRight : List (Attribute msg) -> Element msg -> Label msg
264labelRight =
109labelRight =
@@ -311,26 +156,16 @@ hiddenLabelAttribute label =
312{-| A standard button.
157{-| A standard button.
314−The `onPress` handler will be fired either `onClick` or when the element is focused and the `Enter` key has been pressed.
159+The `onPress` handler will be fired either `onClick` or when the element is focused and the enter key has been pressed.
316− import Element exposing (rgb255, text)
317− import Element.Background as Background
318 import Element.Input as Input
161 import Element.Input as Input
321− Element.rgb255 238 238 238
324− Input.button
163+ Input.button []
325− [ Background.color blue
327− [ Background.color purple ]
329− { onPress = Just ClickMsg
164+ { onPress = ClickMsg
330− , label = text "My Button"
165+ , label = text "My Button"
333−**Note** If you have an icon button but want it to be accessible, consider adding a [`Region.description`](Element-Region#description), which will describe the button to screen readers.
168+`onPress` takes a `Maybe msg`. If you provide the value `Nothing`, then the button will be disabled.
@@ -369,17 +204,7 @@ button attrs { onPress, label } =
370 Just msg ->
205 Just msg ->
371 Events.onClick msg
206 Events.onClick msg
372− :: onKeyLookup
207+ :: onEnter msg
374− if code == enter then
377− else if code == space then
@@ -412,14 +237,7 @@ type alias Checkbox msg =
417− - **onChange** - The `Msg` to send.
418− - **icon** - The checkbox icon to show. This can be whatever you'd like, but `Input.defaultCheckbox` is included to get you started.
419− - **checked** - The current checked state.
420− - **label** - The [`Label`](#Label) for this checkbox
423checkbox :
241checkbox :
424 List (Attribute msg)
242 List (Attribute msg)
@@ -457,24 +275,22 @@ checkbox attrs { label, icon, checked, onChange } =
460− applyLabel
278+ applyLabel attributes
461− (Internal.Attr (Html.Attributes.attribute "role" "checkbox")
284+ Html.Attributes.attribute "role" "checkbox"
462− :: Internal.Attr
285+ , Internal.Attr <|
463− (Html.Attributes.attribute "aria-checked" <|
286+ Html.Attributes.attribute "aria-checked" <|
464 if checked then
287 if checked then
470− :: hiddenLabelAttribute label
292+ , hiddenLabelAttribute label
477− [ Element.centerY
293+ , Element.centerY
478 , Element.height Element.fill
294 , Element.height Element.fill
479 , Element.width Element.shrink
295 , Element.width Element.shrink
@@ -527,9 +343,7 @@ defaultThumb =
529 { onChange = AdjustValue
345 { onChange = AdjustValue
532− (text "My Slider Value")
346+ , label = Input.labelAbove [] (text "My Slider Value")
533 , min = 0
347 , min = 0
534 , max = 75
348 , max = 75
535 , step = Nothing
349 , step = Nothing
@@ -546,7 +360,7 @@ The slider can be vertical or horizontal depending on the width/height of the sl
546 - `height (px someHeight)` and `width (px someWidth)` where `someHeight` > `someWidth` will also do it.
360 - `height (px someHeight)` and `width (px someWidth)` where `someHeight` > `someWidth` will also do it.
547 - otherwise, the slider will be horizontal.
361 - otherwise, the slider will be horizontal.
549−**Note** If you want a slider for an `Int` value:
363+**Note:** If you want a slider for an `Int` value:
551 - set `step` to be `Just 1`, or some other whole value
365 - set `step` to be `Just 1`, or some other whole value
552 - `value = toFloat model.myInt`
366 - `value = toFloat model.myInt`
@@ -713,7 +527,7 @@ slider attributes input =
713 ("input[type=\"range\"]." ++ className ++ "::-ms-thumb")
527 ("input[type=\"range\"]." ++ className ++ "::-ms-thumb")
714 thumbShadowStyle
528 thumbShadowStyle
716− , Internal.Attr (Html.Attributes.class (className ++ " ui-slide-bar focusable-parent"))
530+ , Internal.Attr (Html.Attributes.class (className ++ " focusable-parent"))
717 , Internal.Attr
531 , Internal.Attr
718 (Html.Events.onInput
532 (Html.Events.onInput
@@ -779,10 +593,10 @@ slider attributes input =
779 -- This is after `attributes` because the thumb should be in front of everything.
593 -- This is after `attributes` because the thumb should be in front of everything.
780 ++ [ Element.behindContent <|
594 ++ [ Element.behindContent <|
781 if vertical then
595 if vertical then
782− viewVerticalThumb factor (Internal.htmlClass "focusable-thumb" :: thumbAttributes) trackWidth
596+ viewVerticalThumb factor thumbAttributes trackWidth
785− viewHorizontalThumb factor (Internal.htmlClass "focusable-thumb" :: thumbAttributes) trackHeight
599+ viewHorizontalThumb factor thumbAttributes trackHeight
788 Element.none
602 Element.none
@@ -855,198 +669,304 @@ type alias Text msg =
673+ = Padding Int Int Int Int
676+inheritablePlaceholderAttributes attr =
678+ Internal.StyleClass _ (Internal.PaddingStyle _ _ _ _ _) ->
681+ Internal.StyleClass _ (Internal.BorderWidth _ _ _ _ _) ->
684+ Internal.StyleClass _ (Internal.Transform _) ->
696+ attribute::width/height fill
697+ attribtue::alignment
699+ attribute::fontsize/family/lineheight
701+ attribute::nearby(placeholder)
702+ attribute::width/height fill
710+ special height for height-content
712+ attribute::lineHeight
859textHelper : TextInput -> List (Attribute msg) -> Text msg -> Element msg
717textHelper : TextInput -> List (Attribute msg) -> Text msg -> Element msg
860textHelper textInput attrs textOptions =
718textHelper textInput attrs textOptions =
862− withDefaults =
720+ attributes =
863 defaultTextBoxStyle ++ attrs
721 defaultTextBoxStyle ++ attrs
865− redistributed =
723+ behavior =
866− redistribute (textInput.type_ == TextArea)
724+ [ Internal.Attr (Html.Events.onInput textOptions.onChange) ]
867− (isStacked textOptions.label)
870− onlySpacing attr =
726+ forPlaceholder =
871− case attr of
727+ List.filter inheritablePlaceholderAttributes attributes
872− Internal.StyleClass _ (Internal.SpacingStyle _ _ _) ->
875− _ ->
729+ noNearbys =
876− False
730+ List.filter (not << forNearby) attributes
878− getPadding attr =
732+ forNearby attr =
879 case attr of
733 case attr of
880− Internal.StyleClass cls (Internal.PaddingStyle pad t r b l) ->
734+ Internal.Nearby _ _ ->
881− -- The - 3 is here to prevent accidental triggering of scrollbars
735+ True
882− -- when things are off by a pixel or two.
883− -- (or at least when the browser *thinks* it's off by a pixel or two)
885− { top = max 0 (floor (t - 3))
886− , right = max 0 (floor (r - 3))
887− , bottom = max 0 (floor (b - 3))
888− , left = max 0 (floor (l - 3))
894− heightConstrained =
740+ ( inputNode, inputAttrs, inputChildren ) =
895 case textInput.type_ of
741 case textInput.type_ of
896 TextInputNode inputType ->
742 TextInputNode inputType ->
744+ , [ Internal.Attr (Html.Attributes.type_ inputType)
745+ , value textOptions.text
746+ , spellcheck textInput.spellchecked
747+ , Internal.htmlClass classes.inputText
748+ , case textInput.autofill of
750+ Internal.NoAttribute
899− TextArea ->
752+ Just fill ->
900− withDefaults
753+ autofill fill
901− |> List.filterMap getHeight
754+ ]
902− |> List.reverse
755+ ++ noNearbys
903− |> List.head
756+ , []
904− |> Maybe.map isConstrained
757+ )
905− |> Maybe.withDefault False
909− |> List.filterMap getPadding
912− |> Maybe.withDefault
919− inputElement =
759+ TextArea ->
761+ { maybePadding, heightContent, maybeSpacing, adjustedAttributes, maybeBorder } =
762+ (value textOptions.text :: attributes)
920− Internal.element
766+ Internal.Describe _ ->
921− Internal.asEl
769+ Internal.Height len ->
922− (case textInput.type_ of
770+ case found.heightContent of
923− TextInputNode inputType ->
771+ Nothing ->
924− Internal.NodeName "input"
772+ { found
773+ | heightContent = Just (Internal.isContent len)
774+ , adjustedAttributes = attr :: found.adjustedAttributes
780+ Internal.StyleClass _ (Internal.BorderWidth _ t r b l) ->
781+ case found.maybeBorder of
784+ | maybeBorder = Just (Padding t r b l)
785+ , adjustedAttributes = attr :: found.adjustedAttributes
791+ Internal.StyleClass _ (Internal.PaddingStyle _ t r b l) ->
792+ case found.maybePadding of
795+ | maybePadding = Just (Padding t r b l)
797+ -- Skip storing padding because it's being customized later
798+ , adjustedAttributes = found.adjustedAttributes
804+ Internal.StyleClass _ (Internal.SpacingStyle _ x y) ->
805+ case found.maybeSpacing of
808+ | maybeSpacing = Just y
809+ , adjustedAttributes = attr :: found.adjustedAttributes
816+ { found | adjustedAttributes = attr :: found.adjustedAttributes }
818+ { maybePadding = Nothing
819+ , heightContent = Nothing
820+ , maybeBorder = Nothing
821+ , maybeSpacing = Nothing
822+ , adjustedAttributes = []
825+ -- NOTE: This is where default text spacing is set
827+ Maybe.withDefault 5 maybeSpacing
830+ , [ spellcheck textInput.spellchecked
831+ , Internal.htmlClass classes.inputMultiline
832+ , Maybe.map autofill textInput.autofill
833+ |> Maybe.withDefault Internal.NoAttribute
834+ , case maybePadding of
836+ Internal.NoAttribute
926− TextArea ->
838+ Just (Padding t r b l) ->
927− Internal.NodeName "textarea"
839+ Element.paddingEach
928− )
840+ { top = max 0 (t - (spacing // 2))
929− ((case textInput.type_ of
841+ , bottom = max 0 (b - (spacing // 2))
930− TextInputNode inputType ->
842+ , left = l
931− -- Note: Due to a weird edgecase in...Edge...
843+ , right = r
932− -- `type` needs to come _before_ `value`
844+ }
933− -- More reading: https://github.com/mdgriffith/elm-ui/pull/94/commits/4f493a27001ccc3cf1f2baa82e092c35d3811876
845+ , case heightContent of
934− [ Internal.Attr (Html.Attributes.type_ inputType)
846+ Nothing ->
935− , Internal.htmlClass classes.inputText
847+ Internal.NoAttribute
938− TextArea ->
849+ Just True ->
939− [ Element.clip
850+ textHeightContent textOptions.text spacing maybePadding maybeBorder
940− , Element.height Element.fill
941− , Internal.htmlClass classes.inputMultiline
942− , calcMoveToCompensateForPadding withDefaults
944− -- The only reason we do this padding trick is so that when the user clicks in the padding,
945− -- that the cursor will reset correctly.
946− -- This could probably be combined with the above `calcMoveToCompensateForPadding`
947− , Element.paddingEach parentPadding
948− , Internal.Attr (Html.Attributes.style "margin" (renderBox (negateBox parentPadding)))
949− , Internal.Attr (Html.Attributes.style "box-sizing" "content-box")
952− ++ [ value textOptions.text
953− , Internal.Attr (Html.Events.onInput textOptions.onChange)
954− , hiddenLabelAttribute textOptions.label
955− , spellcheck textInput.spellchecked
956− , Maybe.map autofill textInput.autofill
957− |> Maybe.withDefault Internal.NoAttribute
959− ++ redistributed.input
961− (Internal.Unkeyed [])
963− wrappedInput =
852+ Just False ->
964− case textInput.type_ of
966− -- textarea with height-content means that
967− -- the input element is rendered `inFront` with a transparent background
968− -- Then the input text is rendered as the space filling element.
972− ((if heightConstrained then
973− (::) Element.scrollbarY
978− [ Element.width Element.fill
979− , if List.any hasFocusStyle withDefaults then
980 Internal.NoAttribute
853 Internal.NoAttribute
855+ ++ adjustedAttributes
856+ , [ Internal.unstyled (Html.text textOptions.text) ]
982− else
859+ heightFillFromChild =
983− Internal.htmlClass classes.focusedWithin
860+ Internal.get attributes <|
984− , Internal.htmlClass classes.inputMultilineWrapper
861+ \attr ->
986− ++ redistributed.parent
863+ Internal.Height (Internal.Fill _) ->
990− Internal.asParagraph
992− (Element.width Element.fill
993− :: Element.height Element.fill
994− :: Element.inFront inputElement
995− :: Internal.htmlClass classes.inputMultilineParent
996− :: redistributed.wrapper
999− (if textOptions.text == "" then
1000− case textOptions.placeholder of
1002− -- Without this, firefox will make the text area lose focus
1003− -- if the input is empty and you mash the keyboard
1004− [ Element.text "\u{00A0}"
1008− [ renderPlaceholder place
1010− (textOptions.text == "")
1014− [ Internal.unstyled
1015− (Html.span [ Html.Attributes.class classes.inputMultilineFiller ]
1016− -- We append a non-breaking space to the end of the content so that newlines don't get chomped.
1017− [ Html.text (textOptions.text ++ "\u{00A0}")
1026− TextInputNode inputType ->
866+ _ ->
1027− Internal.element
867+ False
1030− (Element.width Element.fill
1031− :: (if List.any hasFocusStyle withDefaults then
1032− Internal.NoAttribute
1034− else
869+ attributesFromChild =
1035− Internal.htmlClass classes.focusedWithin
870+ Internal.get attributes <|
873+ Internal.Width (Internal.Fill _) ->
876+ Internal.Height (Internal.Fill _) ->
879+ Internal.AlignX _ ->
882+ Internal.AlignY _ ->
885+ Internal.StyleClass _ (Internal.SpacingStyle _ _ _) ->
888+ Internal.StyleClass _ (Internal.FontSize _) ->
891+ Internal.StyleClass _ (Internal.FontFamily _ _) ->
898+ Internal.get attributes <|
901+ Internal.Nearby _ _ ->
908+ Internal.get attributes <|
911+ Internal.StyleClass _ (Internal.PaddingStyle _ _ _ _ _) ->
921+ (Element.width Element.fill
1037− :: List.concat
922+ :: List.concat
1038− [ redistributed.parent
923+ [ nearbys
924+ , heightFillFromChild
1039− , case textOptions.placeholder of
925+ , case textOptions.placeholder of
1040− Nothing ->
926+ Nothing ->
1043− Just place ->
929+ Just (Placeholder placeholderAttrs placeholderEl) ->
1044− [ Element.behindContent
930+ [ Element.inFront
1045− (renderPlaceholder place redistributed.cover (textOptions.text == ""))
931+ (Element.el
1046− ]
932+ (defaultTextPadding
934+ ++ [ Font.color charcoal
935+ , Internal.htmlClass (classes.noTextSelection ++ " " ++ classes.passPointerEvents)
936+ , Border.color (Element.rgba 0 0 0 0)
937+ , Background.color (Element.rgba 0 0 0 0)
938+ , Element.height Element.fill
939+ , Element.width Element.fill
941+ (if textOptions.text == "" then
958+ (Internal.NodeName inputNode)
960+ [ [ focusDefault attrs
961+ , hiddenLabelAttribute textOptions.label
1049− (Internal.Unkeyed [ inputElement ])
967+ (Internal.Unkeyed inputChildren)
1051 applyLabel
971 applyLabel
1052 (Internal.Class Flag.cursor classes.cursorText
972 (Internal.Class Flag.cursor classes.cursorText
@@ -1058,348 +978,45 @@ textHelper textInput attrs textOptions =
1060 :: Region.announce
980 :: Region.announce
1061− :: redistributed.fullParent
981+ :: attributesFromChild
1063 textOptions.label
983 textOptions.label
1064− wrappedInput
984+ inputElement
1069− Internal.Height h ->
1077− { top = negate box.top
1078− , right = negate box.right
1079− , bottom = negate box.bottom
1080− , left = negate box.left
1084−renderBox { top, right, bottom, left } =
987+textHeightContent textValue spacing maybePadding maybeBorder =
1087− ++ String.fromInt right
1089− ++ String.fromInt bottom
1091− ++ String.fromInt left
1095−renderPlaceholder (Placeholder placeholderAttrs placeholderEl) forPlaceholder on =
1098− ++ [ Font.color charcoal
1099− , Internal.htmlClass (classes.noTextSelection ++ " " ++ classes.passPointerEvents)
1101− , Border.color (Element.rgba 0 0 0 0)
1102− , Background.color (Element.rgba 0 0 0 0)
1103− , Element.height Element.fill
1104− , Element.width Element.fill
1113− ++ placeholderAttrs
1118−{-| Because textareas are now shadowed, where they're rendered twice,
1119−we to move the literal text area up because spacing is based on line height.
1121−calcMoveToCompensateForPadding : List (Attribute msg) -> Attribute msg
1122−calcMoveToCompensateForPadding attrs =
1124− gatherSpacing attr found =
989+ newlineCount =
1125− case attr of
990+ String.lines textValue
1126− Internal.StyleClass _ (Internal.SpacingStyle _ x y) ->
991+ |> List.length
1127− case found of
992+ |> (\x ->
1128− Nothing ->
993+ if x < 1 then
1135− found
1000+ topBottom (Padding t _ b _) =
1003+ additionalSpacing =
1004+ ((newlineCount - 1) * spacing)
1005+ + Maybe.withDefault 0 (Maybe.map topBottom maybePadding)
1006+ + Maybe.withDefault 0 (Maybe.map topBottom maybeBorder)
1008+ heightValue count =
1010+ ++ String.fromInt count
1012+ ++ String.fromInt additionalSpacing
1013+ ++ "px) !important"
1137− case List.foldr gatherSpacing Nothing attrs of
1139− Internal.NoAttribute
1142− Element.moveUp (toFloat (floor (toFloat vSpace / 2)))
1145−{-| Given the list of attributes provided to `Input.multiline` or `Input.text`,
1147−redistribute them to the parent, the input, or the cover.
1149− - fullParent -> Wrapper around label and input
1150− - parent -> parent of wrapper
1151− - wrapper -> the element that is here to take up space.
1152− - cover -> things like placeholders or text areas which are layered on top of input.
1153− - input -> actual input element
1159− -> List (Attribute msg)
1161− { fullParent : List (Attribute msg)
1162− , parent : List (Attribute msg)
1163− , wrapper : List (Attribute msg)
1164− , input : List (Attribute msg)
1165− , cover : List (Attribute msg)
1167−redistribute isMultiline stacked attrs =
1168− List.foldl (redistributeOver isMultiline stacked)
1177− { parent = List.reverse redist.parent
1178− , fullParent = List.reverse redist.fullParent
1179− , wrapper = List.reverse redist.wrapper
1180− , input = List.reverse redist.input
1181− , cover = List.reverse redist.cover
1191− Internal.Content ->
1197− Internal.Min _ l ->
1200− Internal.Max _ l ->
1206− Internal.Content ->
1215− Internal.Min _ l ->
1218− Internal.Max _ l ->
1224− Internal.Content ->
1233− Internal.Min _ l ->
1236− Internal.Max _ l ->
1242− Internal.Content ->
1251− Internal.Min _ l ->
1254− Internal.Max _ l ->
1258−{-| isStacked means that the label is above or below
1260−redistributeOver isMultiline stacked attr els =
1262− Internal.Nearby _ _ ->
1263− { els | parent = attr :: els.parent }
1265− Internal.Width width ->
1266− if isFill width then
1268− | fullParent = attr :: els.fullParent
1269− , parent = attr :: els.parent
1270− , input = attr :: els.input
1273− else if stacked then
1275− | fullParent = attr :: els.fullParent
1280− | parent = attr :: els.parent
1283− Internal.Height height ->
1284− if not stacked then
1286− | fullParent = attr :: els.fullParent
1287− , parent = attr :: els.parent
1290− else if isFill height then
1292− | fullParent = attr :: els.fullParent
1293− , parent = attr :: els.parent
1296− else if isPixel height then
1297− { els | parent = attr :: els.parent }
1301− | parent = attr :: els.parent
1304− Internal.AlignX _ ->
1305− { els | fullParent = attr :: els.fullParent }
1307− Internal.AlignY _ ->
1308− { els | fullParent = attr :: els.fullParent }
1310− Internal.StyleClass _ (Internal.SpacingStyle _ _ _) ->
1312− | fullParent = attr :: els.fullParent
1313− , parent = attr :: els.parent
1314− , input = attr :: els.input
1315− , wrapper = attr :: els.wrapper
1318− Internal.StyleClass cls (Internal.PaddingStyle pad t r b l) ->
1319− if isMultiline then
1321− | parent = attr :: els.parent
1322− , cover = attr :: els.cover
1328− Element.htmlAttribute
1329− (Html.Attributes.style
1331− ("calc(1.0em + " ++ String.fromFloat (2 * min t b) ++ "px)")
1335− Element.htmlAttribute
1336− (Html.Attributes.style
1338− ("calc(1.0em + " ++ String.fromFloat (2 * min t b) ++ "px)")
1347− reducedVerticalPadding =
1348− Internal.StyleClass Flag.padding
1015+ Internal.StyleClass Flag.heightTextAreaContent
1349− (Internal.PaddingStyle
1016+ (Internal.Single ("textarea-height-" ++ String.fromInt newlineCount)
1350− (Internal.paddingNameFloat
1017+ "height"
1351− newTop
1018+ (heightValue newlineCount)
1363− | parent = reducedVerticalPadding :: els.parent
1364− , input = newHeight :: newLineHeight :: els.input
1365− , cover = attr :: els.cover
1368− Internal.StyleClass _ (Internal.BorderWidth _ _ _ _ _) ->
1370− | parent = attr :: els.parent
1371− , cover = attr :: els.cover
1374− Internal.StyleClass _ (Internal.Transform _) ->
1376− | parent = attr :: els.parent
1377− , cover = attr :: els.cover
1380− Internal.StyleClass _ (Internal.FontSize _) ->
1381− { els | fullParent = attr :: els.fullParent }
1383− Internal.StyleClass _ (Internal.FontFamily _ _) ->
1384− { els | fullParent = attr :: els.fullParent }
1386− Internal.StyleClass flag cls ->
1387− { els | parent = attr :: els.parent }
1389− Internal.NoAttribute ->
1393− { els | input = attr :: els.input }
1395− Internal.Describe _ ->
1396− { els | input = attr :: els.input }
1398− Internal.Class _ _ ->
1399− { els | parent = attr :: els.parent }
1401− Internal.TransformComponent _ _ ->
1402− { els | input = attr :: els.input }
@@ -1461,7 +1078,7 @@ search =
1462It's `newPassword` instead of just `password` because it gives the browser a hint on what type of password input it is.
1079It's `newPassword` instead of just `password` because it gives the browser a hint on what type of password input it is.
1464−A password takes all the arguments a normal `Input.text` would, and also **show**, which will remove the password mask (e.g. `****` vs `pass1234`)
1081+A password takes all the arguments a normal `Input.text` would, and also `show`, which will remove the password mask (e.g. `****` vs `pass1234`)
1467newPassword :
1084newPassword :
@@ -1561,13 +1178,7 @@ email =
1564−{-| A multiline text input.
1566−By default it will have a minimum height of one line and resize based on it's contents.
1568−Use `Element.spacing` to change its line-height.
1571multiline :
1182multiline :
1572 List (Attribute msg)
1183 List (Attribute msg)
@@ -1628,32 +1239,33 @@ applyLabel attrs label input =
1628 Internal.element
1239 Internal.element
1629 Internal.asColumn
1240 Internal.asColumn
1630 (Internal.NodeName "label")
1241 (Internal.NodeName "label")
1631− (Internal.htmlClass classes.inputLabel :: attrs)
1242+ attrs
1632 (Internal.Unkeyed [ labelElement, input ])
1243 (Internal.Unkeyed [ labelElement, input ])
1634 Below ->
1245 Below ->
1635 Internal.element
1246 Internal.element
1636 Internal.asColumn
1247 Internal.asColumn
1637 (Internal.NodeName "label")
1248 (Internal.NodeName "label")
1638− (Internal.htmlClass classes.inputLabel :: attrs)
1249+ attrs
1639 (Internal.Unkeyed [ input, labelElement ])
1250 (Internal.Unkeyed [ input, labelElement ])
1641 OnRight ->
1252 OnRight ->
1642 Internal.element
1253 Internal.element
1643 Internal.asRow
1254 Internal.asRow
1644 (Internal.NodeName "label")
1255 (Internal.NodeName "label")
1645− (Internal.htmlClass classes.inputLabel :: attrs)
1256+ attrs
1646 (Internal.Unkeyed [ input, labelElement ])
1257 (Internal.Unkeyed [ input, labelElement ])
1648 OnLeft ->
1259 OnLeft ->
1649 Internal.element
1260 Internal.element
1650 Internal.asRow
1261 Internal.asRow
1651 (Internal.NodeName "label")
1262 (Internal.NodeName "label")
1652− (Internal.htmlClass classes.inputLabel :: attrs)
1263+ attrs
1653 (Internal.Unkeyed [ labelElement, input ])
1264 (Internal.Unkeyed [ labelElement, input ])
1267+{-| Add choices to your radio and select menus.
1657type Option value msg
1269type Option value msg
1658 = Option value (OptionState -> Element msg)
1270 = Option value (OptionState -> Element msg)
@@ -1665,21 +1277,35 @@ type OptionState
1665 | Selected
1277 | Selected
1668−{-| Add a choice to your radio element. This will be rendered with the default radio icon.
1670option : value -> Element msg -> Option value msg
1281option : value -> Element msg -> Option value msg
1671option val txt =
1282option val txt =
1672 Option val (defaultRadioOption txt)
1283 Option val (defaultRadioOption txt)
1675−{-| Customize exactly what your radio option should look like in different states.
1677optionWith : value -> (OptionState -> Element msg) -> Option value msg
1287optionWith : value -> (OptionState -> Element msg) -> Option value msg
1678optionWith val view =
1288optionWith val view =
1679 Option val view
1289 Option val view
1298+ { onChange = ChooseLunch
1299+ , selected = Just model.lunch
1300+ , label = Input.labelAbove [] (text "Lunch")
1302+ [ Input.option Burrito (text "Burrito")
1303+ , Input.option Taco (text "Taco!")
1304+ , Input.option Gyro (text "Gyro")
1684 List (Attribute msg)
1310 List (Attribute msg)
@@ -2105,11 +1731,7 @@ onKeyLookup lookup =
2105 Json.field "key" Json.string
1731 Json.field "key" Json.string
2106 |> Json.andThen decode
1732 |> Json.andThen decode
2108− -- We generally want these attached to the keydown event becaues it allows us to prevent default on things like spacebar scrolling the page.
2109− -- https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/button_role
2110− Internal.Attr <|
1734+ Internal.Attr <| Html.Events.on "keyup" isKey
2111− Html.Events.preventDefaultOn "keydown"
2112− (Json.map (\fired -> ( fired, True )) isKey)
@@ -2124,6 +1746,17 @@ onFocusIn msg =
2124 Internal.Attr <| Html.Events.on "focusin" (Json.succeed msg)
1746 Internal.Attr <| Html.Events.on "focusin" (Json.succeed msg)
1749+type_ : String -> Attribute msg
1751+ Internal.Attr << Html.Attributes.type_
1755+-- checked : Bool -> Attribute msg
1757+-- Internal.Attr << Html.Attributes.checked
2127selected : Bool -> Attribute msg
1760selected : Bool -> Attribute msg
2128selected =
1761selected =
2129 Internal.Attr << Html.Attributes.selected
1762 Internal.Attr << Html.Attributes.selected
@@ -2164,11 +1797,7 @@ autofill =
2164 Internal.Attr << Html.Attributes.attribute "autocomplete"
1797 Internal.Attr << Html.Attributes.attribute "autocomplete"
2167−{-| Attach this attribute to any `Input` that you would like to be automatically focused when the page loads.
2169−You should only have a maximum of one per page.
2172focusedOnLoad : Attribute msg
1801focusedOnLoad : Attribute msg
2173focusedOnLoad =
1802focusedOnLoad =
2174 Internal.Attr <| Html.Attributes.autofocus True
1803 Internal.Attr <| Html.Attributes.autofocus True
@@ -2185,9 +1814,8 @@ defaultTextBoxStyle =
2185 , Border.color darkGrey
1814 , Border.color darkGrey
2186 , Background.color white
1815 , Background.color white
2187 , Border.width 1
1816 , Border.width 1
2188− , Element.spacing 5
1817+ , Element.spacing 3
2189 , Element.width Element.fill
1818 , Element.width Element.fill
2190− , Element.height Element.shrink
@@ -2196,17 +1824,12 @@ defaultTextPadding =
2196 Element.paddingXY 12 12
1824 Element.paddingXY 12 12
2199−{-| The blue default checked box icon.
2201−You'll likely want to make your own checkbox at some point that fits your design.
2204defaultCheckbox : Bool -> Element msg
1828defaultCheckbox : Bool -> Element msg
2205defaultCheckbox checked =
1829defaultCheckbox checked =
2206 Element.el
1830 Element.el
2207 [ Internal.htmlClass "focusable"
1831 [ Internal.htmlClass "focusable"
2208− , Element.width
1832+ , Element.width (Element.px 14)
2210 , Element.height (Element.px 14)
1833 , Element.height (Element.px 14)
2211 , Font.color white
1834 , Font.color white
2212 , Element.centerY
1835 , Element.centerY
@@ -2219,7 +1842,7 @@ defaultCheckbox checked =
2221 Element.rgb (211 / 255) (211 / 255) (211 / 255)
1844 Element.rgb (211 / 255) (211 / 255) (211 / 255)
2222− , Border.shadow
1845+ , Border.shadow <|
2223 { offset = ( 0, 0 )
1846 { offset = ( 0, 0 )
2224 , blur = 1
1847 , blur = 1
2225 , size = 1
1848 , size = 1
@@ -2242,8 +1865,9 @@ defaultCheckbox checked =
2245− , Element.inFront
1868+ ]
2246− (Element.el
1870+ Element.el
2247 [ Border.color white
1871 [ Border.color white
2248 , Element.height (Element.px 6)
1872 , Element.height (Element.px 6)
2249 , Element.width (Element.px 9)
1873 , Element.width (Element.px 9)
@@ -2251,7 +1875,6 @@ defaultCheckbox checked =
2251 , Element.centerX
1875 , Element.centerX
2252 , Element.centerY
1876 , Element.centerY
2253 , Element.moveUp 1
1877 , Element.moveUp 1
2254− , Element.transparent (not checked)
2255 , Border.widthEach
1878 , Border.widthEach
2256 { top = 0
1879 { top = 0
2257 , left = 2
1880 , left = 2
@@ -2260,6 +1883,7 @@ defaultCheckbox checked =
2262 Element.none
1885 Element.none
2265− Element.none
1888+ Element.none