Skip to content

Instantly share code, notes, and snippets.

@jacobparis
Created November 14, 2024 07:25
Show Gist options
  • Save jacobparis/7d12affb9d87597e9524c2a65957260f to your computer and use it in GitHub Desktop.
Save jacobparis/7d12affb9d87597e9524c2a65957260f to your computer and use it in GitHub Desktop.
import { TweetAuthor } from "~/components/TweetAuthor"
import { ExternalLink } from "./ExternalLink"
type Tweet = {
media:
| Array<
| {
alt_text: string
height: number
type: "photo"
url: string
width: number
}
| {
height: number
preview_image_url: string
type: "animated_gif" | "video"
variants: { url: string }[]
width: number
}
>
| undefined
referenced_tweets: Tweet[] | undefined
type: "quoted" | null
author: { name: string; username: string; profile_image_url: string }
attachments: {
media_key: string
height: number
width: number
type: string
preview_image_url: string
}[]
replyingTo: string[]
html: string
id: string
created_at: string
}
export function SingleTweet({
tweet,
minimal = false,
}: {
tweet: Tweet
minimal: boolean
}) {
let grid = tweet.media
? {
4: `
"media-0 media-1" 10rem
"media-2 media-3" 10rem
/ 50% 50%;
`,
3: `
"media-0 media-1" 10rem
"media-0 media-2" 10rem
/ 1fr 1fr;
`,
2: `
"media-0 media-1" 20rem
/ 50% 50%
`,
1: `"media-0" 100% / 100%`,
}[tweet.media?.length]
: undefined
const quotedTweet = tweet.referenced_tweets?.find(
(tweet) => tweet.type === "quoted",
)
return (
<div className="mb-4 rounded-lg border px-6 py-4">
<header className="mb-6">
{minimal ? (
<div className="flex gap-x-2">
<img
alt={tweet.author.name}
src={tweet.author.profile_image_url}
decoding="async"
className="h-5 w-5 rounded-full"
/>
<div className="text-sm font-bold" title={tweet.author.name}>
{tweet.author.name}
</div>
<div
className="text-sm text-gray-600"
title={tweet.author.username}
>
@{tweet.author.username}
</div>
<a
href={tweet.id}
className="text-sm text-gray-600 hover:text-gray-500 hover:underline"
>
<time
title={`Time Posted: ${new Date(
tweet.created_at,
).toUTCString()}`}
dateTime={new Date(tweet.created_at).toISOString()}
>
{new Date(tweet.created_at).toLocaleDateString("en-US", {
year: "numeric",
month: "short",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
})}
</time>
</a>
</div>
) : (
<TweetAuthor
name={tweet.author.name}
username={tweet.author.username}
profile_image_url={tweet.author.profile_image_url}
/>
)}
</header>
{tweet.replyingTo ? (
<p className=" mb-3 text-sm text-gray-600">
Replying to{" "}
{tweet.replyingTo.map((username, i) => (
<span key={username}>
{i !== 0 && i === tweet.replyingTo.length - 1 ? (
<span> and </span>
) : null}
<ExternalLink
href={`https://twitter.com/${username}`}
className="text-sky-500"
>
@{username}{" "}
</ExternalLink>
</span>
))}
</p>
) : null}
<div className={`mb-4 ${minimal ? "" : "text-lg"}`}>
<div dangerouslySetInnerHTML={{ __html: tweet.html }}></div>
</div>
{tweet.media?.length ? (
<div
className="mt-2 mb-4 grid gap-1 overflow-hidden rounded-2xl border border-solid border-gray-300 "
style={{ grid: grid }}
>
{tweet.media.map((media, i) => {
if (media.type === "photo") {
return (
<div className="relative">
<img
key={i}
className="h-full w-full object-cover"
style={{ gridArea: `media-${i}` }}
alt={media.alt_text}
src={media.url}
width={media.width}
height={media.height}
/>
<div className="absolute left-0 bottom-0 p-3">
{media.alt_text ? (
<div
className="rounded bg-black px-1 text-sm font-bold text-white"
title={media.alt_text}
>
ALT
</div>
) : null}
</div>
</div>
)
}
if (media.type === "animated_gif") {
return (
<div className="relative">
<video
key={i}
src={media.variants[0].url}
poster={media.preview_image_url}
preload="none"
autoPlay
loop
/>
<div className="absolute left-0 bottom-0 p-3">
<div className="rounded bg-black px-1 text-sm font-bold text-white">
GIF
</div>
</div>
</div>
)
}
if (media.type === "video") {
return (
<div className="relative bg-black">
<video
key={i}
controls
src={media.variants.at(-1).url}
poster={media.preview_image_url}
autoPlay
muted
className="h-full"
preload="none"
/>
</div>
)
}
throw new Error(`Unsupported media type ${media.type}`)
})}
</div>
) : null}
{quotedTweet ? <SingleTweet tweet={quotedTweet} minimal /> : null}
{minimal ? null : (
<footer>
<a
href={`https://twitter.com/${tweet.author.username}/status/${tweet.id}`}
target="_blank"
rel="noopener noreferrer"
className="text-gray-600 hover:text-gray-500 hover:underline"
>
<time
title={`Time Posted: ${new Date(tweet.created_at).toUTCString()}`}
dateTime={new Date(tweet.created_at).toISOString()}
>
{new Date(tweet.created_at).toLocaleDateString("en-US", {
year: "numeric",
month: "short",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
})}
</time>
</a>
</footer>
)}
</div>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment