git.iko.soy/typeable/elm-ui
on master help sign in
15 files changed+419−50
since splitsnapshots
unifiedsplit
README.md+4 elm.json+1−1 src/Element/Input.elm+42−24 src/Internal/Model.elm+9−3 src/Internal/Style.elm+20−5 tests-rendering/cases/open/LabelledInputAlignRight.elm+28 tests-rendering/cases/open/NearbyElementBordersOverlap.elm+46 tests-rendering/cases/resolved/Images/ImageRegression.elm+63 tests-rendering/cases/resolved/Images/ImageRegression2.elm+19 tests-rendering/cases/resolved/Misc/ImageSizing.elm → tests-rendering/cases/resolved/Images/ImageSizing.elm+7−3 tests-rendering/cases/resolved/Layout/Columns/DistributeHeight.elm+46 tests-rendering/cases/resolved/Layout/Columns/DistributeHeightCorrectly2.elm+86 tests-rendering/cases/resolved/Layout/Columns/DoNotCollapseBelow0.elm+48 tests-rendering/cases/resolved/Layout/SafariTwo.elm → tests-rendering/cases/resolved/Layout/Columns/SafariTwo.elm tests-rendering/cases/resolved/Layout/SafariColumnBug.elm−14
README.md+4
@@ -66,6 +66,10 @@ The work is based off of a rewrite of the [Style Elements](https://github.com/md
6666
6767The community around `elm-ui` is maintaining a collection of examples called the [elm-ui-cookbook](https://github.com/rofrol/elm-ui-cookbook). If you are just starting out with `elm-ui`, or get stuck on specific things, this can be a great resource.
6868
69+## Notes
70+
71+Make sure to have `<!DOCTYPE html>` on top of your application; otherwise, things might get messed up in some browsers.
72+
6973## Contributing
7074
7175Want to help out fixing bugs or reporting issues?
elm.json+1−1
@@ -3,7 +3,7 @@
33 "name": "mdgriffith/elm-ui",
44 "summary": "Layout and style that's easy to refactor, all without thinking about CSS.",
55 "license": "BSD-3-Clause",
6− "version": "1.1.5",
6+ "version": "1.1.8",
77 "exposed-modules": [
88 "Element",
99 "Element.Input",
src/Element/Input.elm+42−24
@@ -369,7 +369,17 @@ button attrs { onPress, label } =
369369
370370 Just msg ->
371371 Events.onClick msg
372− :: onEnter msg
372+ :: onKeyLookup
373+ (\code ->
374+ if code == enter then
375+ Just msg
376+
377+ else if code == space then
378+ Just msg
379+
380+ else
381+ Nothing
382+ )
373383 :: attrs
374384 )
375385 )
@@ -447,22 +457,24 @@ checkbox attrs { label, icon, checked, onChange } =
447457 ]
448458 ++ attrs
449459 in
450− applyLabel attributes
451− label
452− (Internal.element
453− Internal.asEl
454− Internal.div
455− [ Internal.Attr <|
456− Html.Attributes.attribute "role" "checkbox"
457− , Internal.Attr <|
458− Html.Attributes.attribute "aria-checked" <|
460+ applyLabel
461+ (Internal.Attr (Html.Attributes.attribute "role" "checkbox")
462+ :: Internal.Attr
463+ (Html.Attributes.attribute "aria-checked" <|
459464 if checked then
460465 "true"
461466
462467 else
463468 "false"
464− , hiddenLabelAttribute label
465− , Element.centerY
469+ )
470+ :: hiddenLabelAttribute label
471+ :: attributes
472+ )
473+ label
474+ (Internal.element
475+ Internal.asEl
476+ Internal.div
477+ [ Element.centerY
466478 , Element.height Element.fill
467479 , Element.width Element.shrink
468480 ]
@@ -701,7 +713,7 @@ slider attributes input =
701713 ("input[type=\"range\"]." ++ className ++ "::-ms-thumb")
702714 thumbShadowStyle
703715 )
704− , Internal.Attr (Html.Attributes.class (className ++ " focusable-parent"))
716+ , Internal.Attr (Html.Attributes.class (className ++ " ui-slide-bar focusable-parent"))
705717 , Internal.Attr
706718 (Html.Events.onInput
707719 (\str ->
@@ -767,10 +779,10 @@ slider attributes input =
767779 -- This is after `attributes` because the thumb should be in front of everything.
768780 ++ [ Element.behindContent <|
769781 if vertical then
770− viewVerticalThumb factor thumbAttributes trackWidth
782+ viewVerticalThumb factor (Internal.htmlClass "focusable-thumb" :: thumbAttributes) trackWidth
771783
772784 else
773− viewHorizontalThumb factor thumbAttributes trackHeight
785+ viewHorizontalThumb factor (Internal.htmlClass "focusable-thumb" :: thumbAttributes) trackHeight
774786 ]
775787 )
776788 Element.none
@@ -1553,6 +1565,8 @@ email =
15531565
15541566By default it will have a minimum height of one line and resize based on it's contents.
15551567
1568+Use `Element.spacing` to change its line-height.
1569+
15561570-}
15571571multiline :
15581572 List (Attribute msg)
@@ -2091,7 +2105,11 @@ onKeyLookup lookup =
20912105 Json.field "key" Json.string
20922106 |> Json.andThen decode
20932107 in
2094− Internal.Attr <| Html.Events.on "keyup" isKey
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 <|
2111+ Html.Events.preventDefaultOn "keydown"
2112+ (Json.map (\fired -> ( fired, True )) isKey)
20952113
20962114
20972115{-| -}
@@ -2187,7 +2205,8 @@ defaultCheckbox : Bool -> Element msg
21872205defaultCheckbox checked =
21882206 Element.el
21892207 [ Internal.htmlClass "focusable"
2190− , Element.width (Element.px 14)
2208+ , Element.width
2209+ (Element.px 14)
21912210 , Element.height (Element.px 14)
21922211 , Font.color white
21932212 , Element.centerY
@@ -2223,9 +2242,8 @@ defaultCheckbox checked =
22232242
22242243 else
22252244 1
2226− ]
2227− (if checked then
2228− Element.el
2245+ , Element.inFront
2246+ (Element.el
22292247 [ Border.color white
22302248 , Element.height (Element.px 6)
22312249 , Element.width (Element.px 9)
@@ -2233,6 +2251,7 @@ defaultCheckbox checked =
22332251 , Element.centerX
22342252 , Element.centerY
22352253 , Element.moveUp 1
2254+ , Element.transparent (not checked)
22362255 , Border.widthEach
22372256 { top = 0
22382257 , left = 2
@@ -2241,7 +2260,6 @@ defaultCheckbox checked =
22412260 }
22422261 ]
22432262 Element.none
2244−
2245− else
2246− Element.none
2247− )
2263+ )
2264+ ]
2265+ Element.none
src/Internal/Model.elm+9−3
@@ -1478,7 +1478,9 @@ renderHeight h =
14781478 Single
14791479 cls
14801480 "min-height"
1481− (String.fromInt minSize ++ "px")
1481+ -- This needs to be !important because we're using `min-height: min-content`
1482+ -- to correct for safari's incorrect implementation of flexbox.
1483+ (String.fromInt minSize ++ "px !important")
14821484
14831485 ( newFlag, newAttrs, newStyle ) =
14841486 renderHeight len
@@ -2242,7 +2244,11 @@ renderFocusStyle focus =
22422244 , Just <| Property "outline" "none"
22432245 ]
22442246 )
2245− , Style (Internal.Style.dot classes.any ++ ":focus .focusable, " ++ Internal.Style.dot classes.any ++ ".focusable:focus")
2247+ , Style
2248+ ((Internal.Style.dot classes.any ++ ":focus .focusable, ")
2249+ ++ (Internal.Style.dot classes.any ++ ".focusable:focus, ")
2250+ ++ (".ui-slide-bar:focus + " ++ Internal.Style.dot classes.any ++ " .focusable-thumb")
2251+ )
22462252 (List.filterMap identity
22472253 [ Maybe.map (\color -> Property "border-color" (formatColor color)) focus.borderColor
22482254 , Maybe.map (\color -> Property "background-color" (formatColor color)) focus.backgroundColor
@@ -2650,7 +2656,7 @@ renderStyle options maybePseudo selector props =
26502656 , (selector ++ "-fs:focus-within {")
26512657 ++ renderedProps
26522658 ++ "\n}"
2653− , (".focusable-parent:focus ~ " ++ "." ++ classes.any ++ " " ++ selector ++ "-fs {")
2659+ , (".ui-slide-bar:focus + " ++ Internal.Style.dot classes.any ++ " .focusable-thumb" ++ selector ++ "-fs {")
26542660 ++ renderedProps
26552661 ++ "\n}"
26562662 ]
src/Internal/Style.elm+20−5
@@ -961,10 +961,17 @@ baseSheet =
961961 ]
962962 , Class (dot classes.any ++ dot classes.single ++ dot classes.imageContainer)
963963 [ Prop "display" "block"
964− , Child "img"
965− [ Prop "max-height" "100%"
966− , Prop "max-width" "100%"
967− , Prop "object-fit" "cover"
964+ , Descriptor (dot classes.heightFill)
965+ [ Child "img"
966+ [ Prop "max-height" "100%"
967+ , Prop "object-fit" "cover"
968+ ]
969+ ]
970+ , Descriptor (dot classes.widthFill)
971+ [ Child "img"
972+ [ Prop "max-width" "100%"
973+ , Prop "object-fit" "cover"
974+ ]
968975 ]
969976 ]
970977 , Class (dot classes.any ++ ":focus")
@@ -1377,7 +1384,15 @@ baseSheet =
13771384 -- This apparently is a different story for columns.
13781385 -- Safari has an issue if this is flex-basis: 0%, as it goes entirely to 0,
13791386 -- instead of the expected content size.
1380− [ Prop "flex-basis" "auto"
1387+ -- So we add `min-height: min-content`, which isn't supported by IE, but works for all other browsers!
1388+ -- Separately, 0% is different than 0px, but only for columns
1389+ -- In columns, 0% will actually be calculated as `auto` for columns
1390+ -- So, 0px is the one we want.
1391+ [ Prop "flex-basis" "0px"
1392+ , Prop "min-height" "min-content"
1393+ , Descriptor (dot classes.heightExact)
1394+ [ Prop "flex-basis" "auto"
1395+ ]
13811396 ]
13821397 , Child (dot classes.heightFill)
13831398 [ Prop "flex-grow" "100000"
tests-rendering/cases/open/LabelledInputAlignRight.elmnew file+28
@@ -0,0 +1,28 @@
1+module LabelledInputAlignRight exposing (view)
2+
3+import Testable.Element exposing (..)
4+import Testable.Element.Input as Input
5+
6+
7+view =
8+ layout [] <|
9+ column [ width fill ]
10+ [ Input.text
11+ [ width (px 200)
12+ , alignRight
13+ ]
14+ { onChange = always False
15+ , text = ""
16+ , placeholder = Nothing
17+ , label = Input.labelLeft [] (text "label")
18+ }
19+ , Input.text
20+ [ width (px 200)
21+ , alignRight
22+ ]
23+ { onChange = always False
24+ , text = ""
25+ , placeholder = Nothing
26+ , label = Input.labelHidden "label"
27+ }
28+ ]
tests-rendering/cases/open/NearbyElementBordersOverlap.elmnew file+46
@@ -0,0 +1,46 @@
1+module NearbyElementBordersOverlap exposing (view)
2+
3+{-| Elements placed with onLeft, onRight, above & below overlap main element's border
4+
5+
6+# inFront elements with width fill are contained within the parent's border
7+
8+<https://github.com/mdgriffith/elm-ui/issues/223>
9+
10+In addition to the overlap, it affects layout in unexpected ways: eg if the elements
11+are the same height, onLeft and onRight elements will be vertically offset
12+from the main element.
13+
14+-}
15+
16+import Testable.Element exposing (..)
17+import Testable.Element.Border as Border
18+
19+
20+blue =
21+ rgb 0 0 1
22+
23+
24+green =
25+ rgb 0 1 0
26+
27+
28+grey =
29+ rgb 0.5 0.5 0.5
30+
31+
32+view =
33+ layout [ width fill, height fill ] <|
34+ el
35+ [ centerX
36+ , centerY
37+ , Border.width 10
38+ , Border.color green
39+ , padding 50
40+ , above <| el [ Border.color grey, Border.width 10 ] <| text "above"
41+ , below <| el [ Border.color grey, Border.width 10 ] <| text "below"
42+ , onRight <| el [ Border.color blue, Border.width 10 ] <| text "onRight"
43+ , onLeft <| el [ Border.color blue, Border.width 10 ] <| text "onLeft"
44+ ]
45+ <|
46+ text "Centre"
tests-rendering/cases/resolved/Images/ImageRegression.elmnew file+63
@@ -0,0 +1,63 @@
1+module ImageRegression exposing (main)
2+
3+{-| <https://github.com/mdgriffith/elm-ui/issues/232>
4+-}
5+
6+import Browser
7+import Element exposing (Element, centerX, clipX, el, image, px, rgb255, row, shrink, width)
8+import Element.Background as Background
9+import Html exposing (Html, button, div, text)
10+import Html.Events exposing (onClick)
11+
12+
13+type alias Model =
14+ Int
15+
16+
17+type Msg
18+ = NoOp
19+
20+
21+update : Msg -> Model -> Model
22+update msg model =
23+ model
24+
25+
26+view : Model -> Html Msg
27+view model =
28+ Element.layout [] <|
29+ row
30+ [ centerX
31+ , width shrink
32+ , Background.color <| rgb255 255 255 255
33+ ]
34+ [ viewCard "qs" True
35+ , viewCard "ah" False
36+ ]
37+
38+
39+main : Program () Model Msg
40+main =
41+ Browser.sandbox
42+ { init = 0
43+ , view = view
44+ , update = update
45+ }
46+
47+
48+viewCard : String -> Bool -> Element Msg
49+viewCard card bool =
50+ let
51+ source =
52+ "https://hearts-bawolk.herokuapp.com/static/cards/" ++ card ++ ".png"
53+
54+ overlapStyles =
55+ if bool then
56+ [ width (px 50)
57+ , clipX
58+ ]
59+
60+ else
61+ []
62+ in
63+ el overlapStyles (image [] { src = source, description = "" })
tests-rendering/cases/resolved/Images/ImageRegression2.elmnew file+19
@@ -0,0 +1,19 @@
1+module ImageRegression2 exposing (main)
2+
3+{-| <https://github.com/mdgriffith/elm-ui/issues/228>
4+-}
5+
6+import Element exposing (..)
7+
8+
9+main =
10+ Element.layout []
11+ (Element.row [ width fill, height fill, explain Debug.todo ]
12+ [ text "BEFORE"
13+ , image []
14+ { src = "https://placekitten.com/300/200"
15+ , description = "kitten"
16+ }
17+ , text "AFTER"
18+ ]
19+ )
tests-rendering/cases/resolved/Misc/ImageSizing.elm → tests-rendering/cases/resolved/Images/ImageSizing.elmrenamed+7−3
@@ -1,6 +1,9 @@
11module ImageSizing exposing (main)
22
3−import Element as E exposing (column, el, row, text)
3+{-| <https://github.com/mdgriffith/elm-ui/issues/62>
4+-}
5+
6+import Element as E exposing (column, el, px, row, text)
47import Element.Border as Border
58import Element.Font as Font
69import Html exposing (Html)
@@ -11,8 +14,9 @@ main =
1114 E.layout [ E.height E.fill, Border.width 5, E.explain Debug.todo ] <|
1215 E.image
1316 [ -- E.height (E.px 500)
14− E.width E.fill
15− , E.height E.fill
17+ -- ,
18+ -- E.width E.fill
19+ E.height E.fill
1620 ]
1721 -- <| px 500 ]
1822 { src = "http://bburdette.github.io/music-reader.png"
tests-rendering/cases/resolved/Layout/Columns/DistributeHeight.elmnew file+46
@@ -0,0 +1,46 @@
1+module DistributeHeight exposing (main)
2+
3+import Browser
4+import Element exposing (column, el, fill, fillPortion, height, minimum, none, px, rgb, row, text, width)
5+import Element.Background as Bg
6+import Html as Html exposing (Html)
7+
8+
9+type alias Model =
10+ ()
11+
12+
13+update : msg -> Model -> Model
14+update _ model =
15+ model
16+
17+
18+view : model -> Html msg
19+view _ =
20+ Element.layout [ height fill, width fill ] <|
21+ column [ height fill, width fill ]
22+ [ row
23+ [ height
24+ fill
25+ , width fill
26+ , Bg.color <| rgb 1 0 0
27+ ]
28+ [ el
29+ [ height <| px 200
30+ , width fill
31+ , Bg.color <| rgb 1 0 1
32+ ]
33+ (text "Helloooo!")
34+ ]
35+ , row [ height fill, width fill, Bg.color <| rgb 0 1 0 ]
36+ [ none ]
37+ ]
38+
39+
40+main : Program () Model msg
41+main =
42+ Browser.sandbox
43+ { init = ()
44+ , view = view
45+ , update = update
46+ }
tests-rendering/cases/resolved/Layout/Columns/DistributeHeightCorrectly2.elmnew file+86
@@ -0,0 +1,86 @@
1+module Other exposing (main)
2+
3+import Browser
4+import Element exposing (..)
5+import Element.Border as Border
6+import Element.Events as Events
7+import Html exposing (Html)
8+import Html.Attributes
9+
10+
11+type alias Model =
12+ { count : Int }
13+
14+
15+initialModel : Model
16+initialModel =
17+ { count = 0 }
18+
19+
20+type Msg
21+ = Increment
22+ | Decrement
23+
24+
25+update : Msg -> Model -> Model
26+update msg model =
27+ case msg of
28+ Increment ->
29+ { model | count = model.count + 1 }
30+
31+ Decrement ->
32+ { model | count = model.count - 1 }
33+
34+
35+view : Model -> Html Msg
36+view model =
37+ viewElements model
38+ |> layout []
39+
40+
41+viewElements : Model -> Element Msg
42+viewElements model =
43+ el [ height fill ] <|
44+ column [ height fill ]
45+ [ el
46+ [ height (fillPortion 1)
47+ ]
48+ <|
49+ viewCounter model
50+ , el
51+ [ height (fillPortion 2)
52+ ]
53+ <|
54+ viewCounters model
55+ ]
56+
57+
58+flexBasisZero : Element.Attribute msg
59+flexBasisZero =
60+ htmlAttribute (Html.Attributes.style "flex-basis" "0")
61+
62+
63+viewCounters : Model -> Element Msg
64+viewCounters model =
65+ column [ height fill ]
66+ (List.repeat model.count model
67+ |> List.map viewCounter
68+ )
69+
70+
71+viewCounter : Model -> Element Msg
72+viewCounter model =
73+ column [ width fill, height fill, Border.width 1, Border.dotted ]
74+ [ el [ Events.onClick Increment, Border.width 1, Border.rounded 3 ] <| text "+1"
75+ , el [] <| text <| String.fromInt model.count
76+ , el [ Events.onClick Decrement, Border.width 1, Border.rounded 3 ] <| text "-1"
77+ ]
78+
79+
80+main : Program () Model Msg
81+main =
82+ Browser.sandbox
83+ { init = initialModel
84+ , view = view
85+ , update = update
86+ }
tests-rendering/cases/resolved/Layout/Columns/DoNotCollapseBelow0.elmnew file+48
@@ -0,0 +1,48 @@
1+module DoNotCollapseBelow0 exposing (main)
2+
3+{-|
4+
5+
6+# Safari bug for `el` heigh calculation in combination with `height fill`
7+
8+The problem appears to be that the height of the first el is 0, and therefore the second
9+text is rendered on the first.
10+
11+Versions
12+
13+OS: macOS Mojave 10.14.5
14+Browser: Safari
15+Browser Version: 12.1.1 (14607.2.6.1.1)
16+Elm Version: 0.19
17+Elm UI Version: 1.1.5
18+
19+<https://github.com/mdgriffith/elm-ui/issues/147>
20+
21+I was able to pinpoint the issue using git bisect to this fd08f1a commit, which lines up.
22+
23+<https://github.com/mdgriffith/elm-ui/commit/fd08f1a953484ba96f2d05037d4f208eab351514>
24+
25+-}
26+
27+import Browser
28+import Element exposing (column, el, fill, height, layout, scrollbarY, text)
29+import Html exposing (Html)
30+
31+
32+view : () -> Html ()
33+view () =
34+ layout [ height fill ] <|
35+ column
36+ [ height fill ]
37+ [ el [] <| text "Element that Safari gives height 0, if inside an el and not just text."
38+ , text "Text below the el above"
39+ ]
40+
41+
42+main : Program () () ()
43+main =
44+ Browser.sandbox
45+ { init = ()
46+ , view = view
47+ , update = \() () -> ()
48+ }
tests-rendering/cases/resolved/Layout/SafariTwo.elm → tests-rendering/cases/resolved/Layout/Columns/SafariTwo.elmrenamed

The content is the same.

tests-rendering/cases/resolved/Layout/SafariColumnBug.elmdeleted−14
@@ -1,14 +0,0 @@
1−module SafariColumnBug exposing (main)
2−
3−import Browser
4−import Element exposing (column, el, fill, height, layout, scrollbarY, text)
5−import Html exposing (Html)
6−
7−
8−main =
9− layout [ height fill ] <|
10− column
11− [ height fill ]
12− [ el [] <| text "Element that Safari gives height 0, if inside an el and not just text."
13− , text "Text below the el above"
14− ]