chore: add pnpm workspace configuration with package definitions and overrides
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
import { Body, Container, Head, Hr, Html, Preview, Section, Text } from "@react-email/components";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
const brand = "#4338ca";
|
||||
const ink = "#18181b";
|
||||
const muted = "#71717a";
|
||||
const border = "#e4e4e7";
|
||||
const surface = "#fafafa";
|
||||
|
||||
interface EmailLayoutProps {
|
||||
/** Short preview line shown in inbox lists. */
|
||||
preview: string;
|
||||
/** App display name shown in the header/footer. */
|
||||
appName: string;
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared shell for transactional email. Neutral, system-font, inline-styled
|
||||
* (no Tailwind) so the Worker bundle stays lean and rendering is fast.
|
||||
*/
|
||||
export function EmailLayout({ preview, appName, children }: EmailLayoutProps) {
|
||||
return (
|
||||
<Html lang="en" dir="ltr">
|
||||
<Head />
|
||||
<Preview>{preview}</Preview>
|
||||
<Body style={layoutBodyStyle}>
|
||||
<Container style={containerStyle}>
|
||||
<Section style={headerStyle}>
|
||||
<Text style={brandStyle}>{appName}</Text>
|
||||
</Section>
|
||||
|
||||
<Section style={cardStyle}>{children}</Section>
|
||||
|
||||
<Hr style={hrStyle} />
|
||||
<Text style={footerStyle}>
|
||||
You received this email because you have an account or were invited to {appName}. If
|
||||
this wasn't you, you can safely ignore it.
|
||||
</Text>
|
||||
</Container>
|
||||
</Body>
|
||||
</Html>
|
||||
);
|
||||
}
|
||||
|
||||
const layoutBodyStyle: React.CSSProperties = {
|
||||
backgroundColor: surface,
|
||||
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
|
||||
margin: 0,
|
||||
padding: "24px 0",
|
||||
};
|
||||
|
||||
const containerStyle: React.CSSProperties = {
|
||||
maxWidth: 480,
|
||||
margin: "0 auto",
|
||||
padding: "0 16px",
|
||||
};
|
||||
|
||||
const headerStyle: React.CSSProperties = {
|
||||
padding: "8px 0 16px",
|
||||
};
|
||||
|
||||
const brandStyle: React.CSSProperties = {
|
||||
color: brand,
|
||||
fontSize: 18,
|
||||
fontWeight: 700,
|
||||
letterSpacing: "-0.01em",
|
||||
margin: 0,
|
||||
};
|
||||
|
||||
const cardStyle: React.CSSProperties = {
|
||||
backgroundColor: "#ffffff",
|
||||
border: `1px solid ${border}`,
|
||||
borderRadius: 12,
|
||||
padding: "28px 28px 24px",
|
||||
};
|
||||
|
||||
const hrStyle: React.CSSProperties = {
|
||||
border: "none",
|
||||
borderTop: `1px solid ${border}`,
|
||||
margin: "24px 0 16px",
|
||||
};
|
||||
|
||||
const footerStyle: React.CSSProperties = {
|
||||
color: muted,
|
||||
fontSize: 12,
|
||||
lineHeight: "18px",
|
||||
margin: 0,
|
||||
textAlign: "center",
|
||||
};
|
||||
|
||||
/**
|
||||
* Shared content styles used by the email templates (heading, body text,
|
||||
* primary button, muted helper text).
|
||||
*/
|
||||
export const titleStyle: React.CSSProperties = {
|
||||
color: ink,
|
||||
fontSize: 22,
|
||||
fontWeight: 700,
|
||||
letterSpacing: "-0.01em",
|
||||
margin: "0 0 12px",
|
||||
};
|
||||
|
||||
export const bodyStyle: React.CSSProperties = {
|
||||
color: ink,
|
||||
fontSize: 14,
|
||||
lineHeight: "22px",
|
||||
margin: "0 0 12px",
|
||||
};
|
||||
|
||||
export const buttonStyle: React.CSSProperties = {
|
||||
backgroundColor: brand,
|
||||
borderRadius: 8,
|
||||
color: "#ffffff",
|
||||
display: "inline-block",
|
||||
fontSize: 14,
|
||||
fontWeight: 600,
|
||||
margin: "16px 0",
|
||||
padding: "10px 18px",
|
||||
textDecoration: "none",
|
||||
};
|
||||
|
||||
export const mutedStyle: React.CSSProperties = {
|
||||
color: muted,
|
||||
fontSize: 12,
|
||||
lineHeight: "18px",
|
||||
margin: "16px 0 0",
|
||||
};
|
||||
|
||||
export const emailTokens = { brand, ink, muted, border } as const;
|
||||
Reference in New Issue
Block a user