Read More
DisclosureText with expandable truncated content.
Preview
Usage
example.jsx
import { ReadMore } from "@/components/ui/read-more";
export default function Example() {
return <ReadMore />;
}Source Code
Copy this file into components/ui/read-more.jsx in your project.
read-more.jsx
"use client";
import { forwardRef, useState } from "react";
import { cn } from "@/lib/utils";
const ReadMore = forwardRef(({ className, text = "", maxLength = 150, moreLabel = "Read more", lessLabel = "Read less", ...props }, ref) => {
const [expanded, setExpanded] = useState(false);
const shouldTruncate = text.length > maxLength;
return (
<div ref={ref} className={cn("text-sm", className)} {...props}>
<span>{expanded || !shouldTruncate ? text : `${text.slice(0, maxLength)}…`}</span>
{shouldTruncate && (
<button onClick={() => setExpanded(!expanded)} className="ml-1 font-medium text-primary hover:underline">
{expanded ? lessLabel : moreLabel}
</button>
)}
</div>
);
});
ReadMore.displayName = "ReadMore";
export { ReadMore };
Quick Install
Make sure you have the cn() utility set up. It requires clsx and tailwind-merge.
npm install clsx tailwind-merge