- All Components
- Animated Arrow
- Animated Counter
- Animated Save Button
- Animated Tabs
- Animated List/Grid View
- Bento Grid
- Border Beam
- Button
- Animated Copy Button
- Dock
- Animated 3D Folder
- Cursor-Tracking Glow Card
- Inline Edit Animation
- Animated OTP Input
- Infinite Marquee
- Animated Password Input
- Interactive Pie Chart
- Reveal on Scroll
- Tweet Card
- Typewriter
- Interactive World Map
Installation
npx shadcn@latest add https://tentui.com/r/tweet-card.json
Usage
Pass the tweet content as children and the author metadata as props. No iframe, no script tag, no third-party JavaScript — just HTML and CSS.
import { TweetCard } from "@/components/tweet-card";
export function Quote() {
return (
<TweetCard
name="Lee Robinson"
handle="leeerob"
verified
date="May 21"
likes={1843}
retweets={142}
replies={37}
href="https://x.com/leeerob/status/123"
>
Ship the smallest possible version of your idea today.
</TweetCard>
);
}Patterns
Server-side fetch with react-tweet
If you want a live tweet, pair this card with react-tweet's getTweet helper. It pulls from the public syndication API — still no client-side script.
import { getTweet } from "react-tweet/api";
import { TweetCard } from "@/components/tweet-card";
export async function LiveTweet({ id }: { id: string }) {
const tweet = await getTweet(id);
if (!tweet) return null;
return (
<TweetCard
name={tweet.user.name}
handle={tweet.user.screen_name}
avatarUrl={tweet.user.profile_image_url_https}
verified={tweet.user.verified}
date={new Date(tweet.created_at).toLocaleDateString()}
likes={tweet.favorite_count}
href={`https://x.com/${tweet.user.screen_name}/status/${tweet.id_str}`}
>
{tweet.text}
</TweetCard>
);
}Testimonial walls
TweetCard plays well with the Marquee component for a privacy-friendly testimonial wall.
<Marquee>
{tweets.map((t) => (
<TweetCard key={t.id} {...t}>
{t.text}
</TweetCard>
))}
</Marquee>Avatar fallback
If you omit avatarUrl, the card renders the author's initials in a neutral chip — useful for placeholder data and for tweets where you don't want to hotlink Twitter's CDN.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | — | Display name of the author. |
handle | string | — | Username, without the leading @. |
avatarUrl | string | — | Avatar URL. Falls back to initials. |
date | string | — | Free-form date label. |
verified | boolean | false | Show a blue verified badge. |
likes | number | — | Like count — formatted compactly (e.g. 1.2K). |
retweets | number | — | Retweet count. |
replies | number | — | Reply count. |
href | string | — | If set, the entire card becomes a link to the source. |
children | ReactNode | — | Tweet body. Whitespace is preserved. |
className | string | — | Forwarded to the outer <article>. |
Why no embed?
The official X embed script weighs ~80 KB, blocks rendering, and sets third-party cookies. For a static testimonial or quote block this card is faster, leaner, and survives the original tweet being deleted.