Search code examples
hyperscript

How to create an auto-resizing textarea in hyperscript


I have a textarea with a fixed width, and I want to make it auto-resize vertically when the text wraps or the user enters a new line.

I know how I can do it in javascript, but I cannot figure out how to get it to work in hyperscript.

Here's how I started. I understand that hardcoding 17 as the line height (it's actually 2.5rem) and 10 as the character width is wrong, but I'm just trying to get this naive thing working first.

on keyup
    log Math.ceil((my value.length * 10) / my clientWidth) * 17
    set my.style.height to Math.ceil((my value.length * 10) / my clientWidth) * 17 

It logs what I expect, but it won't set the height on the textarea. I've tried using *height as well instead of my.style.height with no luck. What gives?


Solution

  • So, it turns out that I actually just need to format the height as a string with "px" at the end instead of just a number.

    set my.style.height to (...).toString() + "px"

    Here's the full script I ended up with to calculate everything.

    set :lineHeight to parseInt(window.getComputedStyle(me, null).getPropertyValue('line-height'))
    set :paddingRight to parseInt(window.getComputedStyle(me, null).getPropertyValue('padding-right'))
    set :paddingLeft to parseInt(window.getComputedStyle(me, null).getPropertyValue('padding-left'))
    set :font to window.getComputedStyle(me, null).getPropertyValue('font')
    on keyup
        make a <canvas/> called canvas
        set context to canvas.getContext("2d")
        set context.font to :font
        set textWidth to context.measureText(my value).width
        set areaWidth to (my clientWidth - :paddingRight - :paddingLeft)
        set calculatedHeight to Math.ceil(textWidth / areaWidth) * :lineHeight
        set my.style.height to calculatedHeight.toString() + "px"
    

    This only works if we assume that the line-height, padding-right, padding-left, and font of the textarea will not change after load, which is an assumption I'm willing to make.