Skip to content

Instantly share code, notes, and snippets.

@ohanhi
Created March 18, 2017 17:53
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ohanhi/cb42ba2587fefbdae6962518176d114a to your computer and use it in GitHub Desktop.
Save ohanhi/cb42ba2587fefbdae6962518176d114a to your computer and use it in GitHub Desktop.
A pure Elm auto expanding text area
module AutoExpand exposing (main)
-- https://embed.ellie-app.com/Gnv9Bznh4na1/0
import Html exposing (Html, div, p, br, textarea, text)
import Html.Attributes exposing (rows, style)
import Html.Events exposing (onInput, on)
import Json.Decode exposing (Decoder, field, at, map2, int, string)
type alias Model =
{ rows : Int
, inputText : String
}
type alias Config =
{ padding : Float
, lineHeight : Float
, minRows : Int
, maxRows : Int
}
config : Config
config =
{ padding = 10
, lineHeight = 20
, minRows = 1
, maxRows = 4
}
initModel : Model
initModel =
{ rows = config.minRows
, inputText = ""
}
type Msg
= NewValues String Int
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
NewValues inputText height ->
( { model
| inputText = inputText
, rows = getRows height
}
, Cmd.none
)
view : Model -> Html Msg
view model =
div [ containerStyle ]
[ div
[ style [ ( "width", "200px" ) ]
]
[ textarea
[ on "input" inputDecoder
, rows model.rows
, Html.Attributes.value model.inputText
, textareaStyles model.rows
]
[]
, p []
[ text ("Rows: " ++ toString model.rows)
, br [] []
, text ("Min: " ++ toString config.minRows)
, br [] []
, text ("Max: " ++ toString config.maxRows)
]
]
]
getRows : Int -> Int
getRows scrollHeight =
((toFloat scrollHeight - 2 * config.padding) / config.lineHeight)
|> ceiling
|> clamp config.minRows config.maxRows
inputDecoder : Decoder Msg
inputDecoder =
map2 NewValues
(at [ "target", "value" ] string)
(at [ "target", "scrollHeight" ] int)
containerStyle : Html.Attribute msg
containerStyle =
style
[ ( "background-color", "rebeccapurple" )
, ( "color", "white" )
, ( "font-family", "sans-serif" )
, ( "width", "100vw" )
, ( "height", "100vh" )
, ( "display", "flex" )
, ( "align-items", "center" )
, ( "justify-content", "center" )
, ( "flex-direction", "column" )
]
textareaStyles : Int -> Html.Attribute msg
textareaStyles rowCount =
style
[ ( "padding", toString config.padding ++ "px" )
, ( "border", "0 none" )
, ( "border-radius", "2px" )
, ( "box-sizing", "border-box" )
, ( "line-height", toString config.lineHeight ++ "px" )
, ( "width", "100%" )
, ( "overflow"
, if rowCount <= config.maxRows then
"visible"
else
"scroll-y"
)
]
main : Program Never Model Msg
main =
Html.program
{ view = view
, update = update
, subscriptions = \_ -> Sub.none
, init = ( initModel, Cmd.none )
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment