Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Rich Text Comments Block for React

A comment composer with a formatting toolbar that wraps the selected text in bold, italic, code, link, list or quote marks, Ctrl or ⌘ shortcuts, and Write and Preview tabs over a two-comment thread.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Let people format a reply without learning markdown first, with this rich text comment composer for React with Base UI. A note called Autumn menu in Boldwick sits above its two comments, and the composer under them has a toolbar of six Buttons with Tooltips: Bold, Italic, Code, Link, List and Quote. Each one wraps the text selected in the Textarea (or the lines it touches) and takes the marks off again when the selection is already wrapped; Ctrl or ⌘ + B, I and K do the same for bold, italic and link. Write and Preview are Tabs: Preview draws the comment with a small typed parser that reads bold, italic, code, links, lists and quotes into plain elements, so nothing is ever injected as HTML. A Field holds the box with an always-reserved problem line and a count that appears in the last 100 characters, and one Shine Button posts the formatted comment into the thread above, where it is drawn by the same parser. Built from Tabs, Tooltip, Button, Textarea, Field, Avatar, Badge, Kbd, Shine Button and Guides. For notes, docs and any thread where replies need a little structure.

FAQ

How do I fill it with my own note?

Edit PEOPLE and START at the top of the file. Each comment has an id, who wrote it (by, a person's id), an ISO at and its body, written in the markdown the parser reads. ME names the person using the page. Ages such as "1 d ago" are worked out from AS_OF and the typed times, never from the clock, so the server and the browser print the same words.

What stays local, and how do I make it real?

Everything. Posting adds the comment to a list in the page and the status line says "Comment posted in this demo. Nothing was sent." To make it real, send the markdown string from post to your API and store it as text, then draw it on the way back with the same parser or your own. Never store or return HTML built from a visitor's text without sanitizing it on the server.

How do the toolbar buttons decide what to wrap?

The helpers wrapOf, prefixOf and linkOf take the box's text and the selection and return the new text and the new selection. Bold, Italic and Code add their marks around the selection (or around a placeholder word when nothing is selected) and remove them when the marks are already there. List and Quote add - or > to every line the selection touches, or remove it when all of them have it. Link wraps the selection as [text](https://) and selects the address so you can type over it. Focus returns to the box with the selection kept.

Is it accessible?

The buttons are real buttons named for what they do, grouped in a fieldset with a hidden legend, and each tooltip also shows its shortcut. Write and Preview are a labelled tablist. In Preview the toolbar stays in place but answers "Switch to Write to format the text." instead of editing. The problem line is announced when it appears, the polite status region is present from load, and the count is spoken only at 20, 10 and 0 characters left.

How does it look on a phone?

The tabs and the toolbar share a row that wraps to two rows when it must, the toolbar buttons grow to a comfortable touch size, and the post button goes full width under the shortcut hint. The thread keeps its height and scrolls inside its own region.