├── .gitignore ├── LICENSE ├── README.md ├── dialog-infrontof-longcontent ├── elm.json └── src │ └── Main.elm ├── fixed-header-footer ├── elm.json └── src │ ├── Main.elm │ └── Main2.elm ├── flake.lock ├── flake.nix ├── highlight-table-rows ├── elm.json └── src │ └── Main.elm ├── local-font ├── elm.json ├── fonts │ └── GroovtasticRegular.ttf ├── index.html ├── src │ └── Main.elm └── test.sh ├── multiline.elm └── textinput-sized-to-contents ├── elm.json └── src └── Main.elm /.gitignore: -------------------------------------------------------------------------------- 1 | # elm-package generated files 2 | elm-stuff 3 | # elm-repl generated files 4 | repl-temp-* 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, bburdette 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # elm-ui-examples 2 | 3 | This is a collection of tweaks, hacks, and examples that I've found helpful (or at least interesting), while building things with elm-ui. 4 | 5 | Do you have some code that belongs here? Contributions welcome. Maybe some of these things will find their way into a more coherent form at some point. 6 | 7 | Also check out rofrol's repo here: https://github.com/rofrol/elm-ui-cookbook 8 | 9 | # simple dialog 10 | 11 | displaying elements centered in front of other elements: https://ellie-app.com/dYb8K3K38NPa1 12 | 13 | for an actual dialog you'd probably want to map the events from the background to a Noop msg. 14 | 15 | # code block 16 | 17 | I wanted a text area to display code - preserving whitespace but still doing line wrap. This works as expected, wrapping on spaces and then breaking words if necessary. https://ellie-app.com/dQTRJhnwV4za1 18 | 19 | here's a horizontally scrolling version: https://ellie-app.com/dRM6XjdZf3Xa1 20 | 21 | # (non) blinky fonts. 22 | 23 | Using Element.Font.external results in blinky UI due to font reloading. 24 | 25 | Here are a couple of ellies showing the blink problem and then fixing it by loading the font in the html. 26 | 27 | Before, with blinking: https://ellie-app.com/5JtKXXPmpKta1 28 | After, blinking fixed: https://ellie-app.com/5JvNzmS5Qxba1 29 | 30 | # toggle 31 | 32 | fancy animated toggle switch: https://ellie-app.com/85HbWTjCGWha1 33 | 34 | # tooltips 35 | 36 | tooltips plus some interesting 'never' usage: https://ellie-app.com/7R2VHTzHJYYa1 37 | 38 | # highlighting rows in elm-ui tables 39 | 40 | you have to track the highlight row in the model, and put mouse events in each cell: 41 | 42 | https://ellie-app.com/kSZPrk5BCRNa1 -------------------------------------------------------------------------------- /dialog-infrontof-longcontent/elm.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "application", 3 | "source-directories": [ 4 | "src" 5 | ], 6 | "elm-version": "0.19.0", 7 | "dependencies": { 8 | "direct": { 9 | "elm/browser": "1.0.1", 10 | "elm/core": "1.0.2", 11 | "elm/html": "1.0.0", 12 | "mdgriffith/elm-ui": "1.1.0" 13 | }, 14 | "indirect": { 15 | "elm/json": "1.1.3", 16 | "elm/time": "1.0.0", 17 | "elm/url": "1.0.0", 18 | "elm/virtual-dom": "1.0.2" 19 | } 20 | }, 21 | "test-dependencies": { 22 | "direct": {}, 23 | "indirect": {} 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /dialog-infrontof-longcontent/src/Main.elm: -------------------------------------------------------------------------------- 1 | 2 | module Main exposing (main) 3 | 4 | import Browser 5 | import Element exposing (..) 6 | import Element.Border as Border 7 | 8 | 9 | main = 10 | layout 11 | [ width fill 12 | , height fill 13 | , centerX 14 | , inFront <| 15 | column [ centerX, height fill, scrollbarY ] 16 | [ el [ height fill, scrollbarY ] none 17 | , column [ Border.width 1, scrollbarY ] <| 18 | List.map (\n -> text <| "long dialog" ++ String.fromInt n) 19 | (List.range 0 2) 20 | , el [ height fill ] none 21 | ] 22 | ] 23 | <| 24 | column [] <| 25 | List.map (\n -> text <| "long content" ++ String.fromInt n) 26 | (List.range 0 1000) 27 | -------------------------------------------------------------------------------- /fixed-header-footer/elm.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "application", 3 | "source-directories": [ 4 | "src" 5 | ], 6 | "elm-version": "0.19.0", 7 | "dependencies": { 8 | "direct": { 9 | "elm/browser": "1.0.0", 10 | "elm/core": "1.0.0", 11 | "elm/html": "1.0.0", 12 | "mdgriffith/elm-ui": "1.0.0" 13 | }, 14 | "indirect": { 15 | "elm/json": "1.0.0", 16 | "elm/time": "1.0.0", 17 | "elm/url": "1.0.0", 18 | "elm/virtual-dom": "1.0.0" 19 | } 20 | }, 21 | "test-dependencies": { 22 | "direct": {}, 23 | "indirect": {} 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /fixed-header-footer/src/Main.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (Model, Msgs(..), main, testview) 2 | 3 | import Browser 4 | import Browser.Events 5 | import Element exposing (..) 6 | import Element.Background as Background 7 | import Element.Border as Border 8 | import Element.Events exposing (onClick) 9 | import Element.Font as Font 10 | import Element.Input as Input 11 | 12 | 13 | type Msgs 14 | = Resize Int Int 15 | 16 | 17 | type alias Model = 18 | { size : ( Int, Int ) } 19 | 20 | 21 | main = 22 | Browser.element 23 | { init = \() -> ( { size = ( 0, 0 ) }, Cmd.none ) 24 | , update = \(Resize a b) mod -> ( { mod | size = ( a, b ) }, Cmd.none ) 25 | , view = \mod -> Element.layout [ height fill, width fill, Border.width 5 ] (testview (Tuple.second mod.size)) 26 | , subscriptions = \_ -> Browser.Events.onResize Resize 27 | } 28 | 29 | 30 | testview : Int -> Element Msgs 31 | testview h = 32 | column [ height fill, width fill ] 33 | -- height (px (h - 5)) ] 34 | -- column [ height fill ] 35 | [ row [ width fill ] [ text "header" ] 36 | , column [ scrollbarY, width fill ] (List.repeat 100 (text "content")) 37 | , row [ width fill ] [ text "footer" ] 38 | ] 39 | -------------------------------------------------------------------------------- /fixed-header-footer/src/Main2.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (main) 2 | 3 | import Browser 4 | import Element exposing (..) 5 | import Element.Border as Border 6 | 7 | 8 | main = 9 | layout [ height fill, width fill ] <| 10 | column [ height fill, width fill ] 11 | [ el [ width fill, height (px 200), padding 5 ] <| 12 | text "This is the top segment" 13 | , column [ width fill, scrollbarY ] 14 | (List.map 15 | (\n -> 16 | el [ width fill ] <| 17 | text ("this is " ++ String.fromInt n) 18 | ) 19 | (List.range 0 100) 20 | ) 21 | , el [ width fill, height (px 200), padding 5 ] <| 22 | text "This is the bottom segment" 23 | ] 24 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "locked": { 5 | "lastModified": 1667395993, 6 | "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", 7 | "owner": "numtide", 8 | "repo": "flake-utils", 9 | "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "numtide", 14 | "repo": "flake-utils", 15 | "type": "github" 16 | } 17 | }, 18 | "nixpkgs": { 19 | "locked": { 20 | "lastModified": 1671548329, 21 | "narHash": "sha256-OrC6R6zihRjFqdKFF3/vD3bkz44poONSII8ncre1Wh0=", 22 | "owner": "NixOS", 23 | "repo": "nixpkgs", 24 | "rev": "ba6ba2b90096dc49f448aa4d4d783b5081b1cc87", 25 | "type": "github" 26 | }, 27 | "original": { 28 | "id": "nixpkgs", 29 | "type": "indirect" 30 | } 31 | }, 32 | "root": { 33 | "inputs": { 34 | "flake-utils": "flake-utils", 35 | "nixpkgs": "nixpkgs" 36 | } 37 | } 38 | }, 39 | "root": "root", 40 | "version": 7 41 | } 42 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "dev deps for elm"; 3 | 4 | # to activate, type `nix develop` while in the repo dir or a subdir. 5 | # or use direnv to automatically do so (see .envrc) 6 | # for best results, don't have a global python installed. mixing python 7 | # versions can make for venv problems. 8 | 9 | inputs = { 10 | flake-utils.url = "github:numtide/flake-utils"; 11 | }; 12 | 13 | outputs = { self, nixpkgs, flake-utils }: 14 | flake-utils.lib.eachDefaultSystem ( 15 | system: let 16 | pname = "elm dev"; 17 | pkgs = nixpkgs.legacyPackages."${system}"; 18 | in 19 | rec { 20 | inherit pname; 21 | 22 | # `nix develop` 23 | devShell = pkgs.mkShell { 24 | nativeBuildInputs = with pkgs; [ 25 | elm2nix 26 | elmPackages.elm 27 | elmPackages.elm-analyse 28 | elmPackages.elm-doc-preview 29 | elmPackages.elm-format 30 | elmPackages.elm-live 31 | elmPackages.elm-test 32 | elmPackages.elm-upgrade 33 | elmPackages.elm-xref 34 | elmPackages.elm-language-server 35 | elmPackages.elm-verify-examples 36 | elmPackages.elmi-to-json 37 | elmPackages.elm-optimize-level-2 38 | ]; 39 | }; 40 | } 41 | ); 42 | } 43 | 44 | -------------------------------------------------------------------------------- /highlight-table-rows/elm.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "application", 3 | "source-directories": [ 4 | "src" 5 | ], 6 | "elm-version": "0.19.1", 7 | "dependencies": { 8 | "direct": { 9 | "elm/browser": "1.0.0", 10 | "elm/core": "1.0.0", 11 | "elm/html": "1.0.0", 12 | "mdgriffith/elm-ui": "1.1.8" 13 | }, 14 | "indirect": { 15 | "elm/json": "1.0.0", 16 | "elm/time": "1.0.0", 17 | "elm/url": "1.0.0", 18 | "elm/virtual-dom": "1.0.0" 19 | } 20 | }, 21 | "test-dependencies": { 22 | "direct": {}, 23 | "indirect": {} 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /highlight-table-rows/src/Main.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Browser 4 | import Browser.Events 5 | import Element exposing (..) 6 | import Element.Background as Background 7 | import Element.Border as Border 8 | import Element.Events exposing (onClick, onMouseEnter, onMouseLeave) 9 | import Element.Font as Font 10 | import Element.Input as Input 11 | 12 | 13 | -- Ellie for this one: 14 | -- https://ellie-app.com/kSZPrk5BCRNa1 15 | 16 | type Msgs 17 | = EnterCell Int 18 | | LeaveCell Int 19 | 20 | 21 | type alias Model = 22 | { highlightRow : Maybe Int } 23 | 24 | 25 | main = 26 | Browser.element 27 | { init = \() -> ( { highlightRow = Nothing }, Cmd.none ) 28 | , update = update 29 | , view = view 30 | , subscriptions = \_ -> Sub.none 31 | } 32 | 33 | 34 | update msg model = 35 | case msg of 36 | EnterCell row -> 37 | ( { model | highlightRow = Just row }, Cmd.none ) 38 | 39 | LeaveCell row -> 40 | ( { model | highlightRow = Just row }, Cmd.none ) 41 | 42 | 43 | cellevents = 44 | \mbhr row evts -> 45 | evts 46 | ++ [ onMouseEnter (EnterCell row), onMouseLeave (LeaveCell row) ] 47 | ++ (if mbhr == Just row then 48 | [ Background.color (Element.rgb 255 0 0) ] 49 | 50 | else 51 | [] 52 | ) 53 | 54 | 55 | view model = 56 | layout [ width fill, height fill ] <| 57 | table [ width fill, height fill, spacing 1 ] <| 58 | { data = 59 | List.indexedMap (\i s -> ( i, s ++ String.fromInt i )) <| 60 | List.repeat 50 "test" 61 | , columns = 62 | [ { header = el [ Background.color (rgb 0.9 0.9 0) ] <| text ("table header, row = " ++ (Maybe.map String.fromInt model.highlightRow |> Maybe.withDefault "none")) 63 | , width = fill 64 | , view = \( i, s ) -> el (cellevents model.highlightRow i [ padding 3 ]) <| text s 65 | } 66 | , { header = el [ Background.color (rgb 0.9 0.9 0) ] <| text "table header" 67 | , width = fill 68 | , view = \( i, s ) -> el (cellevents model.highlightRow i [ padding 3 ]) <| text s 69 | } 70 | , { header = el [ Background.color (rgb 0.9 0.9 0) ] <| text "table header" 71 | , width = fill 72 | , view = \( i, s ) -> el (cellevents model.highlightRow i [ padding 3 ]) <| text s 73 | } 74 | ] 75 | } 76 | -------------------------------------------------------------------------------- /local-font/elm.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "application", 3 | "source-directories": [ 4 | "src" 5 | ], 6 | "elm-version": "0.19.1", 7 | "dependencies": { 8 | "direct": { 9 | "elm/browser": "1.0.2", 10 | "elm/core": "1.0.5", 11 | "elm/html": "1.0.0", 12 | "mdgriffith/elm-ui": "1.1.8" 13 | }, 14 | "indirect": { 15 | "elm/json": "1.1.3", 16 | "elm/time": "1.0.0", 17 | "elm/url": "1.0.0", 18 | "elm/virtual-dom": "1.0.2" 19 | } 20 | }, 21 | "test-dependencies": { 22 | "direct": {}, 23 | "indirect": {} 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /local-font/fonts/GroovtasticRegular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bburdette/elm-ui-examples/55607272de217a36a400cffff2b5f3fb26b66ed3/local-font/fonts/GroovtasticRegular.ttf -------------------------------------------------------------------------------- /local-font/index.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 21 | 22 | 23 | 24 | 25 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /local-font/src/Main.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (main) 2 | 3 | import Browser 4 | import Element 5 | import Element.Input 6 | import Element.Font 7 | import Html exposing (Html, button, div, text) 8 | import Html.Events exposing (onClick) 9 | 10 | 11 | type alias Model = 12 | { lunch : Lunch } 13 | 14 | 15 | initialModel : Model 16 | initialModel = 17 | { lunch = Burrito } 18 | 19 | 20 | type Lunch 21 | = Burrito 22 | | Salad 23 | | Cake 24 | 25 | type Msg 26 | = ChooseLunch Lunch 27 | 28 | 29 | update : Msg -> Model -> Model 30 | update msg model = 31 | case msg of 32 | ChooseLunch lunch -> 33 | { model | lunch = lunch } 34 | 35 | 36 | view : Model -> Html Msg 37 | view model = 38 | Element.layout 39 | [ Element.Font.color (Element.rgb255 51 51 51) 40 | , Element.Font.size 36 41 | , Element.Font.family 42 | [ Element.Font.typeface "Groovtastic" 43 | , Element.Font.sansSerif 44 | ] 45 | -- , Element.Font.extraLight 46 | -- , Element.Font.italic 47 | , Element.Font.center 48 | , Element.padding 10 49 | ] 50 | (Element.Input.radio [] 51 | { label = 52 | Element.Input.labelAbove 53 | [] 54 | (Element.text "Pick lunch") 55 | , onChange = ChooseLunch 56 | , selected = Just model.lunch 57 | , options = 58 | [ Element.Input.option Burrito (Element.text "Burrito!") 59 | , Element.Input.option Salad (Element.text "Salad") 60 | , Element.Input.option Cake (Element.text "Cake") 61 | ] 62 | } 63 | ) 64 | 65 | 66 | main : Program () Model Msg 67 | main = 68 | Browser.sandbox 69 | { init = initialModel 70 | , view = view 71 | , update = update 72 | } 73 | 74 | -------------------------------------------------------------------------------- /local-font/test.sh: -------------------------------------------------------------------------------- 1 | # use elm-live to serve up the app and also a font file. 2 | 3 | elm-live src/Main.elm -- --output=main.js 4 | -------------------------------------------------------------------------------- /multiline.elm: -------------------------------------------------------------------------------- 1 | 2 | {- there's a bug where the multiline control doesn't show the text passed in to 'text', 3 | instead you get old text or text from a different instance of multiline. 4 | This workaround seems to fix it. 5 | -} 6 | workAroundMultiLine : 7 | List (Attribute msg) 8 | -> 9 | { onChange : String -> msg 10 | , text : String 11 | , placeholder : Maybe (EI.Placeholder msg) 12 | , label : EI.Label msg 13 | , spellcheck : Bool 14 | } 15 | -> Element msg 16 | workAroundMultiLine attribs mlspec = 17 | EI.multiline (htmlAttribute (HA.property "value" (JE.string mlspec.text)) :: attribs) 18 | mlspec 19 | 20 | 21 | -------------------------------------------------------------------------------- /textinput-sized-to-contents/elm.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "application", 3 | "source-directories": [ 4 | "src" 5 | ], 6 | "elm-version": "0.19.0", 7 | "dependencies": { 8 | "direct": { 9 | "elm/browser": "1.0.1", 10 | "elm/core": "1.0.2", 11 | "elm/html": "1.0.0", 12 | "mdgriffith/elm-ui": "1.1.0" 13 | }, 14 | "indirect": { 15 | "elm/json": "1.1.3", 16 | "elm/time": "1.0.0", 17 | "elm/url": "1.0.0", 18 | "elm/virtual-dom": "1.0.2" 19 | } 20 | }, 21 | "test-dependencies": { 22 | "direct": {}, 23 | "indirect": {} 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /textinput-sized-to-contents/src/Main.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (main) 2 | 3 | import Browser 4 | import Element exposing (..) 5 | import Element.Background as Background 6 | import Element.Border as Border 7 | import Element.Font as Font 8 | import Element.Input as Input 9 | import Html exposing (Html) 10 | import Html.Events exposing (onClick) 11 | 12 | 13 | type alias Model = 14 | String 15 | 16 | 17 | type Msg 18 | = Type String 19 | 20 | 21 | update : Msg -> Model -> Model 22 | update msg model = 23 | case msg of 24 | Type s -> 25 | s 26 | 27 | 28 | view : Model -> Html Msg 29 | view model = 30 | Element.layout [] 31 | (column [ width fill ] 32 | [ Input.text [ Border.rounded 0 ] 33 | { onChange = Type 34 | , text = model 35 | , placeholder = Nothing 36 | , label = Input.labelAbove [] <| text "default is fill?" 37 | } 38 | , Input.text 39 | [ Border.rounded 0 40 | , width (px 50) 41 | ] 42 | { onChange = Type 43 | , text = model 44 | , placeholder = Nothing 45 | , label = Input.labelAbove [] <| text "hardcoded to 50, sometimes too small" 46 | } 47 | , Input.text 48 | [ Border.rounded 0 49 | , width shrink 50 | ] 51 | { onChange = Type 52 | , text = model 53 | , placeholder = Nothing 54 | , label = Input.labelAbove [] <| text "putting shrink in makes it too big" 55 | } 56 | , Input.text 57 | [ Border.rounded 0 58 | , width (minimum 50 shrink) 59 | ] 60 | { onChange = Type 61 | , text = model 62 | , placeholder = Nothing 63 | , label = Input.labelAbove [] <| text "still meh" 64 | } 65 | , Input.text 66 | [ Border.rounded 0 67 | , width shrink 68 | ] 69 | { onChange = Type 70 | , text = model 71 | , placeholder = Just (Input.placeholder [] <| text model) 72 | , label = Input.labelAbove [] <| text "placeholder? nope." 73 | } 74 | , Input.text 75 | [ Border.rounded 0 76 | , width (px (20 + (10 * max 2 (String.length model)))) 77 | ] 78 | { onChange = Type 79 | , text = model 80 | , placeholder = Just (Input.placeholder [] <| text model) 81 | , label = Input.labelAbove [ Font.bold ] <| text "works: egregious hack, estimating from char count." 82 | } 83 | , sizeWithUnderlyingRow 84 | [ Border.rounded 0 85 | , width shrink 86 | ] 87 | { onChange = Type 88 | , text = model 89 | , placeholder = Just (Input.placeholder [] <| text model) 90 | , label = Input.labelAbove [ Font.bold ] <| text "works: sizeWithUnderlyingRow" 91 | } 92 | ] 93 | ) 94 | 95 | 96 | type alias TextInputSpecs msg = 97 | { onChange : String -> msg 98 | , text : String 99 | , placeholder : Maybe (Input.Placeholder msg) 100 | , label : Input.Label msg 101 | } 102 | 103 | 104 | {-| this works ok for labelAbove, but for LabelLeft would have to add in the label text to the 105 | invisible row text. 106 | -} 107 | sizeWithUnderlyingRow : List (Attribute msg) -> TextInputSpecs msg -> Element msg 108 | sizeWithUnderlyingRow attr specs = 109 | row 110 | (inFront (Input.text [ width fill ] specs) 111 | :: attr 112 | ++ [ paddingXY 15 0, alignLeft ] 113 | ) 114 | [ el [ Font.color (rgba 0 0 0 0) ] <| text specs.text 115 | ] 116 | 117 | 118 | main : Program () Model Msg 119 | main = 120 | Browser.sandbox 121 | { init = "as big as this" 122 | , view = view 123 | , update = update 124 | } 125 | 126 | 127 | sscce : Element msg 128 | sscce = 129 | Element.text "sscce" 130 | --------------------------------------------------------------------------------