Autosize Textarea
zyeon/autosize-textareaFreeComponent
A textarea that grows with its content via CSS field-sizing with a scrollHeight-based JS fallback, capped between minRows and maxRows.
Install it
npx shadcn@latest add https://ui.zyeon.ai/r/autosize-textarea.jsonSource
1"use client"23import * as React from "react"4import { cn } from "@/lib/utils"56/** SSR-safe: `CSS` doesn't exist in Node, so this stays `false` until it's read on the client. */7const supportsFieldSizing =8 typeof CSS !== "undefined" && typeof CSS.supports === "function" && CSS.supports("field-sizing", "content")910export interface AutosizeTextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {11 /** Rows visible before the textarea starts growing. */12 minRows?: number13 /** Rows it grows to before switching to internal scrolling. */14 maxRows?: number15}1617interface Metrics {18 lineHeight: number19 verticalPadding: number20 verticalBorder: number21}2223/** Reads line-height/padding/border once per element so minRows/maxRows convert to real pixels. */24function measure(el: HTMLTextAreaElement): Metrics {25 const style = window.getComputedStyle(el)26 let lineHeight = parseFloat(style.lineHeight)27 if (Number.isNaN(lineHeight)) lineHeight = parseFloat(style.fontSize) * 1.228 return {29 lineHeight,30 verticalPadding: parseFloat(style.paddingTop) + parseFloat(style.paddingBottom),31 verticalBorder: parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth),32 }33}3435export const AutosizeTextarea = React.forwardRef<HTMLTextAreaElement, AutosizeTextareaProps>(36 ({ minRows = 2, maxRows = 8, rows, className, style, onInput, value, defaultValue, ...props }, ref) => {37 const innerRef = React.useRef<HTMLTextAreaElement | null>(null)38 const metricsRef = React.useRef<Metrics | null>(null)3940 const setRefs = React.useCallback(41 (node: HTMLTextAreaElement | null) => {42 innerRef.current = node43 if (typeof ref === "function") ref(node)44 else if (ref) ref.current = node45 },46 [ref],47 )4849 // Writes the DOM directly rather than setState: where field-sizing is supported,50 // min/max-height is all it takes and the browser does the growing; otherwise it is51 // height:auto → measure scrollHeight → clamp to [minHeight, maxHeight] every time.52 const resize = React.useCallback(() => {53 const el = innerRef.current54 if (!el) return55 if (!metricsRef.current) metricsRef.current = measure(el)56 const { lineHeight, verticalPadding, verticalBorder } = metricsRef.current57 const box = verticalPadding + verticalBorder58 const minHeight = lineHeight * minRows + box59 const maxHeight = lineHeight * maxRows + box6061 el.style.minHeight = `${minHeight}px`62// … truncated
What it pulls in
Other registry items
Files it writes
More from zyeon
All 893 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| A/B Test Resultab-test-result | zyeon | Components | Paid | 2 deps · 2 files | |
| Accordionaccordion | zyeon | Components | Free | 1 dep | |
| Activity Feedactivity-feed | zyeon | Components | Free | 2 deps · 2 files | |
| Activity Heatmapactivity-heatmap | zyeon | Components | Paid | 1 dep · 2 files | |
| Address Formaddress-form | zyeon | Components | Paid | 1 dep | |
| Agent Graphagent-graph | zyeon | Components | Free | 2 deps · 2 files | |
| Agent Handoffagent-handoff | zyeon | Components | Free | 1 dep | |
| Agent Inboxagent-inbox | zyeon | Components | Free | 2 deps · 2 files |
