shadcn.io is not affiliated with official shadcn/ui
Textarea with Counter Ring Form Block for React
A stand-up update composer whose character counter is a ring that fills to 280, shows its number only near the end, goes negative past the limit and is spoken at four stages, with a list of the latest two posts.
Installation
Overview
Show how much room is left without nagging, with this textarea form for React with Base UI. A compact header sits over a hairline frame with a plus mark on each corner: a composer band with the author's initials and a Textarea of fixed height, so typing never moves anything; a band with the latest two updates, each an Avatar of initials, a name, a time and the text; and an action foot. The counter is a Circular Progress ring in the foot that fills to 280 characters. Its number appears only in the last 20 and turns negative past the limit ("-12"), the field says why in words under it, and the ring's arc takes the alert colour only when you are over. Post with nothing written, or over the limit, posts nothing and says so; a good post goes to the top of the list and the field empties. It's built from Textarea, Circular Progress, Avatar, Field, Shine Button and Guides, with a CSS entrance only. For status updates, comments, bios and any text with a limit.
FAQ
How do I change the limit and the stages?
LIMIT is the limit and the ring's maximum. The stages are the three thresholds in stageOf (240, 260 and 280) with a sentence for each in STAGE_LINES, and SHOWN_FROM is how many characters from the end the ring starts to show its number. Each sentence is true for every length within its stage, so the text only changes when you cross a threshold, never as you type inside one.
Does a screen reader hear every character?
No. The exact count is the field's description ("212 of 280 characters"), read when the field takes focus, and the foot's polite status changes only when a stage is crossed, so it speaks at most four times however long you type. The ring and the number inside it are hidden from assistive technology: they repeat what the words say. The reason under the field never carries the number, for the same reason.
What happens when I go over the limit?
Typing and pasting are never blocked, so a long paste can be trimmed rather than lost. The ring fills, its arc takes the alert colour and the number goes negative; the field is marked invalid and says to trim the update; Post refuses, names the problem in the foot and puts focus back in the field. The state is carried by words and the sign of the number, never by colour alone.
How are characters counted?
By code point, with Array.from, so an accented letter or an emoji counts once and a paste with line breaks counts each break. That is not always what your server counts (a flag or a family emoji is several code points, and some APIs count UTF-16 units), so count the same way on both sides and trim the same way before you store.
What stays local, and how do I connect it for real?
Nothing is posted. Post puts the update at the top of a list kept in the page's state, which always shows the latest two so the panel never changes height, and the foot says it was posted in this demo. For a real feed, send the trimmed text in the submit handler, add the update from the response (or show the error in the same status line and keep the text), and load the older updates from your own API.
How do I connect it to react-hook-form or TanStack Form?
Keep the count outside the form library: it is derived from the one value. With react-hook-form, use Controller for the textarea, read the value with watch or useWatch for the ring, and move the limit into a resolver or schema (max(280) counts UTF-16 units, so match it to lengthOf). With TanStack Form, subscribe to the field's value for the ring and validate it with an onChange validator that returns the reason line.
Related
- Pro
Text Input with Address Preview Form
Text fieldsA form panel with one required project-name field that shows the web address it will get as you type, flags a name that is taken or past 50 characters, and offers the next free address.
- Pro
Card in Card Contact
Contact formsA card-in-card contact section for a bookkeeping service: the details of the desk you pick beside a raised form with a live message counter.
- Pro
Email and Password Form
Text fieldsThe sign-in pair done well: an email named for password managers, a password with a reveal button and a Caps Lock warning, one generic failure that never says which half was wrong, and a quiet band with the demo account.
- Pro
Minimal Single Question Form
Text fieldsThe calmest form: one page with a mark, a heading that asks one question, one field with a hidden label and one full-width button, with the answer or the one problem shown under the field.
- Pro
Password Strength Form
Text fieldsA master-password form with advice instead of a checklist: a four-segment meter, one sentence that names the weakest thing about what is typed, a polite confirm field and a side cell that explains the four segments.
- Pro
Markdown Editor Form
Text fieldsA page editor whose toolbar really formats: Bold, Italic, Bullet list and Link wrap the selection in Markdown, shortcuts work, the toolbar is one tab stop with arrow keys, and a Preview tab renders the result.