Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Testimonial Form Block for React

A form for writing your own testimonial about Quill, in a split page column: name, role, star rating, a quote with a character counter and a permission switch on one side, a live preview card in a card on the other, and a Shine Button to send.

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

Ask customers for their words and let them see the result before they send it. The page column splits in two with a hairline divider. A compact header and a short form fill the start side: your name, your role and company, a star rating, a quote with a live character counter and a switch that gives permission to show it. The end side holds the testimonial card they are writing, set in a card in a card with + marks on its frame. The card is redrawn as they type: the stars fill, the quote appears, the initials follow the name, and a badge says whether permission has been given. The submit is a Shine Button; it shows a spinner while the send takes a moment, then the form gives way to a thank-you and the finished card stays in view. On a phone the preview comes right after the header and the form follows it. Nothing is sent anywhere: the block says so and keeps the words on the page. It's built from Field, Input, Textarea, Rating, Switch, Avatar, Badge, Guides and Shine Button, with CSS transitions only and your theme's tokens. For a "tell us how it went" page, a customer success follow-up or any place you collect testimonials and want them to feel proud of what they send.

FAQ

How do I send the testimonial somewhere?

Nothing is sent today: submit checks the form, waits 600 ms and shows the thank-you. Replace that wait with your request. Post name, role, rating, quote and consent to your own endpoint, and call finish when it succeeds or show an error when it doesn't. Store the permission with the text, so you can always show when it was given.

What does the form check, and how are errors shown?

It checks, in order, that there is a name, a rating from 1 to 5, a quote of at least 20 characters and that permission is on. Errors appear under their field in plain words with an alert icon, are read out when they appear, and focus moves to the first field that needs attention. Typing in a field clears its own error. The checks are in the validate function at the top of the file, so you can add your own, and the quote can't pass 280 characters because the field stops there; change LIMIT to move it.

How does the live preview work?

Every field is held in state and the preview card reads the same state, so it can never disagree with the form. Until a field is filled in, the card shows a placeholder in its place, and its height is held by an unseen full-length quote so nothing around it moves as the text grows. From lg the card stays in view while the form scrolls. The preview isn't announced while typing, so screen reader users aren't interrupted; the thank-you and the sending state are announced politely.

Is the form accessible?

Yes. Every field has a visible label, the rating is a group of five labelled radio buttons under a legend ("Your rating") that you can also drive with the arrow keys, and the permission switch is named. The character counter is tied to the quote field, so it is read after the label. Errors are tied to their fields and announced; the fields are read-only while sending so focus stays where it is; and after sending, focus moves to the thank-you heading. "Write another" clears the form and puts focus back on its heading. Stars and the switch use the text colour, so the Shine Button is the only primary control.

Does it work in right-to-left languages?

Yes. The two columns, the labels, the divider between them and the frame's marks follow the reading direction. The counter ("94 of 280 characters") and the quote sit in a bdi, so numbers and quotation marks keep their place.

How does it adapt to small screens?

Below lg the page column is one column: the header, then the preview, then the form, so the card is on the first screen and shows what the form will make. The name and role fields stack, and the Shine Button spans the width. It reads at 320px with no horizontal scroll. The quote field has a fixed height, so a long quote scrolls inside it instead of stretching the page.

  • Pro

    Testimonials With CTA

    Results and figures

    Two customer quotes led by the result each one measured, in a hairline band with a divider, then a card in card whose headline repeats the larger result and whose Shine Button is the one primary action.

  • Pro

    A proof bar for a help-desk app: four linked figures (customers, review score, retention, reply time) with a small greyscale picture each, as one band with shared hairlines and + marks at the rails, then the quote that explains them, with a Shine Button in the header row.

  • Pro

    Trust Badges Testimonials

    Ratings and reviews

    A scoreboard of four review sources for a bookkeeping app: a weighted average beside the heading, then a band of four cells on shared hairlines, each with a score, partly filled stars, its review count, one reviewer line and a link.

  • Pro

    Eight customer wordmarks of an inventory app as tabs in a bordered grid that shares its hairlines: choose a company to read its quote, who said it and the one result it points to, in a raised card inside a tinted shell, under a header with a Shine Button.

  • Pro

    A compact start-aligned hero with a headline, a Shine Button and an outline action over a closing band that holds one customer's quote, large, beside their rating, name, role and the number it is about.

  • Pro

    A card-in-card call to action built on a rating summary: a headline and a Shine Button over a band with a big score and foreground stars beside a five-to-one star histogram, all figures worked out from the counts.