brookmind-emails 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,8 +8,8 @@ import {
8
8
  Link,
9
9
  Preview,
10
10
  Font,
11
+ Img,
11
12
  } from "@react-email/components";
12
- import { Header, Footer } from "../../shared/components/index.js";
13
13
  import { modelfyConfig } from "../config.js";
14
14
 
15
15
  export interface OtpEmailProps {
@@ -18,60 +18,137 @@ export interface OtpEmailProps {
18
18
  expirationMinutes?: number;
19
19
  }
20
20
 
21
+ // Design System Colors - Matching Modelfy Landing
22
+ const colors = {
23
+ background: "#0d0d0d",
24
+ cardBg: "#121212",
25
+ primary: "#0a8f5a",
26
+ white: "#f2f2f2",
27
+ textSecondary: "rgba(242, 242, 242, 0.7)",
28
+ textMuted: "#8c8c8c",
29
+ border: "#262626",
30
+ };
31
+
21
32
  const styles = {
22
33
  body: {
23
34
  margin: 0,
24
35
  padding: 0,
25
- backgroundColor: "#F8FAFC",
26
- fontFamily: "'Outfit', Arial, sans-serif",
36
+ backgroundColor: colors.background,
37
+ fontFamily: "'Inter', 'Segoe UI', Arial, sans-serif",
27
38
  },
28
39
  container: {
29
- maxWidth: "560px",
30
- margin: "32px auto",
31
- backgroundColor: "#ffffff",
32
- border: "1px solid #E2E8F0",
33
- borderRadius: "16px",
34
- boxShadow: "0 24px 48px rgba(15, 23, 42, 0.08)",
35
- overflow: "hidden",
40
+ maxWidth: "600px",
41
+ margin: "0 auto",
42
+ backgroundColor: colors.background,
43
+ },
44
+ header: {
45
+ backgroundColor: colors.background,
46
+ padding: "40px 32px 24px",
47
+ textAlign: "center" as const,
36
48
  },
37
- content: {
38
- padding: "32px 40px 24px",
49
+ logo: {
50
+ display: "block" as const,
51
+ margin: "0 auto",
52
+ },
53
+ heroSection: {
54
+ padding: "24px 32px 40px",
55
+ textAlign: "center" as const,
56
+ },
57
+ heroTagline: {
58
+ margin: "0 0 12px",
59
+ fontSize: "13px",
60
+ fontWeight: 600,
61
+ color: colors.primary,
62
+ letterSpacing: "2px",
63
+ textTransform: "uppercase" as const,
64
+ },
65
+ heroHeading: {
66
+ margin: "0 0 16px",
67
+ fontSize: "28px",
68
+ fontWeight: 700,
69
+ color: colors.white,
70
+ lineHeight: "1.3",
39
71
  },
40
72
  paragraph: {
41
- margin: "16px 0 24px",
73
+ margin: "0 0 28px",
42
74
  fontSize: "16px",
43
75
  lineHeight: "1.6",
44
- color: "rgba(15, 23, 42, 0.72)",
76
+ color: colors.textSecondary,
45
77
  },
46
78
  otpContainer: {
47
79
  display: "inline-block",
48
- backgroundColor: "rgba(99, 102, 241, 0.08)",
49
- border: "1px solid rgba(99, 102, 241, 0.24)",
80
+ backgroundColor: "rgba(10, 143, 90, 0.15)",
81
+ border: `1px solid rgba(10, 143, 90, 0.3)`,
50
82
  borderRadius: "12px",
51
- padding: "20px 32px",
52
- marginBottom: "24px",
83
+ padding: "24px 40px",
84
+ marginBottom: "28px",
53
85
  },
54
86
  otp: {
55
- fontSize: "32px",
56
- letterSpacing: "8px",
87
+ fontSize: "36px",
88
+ letterSpacing: "10px",
57
89
  fontWeight: 700,
58
- color: "#0F172A",
90
+ color: colors.white,
59
91
  margin: 0,
60
92
  },
93
+ contentSection: {
94
+ backgroundColor: colors.cardBg,
95
+ padding: "32px",
96
+ borderTop: `1px solid ${colors.border}`,
97
+ },
61
98
  smallText: {
62
99
  margin: "0 0 12px",
63
- fontSize: "15px",
100
+ fontSize: "14px",
64
101
  lineHeight: "1.6",
65
- color: "rgba(15, 23, 42, 0.72)",
102
+ color: colors.textMuted,
103
+ textAlign: "center" as const,
66
104
  },
67
105
  link: {
68
- color: "#0F172A",
106
+ color: colors.primary,
69
107
  textDecoration: "none",
70
108
  fontWeight: 600,
71
109
  },
110
+ footer: {
111
+ backgroundColor: colors.cardBg,
112
+ padding: "24px 32px",
113
+ textAlign: "center" as const,
114
+ borderTop: `1px solid ${colors.border}`,
115
+ },
116
+ footerLogo: {
117
+ display: "block" as const,
118
+ margin: "0 auto 12px",
119
+ opacity: 0.6,
120
+ },
121
+ footerText: {
122
+ margin: "0 0 4px",
123
+ fontSize: "11px",
124
+ color: colors.textMuted,
125
+ lineHeight: "1.6",
126
+ },
127
+ footerLink: {
128
+ color: colors.textMuted,
129
+ textDecoration: "underline",
130
+ },
131
+ downloadSection: {
132
+ backgroundColor: colors.cardBg,
133
+ padding: "24px 32px",
134
+ textAlign: "center" as const,
135
+ borderTop: `1px solid ${colors.border}`,
136
+ },
137
+ downloadText: {
138
+ margin: "0 0 16px",
139
+ fontSize: "14px",
140
+ color: colors.white,
141
+ },
142
+ badgeContainer: {
143
+ textAlign: "center" as const,
144
+ },
145
+ badge: {
146
+ display: "inline-block",
147
+ margin: "0 8px",
148
+ },
72
149
  };
73
150
 
74
- export function OtpEmail({ otp, email, expirationMinutes = 10 }: OtpEmailProps) {
151
+ export function OtpEmail({ otp = "123456", email = "user@example.com", expirationMinutes = 10 }: OtpEmailProps) {
75
152
  const sanitizedOtp = (typeof otp === "string" ? otp : String(otp ?? ""))
76
153
  .replace(/\s+/g, "")
77
154
  .trim();
@@ -80,45 +157,113 @@ export function OtpEmail({ otp, email, expirationMinutes = 10 }: OtpEmailProps)
80
157
  <Html lang="en">
81
158
  <Head>
82
159
  <Font
83
- fontFamily="Outfit"
160
+ fontFamily="Inter"
84
161
  fallbackFontFamily="Arial"
85
162
  webFont={{
86
- url: "https://fonts.gstatic.com/s/outfit/v11/QGYyz_MVcBeNP4NjuGObqx1XmO1I4TC1C4G-EiAou6Y.woff2",
163
+ url: "https://fonts.gstatic.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZ9hjp-Ek-_0.woff2",
87
164
  format: "woff2",
88
165
  }}
89
166
  fontWeight={400}
90
167
  fontStyle="normal"
91
168
  />
169
+ <Font
170
+ fontFamily="Inter"
171
+ fallbackFontFamily="Arial"
172
+ webFont={{
173
+ url: "https://fonts.gstatic.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuFuYAZ9hjp-Ek-_0.woff2",
174
+ format: "woff2",
175
+ }}
176
+ fontWeight={700}
177
+ fontStyle="normal"
178
+ />
92
179
  </Head>
93
180
  <Preview>Your Modelfy access code: {sanitizedOtp}</Preview>
94
181
  <Body style={styles.body}>
95
182
  <Container style={styles.container}>
96
- <Header logoUrl={modelfyConfig.logoUrl} logoAlt="Modelfy" subtitle="Access code" />
97
- <Section style={styles.content}>
183
+ {/* Header */}
184
+ <Section style={styles.header}>
185
+ <Img
186
+ src={modelfyConfig.logoUrl}
187
+ width="130"
188
+ height="auto"
189
+ alt="Modelfy"
190
+ style={styles.logo}
191
+ />
192
+ </Section>
193
+
194
+ {/* Hero Section */}
195
+ <Section style={styles.heroSection}>
196
+ <Text style={styles.heroTagline}>Access Code</Text>
197
+ <Text style={styles.heroHeading}>Sign In to Modelfy</Text>
198
+ <Text style={{ ...styles.paragraph, margin: "0 0 4px" }}>
199
+ Hi <span style={{ color: colors.white, fontWeight: 600 }}>{email}</span>, use the code below to sign in.
200
+ </Text>
98
201
  <Text style={styles.paragraph}>
99
- Hi <strong>{email}</strong>, use the code below to sign in. It will stay valid for the
100
- next <strong>{expirationMinutes} minutes</strong>.
202
+ It will stay valid for the next <span style={{ color: colors.white, fontWeight: 600 }}>{expirationMinutes} minutes</span>.
101
203
  </Text>
102
204
  <div style={styles.otpContainer}>
103
205
  <Text style={styles.otp}>{sanitizedOtp}</Text>
104
206
  </div>
207
+ </Section>
208
+
209
+ {/* Content Section */}
210
+ <Section style={styles.contentSection}>
105
211
  <Text style={styles.smallText}>
106
- If you didn't request this code, you can safely ignore this email. No one else can
107
- access your account without it.
212
+ If you didn't request this code, you can safely ignore this email.
213
+ No one else can access your account without it.
108
214
  </Text>
109
215
  <Text style={styles.smallText}>
110
- Need a hand? Reach us anytime at{" "}
216
+ Need help?{" "}
111
217
  <Link href={`mailto:${modelfyConfig.supportEmail}`} style={styles.link}>
112
218
  {modelfyConfig.supportEmail}
113
219
  </Link>
114
- .
115
220
  </Text>
116
221
  </Section>
117
- <Footer
118
- companyName={modelfyConfig.companyName}
119
- message="You received this email because someone attempted to sign in to Modelfy with this address."
120
- supportEmail={modelfyConfig.supportEmail}
121
- />
222
+
223
+ {/* Download App Section */}
224
+ <Section style={styles.downloadSection}>
225
+ <Text style={styles.downloadText}>Get the Modelfy app</Text>
226
+ <div style={styles.badgeContainer}>
227
+ <Link href={modelfyConfig.appStoreUrl} style={styles.badge}>
228
+ <Img
229
+ src={modelfyConfig.appStoreBadgeUrl}
230
+ width="120"
231
+ height="40"
232
+ alt="Download on the App Store"
233
+ />
234
+ </Link>
235
+ <Link href={modelfyConfig.playStoreUrl} style={styles.badge}>
236
+ <Img
237
+ src={modelfyConfig.playStoreBadgeUrl}
238
+ width="135"
239
+ height="40"
240
+ alt="Get it on Google Play"
241
+ />
242
+ </Link>
243
+ </div>
244
+ </Section>
245
+
246
+ {/* Footer */}
247
+ <Section style={styles.footer}>
248
+ <Img
249
+ src={modelfyConfig.logoUrl}
250
+ width="80"
251
+ height="auto"
252
+ alt="Modelfy"
253
+ style={styles.footerLogo}
254
+ />
255
+ <Text style={styles.footerText}>
256
+ © {new Date().getFullYear()} {modelfyConfig.companyName}. All rights reserved.
257
+ </Text>
258
+ <Text style={styles.footerText}>
259
+ You received this email because someone attempted to sign in to Modelfy with this address.
260
+ </Text>
261
+ <Text style={styles.footerText}>
262
+ <Link href={`${modelfyConfig.appUrl}/privacy`} style={styles.footerLink}>
263
+ Privacy Policy
264
+ </Link>
265
+ </Text>
266
+ </Section>
122
267
  </Container>
123
268
  </Body>
124
269
  </Html>