Skip to content

chore(demo): Move emails into directories of their own #1298

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Feb 16, 2024
Merged
2 changes: 1 addition & 1 deletion apps/demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"@react-email/tailwind": "0.0.14",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-email": "2.0.0"
"react-email": "2.1.0-canary.1"
},
"devDependencies": {
"@types/react": "18.2.47",
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/components/tailwind.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ const Email = () => {
title="Tailwind Demo"
icon="arrow-up-right-from-square"
iconType="duotone"
href="https://demo.react.email/preview/vercel-invite-user.tsx"
href="https://demo.react.email/preview/notifications/vercel-invite-user"
>
See the full demo and source code.
</Card>
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/mint.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
{
"name": "Examples",
"icon": "arrow-pointer",
"url": "https://demo.react.email/preview/vercel-invite-user.tsx"
"url": "https://demo.react.email/preview/notifications/vercel-invite-user"
},
{
"name": "Discord",
Expand Down
88 changes: 49 additions & 39 deletions apps/web/src/components/example.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,54 +5,64 @@ import * as React from "react";
import { Heading } from "./heading";
import { Text } from "./text";

interface ExampleProps {
id: string;
export interface ExampleProps {
path: string;
name: string;
className?: string;
author: string;
}

const GITHUB_URL = "https://demo.react.email/preview";
const DEMO_EMAIL_PREVIEW_BASE_URL = "https://demo.react.email/preview";

export const Example: React.FC<Readonly<ExampleProps>> = ({
className,
id,
path,
name,
author,
...props
}) => (
<Link
className={classnames(
"bg-gradient border-slate-6 flex w-full flex-col rounded-md border backdrop-blur-[20px] focus:outline-none focus:ring-2",
"hover:bg-gradientHover",
"focus:bg-gradientHover focus:ring-white/20",
className,
)}
href={`${GITHUB_URL}/${id}`}
target="_blank"
{...props}
>
<Image
alt={name}
className="rounded-t-md"
height="300"
src={`/static/examples/${id.replace(".tsx", "")}.png`}
width="450"
/>
<div className="p-4">
<Heading size="2" weight="medium">
{name}
</Heading>
<div className="mt-2 flex flex-row gap-2">
<img
alt={author}
className="rounded-full"
height="24"
src={`https://github.com/${author}.png`}
width="24"
/>
<Text>{author}</Text>
}) => {
if (path.length === 0)
throw new Error("Cannot have an empty path for an Example!");

// as the path is never going to be an empty string, this pop here always returns the last
// portion of the path
//
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const emailName = path.split("/").pop()!;
return (
<Link
className={classnames(
"bg-gradient border-slate-6 flex w-full flex-col rounded-md border backdrop-blur-[20px] focus:outline-none focus:ring-2",
"hover:bg-gradientHover",
"focus:bg-gradientHover focus:ring-white/20",
className,
)}
href={`${DEMO_EMAIL_PREVIEW_BASE_URL}/${path}`}
target="_blank"
{...props}
>
<Image
alt={name}
className="rounded-t-md"
height="300"
src={`/static/examples/${emailName}.png`}
width="450"
/>
<div className="p-4">
<Heading size="2" weight="medium">
{name}
</Heading>
<div className="mt-2 flex flex-row gap-2">
<img
alt={author}
className="rounded-full"
height="24"
src={`https://github.com/${author}.png`}
width="24"
/>
<Text>{author}</Text>
</div>
</div>
</div>
</Link>
);
</Link>
);
};
40 changes: 20 additions & 20 deletions apps/web/src/pages/examples/index.tsx
Original file line number Diff line number Diff line change
@@ -1,99 +1,99 @@
import Head from "next/head";
import Image from "next/image";
import { Anchor } from "../../components/anchor";
import { Example } from "../../components/example";
import { Example, type ExampleProps } from "../../components/example";
import { Footer } from "../../components/footer";
import { Heading } from "../../components/heading";
import { Text } from "../../components/text";
import { Topbar } from "../../components/topbar";

const items = [
{
id: "github-access-token.tsx",
path: "notifications/github-access-token",
name: "GitHub / Access Token",
author: "bruno88cabral",
},
{
id: "apple-receipt.tsx",
path: "receipts/apple-receipt",
name: "Apple / Receipt",
author: "relferreira",
},
{
id: "nike-receipt.tsx",
path: "receipts/nike-receipt",
name: "Nike / Receipt",
author: "camillegachido",
},
{
id: "stack-overflow-tips.tsx",
path: "newsletters/stack-overflow-tips",
name: "Stack Overflow / Tips",
author: "bruno88cabral",
},
{
id: "slack-confirm.tsx",
path: "magic-links/slack-confirm",
name: "Slack / Confirm Email",
author: "c0dr",
},
{
id: "twitch-reset-password.tsx",
path: "reset-password/twitch-reset-password",
name: "Twitch / Reset Password",
author: "EmersonGarrido",
},
{
id: "raycast-magic-link.tsx",
path: "magic-links/raycast-magic-link",
name: "Raycast / Magic Link",
author: "abhinandanwadwa",
},
{
id: "yelp-recent-login.tsx",
path: "notifications/yelp-recent-login",
name: "Yelp / Recent Login",
author: "EmersonGarrido",
},
{
id: "linear-login-code.tsx",
path: "magic-links/linear-login-code",
name: "Linear / Login Code",
author: "Rychillie",
},
{
id: "google-play-policy-update.tsx",
path: "newsletters/google-play-policy-update",
name: "Google Play / Policy Update",
author: "EmersonGarrido",
},
{
id: "airbnb-review.tsx",
path: "reviews/airbnb-review",
name: "Airbnb / Review",
author: "joaom00",
},
{
id: "dropbox-reset-password.tsx",
path: "reset-password/dropbox-reset-password",
name: "Dropbox / Reset Password",
author: "ribeiroevandro",
},
{
id: "koala-welcome.tsx",
path: "welcome/koala-welcome",
name: "Koala / Welcome",
author: "nettofarah",
},
{
id: "vercel-invite-user.tsx",
path: "notifications/vercel-invite-user",
name: "Vercel / Invite User",
author: "zenorocha",
},
{
id: "stripe-welcome.tsx",
path: "welcome/stripe-welcome",
name: "Stripe / Welcome",
author: "zenorocha",
},
{
id: "notion-magic-link.tsx",
path: "magic-links/notion-magic-link",
name: "Notion / Magic Link",
author: "bukinoshita",
},
{
id: "plaid-verify-identity.tsx",
path: "magic-links/plaid-verify-identity",
name: "Plaid / Verify Identity",
author: "zenorocha",
},
];
] satisfies ExampleProps[];

const title = "Examples — React Email";
const description = "Open source templates built with React Email";
Expand Down Expand Up @@ -143,7 +143,7 @@ const Examples = () => {

<div className="grid grid-cols-2 gap-8">
{items.map((item) => (
<Example key={item.id} {...item} />
<Example key={item.path} {...item} />
))}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,72 @@ import path from 'node:path';
import { getEmailsDirectoryMetadata } from './get-emails-directory-metadata';

test('getEmailsDirectoryMetadata on demo emails', async () => {
expect(
await getEmailsDirectoryMetadata(
path.resolve(__dirname, '../../../../apps/demo/emails/'),
),
).toEqual({
absolutePath: path.resolve(__dirname, '../../../../apps/demo/emails/'),
const emailsDirectoryPath = path.resolve(
__dirname,
'../../../../apps/demo/emails/',
);
expect(await getEmailsDirectoryMetadata(emailsDirectoryPath)).toEqual({
absolutePath: emailsDirectoryPath,
directoryName: 'emails',
emailFilenames: [
'airbnb-review',
'amazon-review',
'apple-receipt',
'aws-verify-email',
'codepen-challengers',
'dropbox-reset-password',
'github-access-token',
'google-play-policy-update',
'koala-welcome',
'linear-login-code',
'netlify-welcome',
'nike-receipt',
'notion-magic-link',
'plaid-verify-identity',
'raycast-magic-link',
'slack-confirm',
'stack-overflow-tips',
'stripe-welcome',
'twitch-reset-password',
'vercel-invite-user',
'yelp-recent-login',
emailFilenames: [],
subDirectories: [
{
absolutePath: `${emailsDirectoryPath}/magic-links`,
directoryName: 'magic-links',
emailFilenames: [
'aws-verify-email',
'linear-login-code',
'notion-magic-link',
'plaid-verify-identity',
'raycast-magic-link',
'slack-confirm',
],
subDirectories: [],
},
{
absolutePath: `${emailsDirectoryPath}/newsletters`,
directoryName: 'newsletters',
emailFilenames: [
'codepen-challengers',
'google-play-policy-update',
'stack-overflow-tips',
],
subDirectories: [],
},
{
absolutePath: `${emailsDirectoryPath}/notifications`,
directoryName: 'notifications',
emailFilenames: [
'github-access-token',
'vercel-invite-user',
'yelp-recent-login',
],
subDirectories: [],
},
{
absolutePath: `${emailsDirectoryPath}/receipts`,
directoryName: 'receipts',
emailFilenames: ['apple-receipt', 'nike-receipt'],
subDirectories: [],
},
{
absolutePath: `${emailsDirectoryPath}/reset-password`,
directoryName: 'reset-password',
emailFilenames: ['dropbox-reset-password', 'twitch-reset-password'],
subDirectories: [],
},
{
absolutePath: `${emailsDirectoryPath}/reviews`,
directoryName: 'reviews',
emailFilenames: ['airbnb-review', 'amazon-review'],
subDirectories: [],
},
{
absolutePath: `${emailsDirectoryPath}/welcome`,
directoryName: 'welcome',
emailFilenames: ['koala-welcome', 'netlify-welcome', 'stripe-welcome'],
subDirectories: [],
},
],
subDirectories: [],
});
});