have footer on emails (#11300)

# ISSUE 

- Closes #9622

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
Nabhag Motivaras
2025-04-03 17:56:19 +05:30
committed by GitHub
parent cfae440a02
commit 7eec64b6e0
96 changed files with 9359 additions and 2120 deletions

View File

@ -1,10 +1,11 @@
import { i18n, Messages } from '@lingui/core';
import { I18nProvider } from '@lingui/react';
import { Container, Html } from '@react-email/components';
import { PropsWithChildren } from 'react';
import { BaseHead } from 'src/components/BaseHead';
import { Footer } from 'src/components/Footer';
import { Logo } from 'src/components/Logo';
import { APP_LOCALES, SOURCE_LOCALE } from 'twenty-shared/translations';
import { messages as afMessages } from '../locales/generated/af-ZA';
import { messages as arMessages } from '../locales/generated/ar-SA';
import { messages as caMessages } from '../locales/generated/ca-ES';
@ -36,12 +37,12 @@ import { messages as ukMessages } from '../locales/generated/uk-UA';
import { messages as viMessages } from '../locales/generated/vi-VN';
import { messages as zhHansMessages } from '../locales/generated/zh-CN';
import { messages as zhHantMessages } from '../locales/generated/zh-TW';
import { APP_LOCALES, SOURCE_LOCALE } from 'twenty-shared/translations';
type BaseEmailProps = PropsWithChildren<{
type BaseEmailProps = {
children: JSX.Element | JSX.Element[] | string;
width?: number;
locale: keyof typeof APP_LOCALES;
}>;
};
const messages: Record<keyof typeof APP_LOCALES, Messages> = {
en: enMessages,
@ -95,6 +96,7 @@ export const BaseEmail = ({ children, width, locale }: BaseEmailProps) => {
<Container width={width || 290}>
<Logo />
{children}
<Footer />
</Container>
</Html>
</I18nProvider>

View File

@ -1,5 +1,4 @@
import { ReactNode } from 'react';
import { Button } from '@react-email/button';
import { Button } from '@react-email/components';
import { emailTheme } from 'src/common-style';
@ -17,7 +16,7 @@ const callToActionStyle = {
type CallToActionProps = {
href: string;
value: ReactNode;
value: JSX.Element | JSX.Element[] | string;
};
export const CallToAction = ({ value, href }: CallToActionProps) => {

View File

@ -1,17 +1,22 @@
import { Column, Row } from '@react-email/components';
import { i18n } from '@lingui/core';
import { Column, Container, Row } from '@react-email/components';
import { Link } from 'src/components/Link';
import { ShadowText } from 'src/components/ShadowText';
const footerContainerStyle = {
marginTop: '12px',
};
export const Footer = () => {
return (
<>
<Container style={footerContainerStyle}>
<Row>
<Column>
<ShadowText>
<Link
href="https://twenty.com/"
value="Website"
aria-label="Visit Twenty's website"
value={i18n._('Website')}
aria-label={i18n._("Visit Twenty's website")}
/>
</ShadowText>
</Column>
@ -19,8 +24,8 @@ export const Footer = () => {
<ShadowText>
<Link
href="https://github.com/twentyhq/twenty"
value="Github"
aria-label="Visit Twenty's GitHub repository"
value={i18n._('Github')}
aria-label={i18n._("Visit Twenty's GitHub repository")}
/>
</ShadowText>
</Column>
@ -28,8 +33,8 @@ export const Footer = () => {
<ShadowText>
<Link
href="https://twenty.com/user-guide"
value="User guide"
aria-label="Read Twenty's user guide"
value={i18n._('User guide')}
aria-label={i18n._("Read Twenty's user guide")}
/>
</ShadowText>
</Column>
@ -37,19 +42,19 @@ export const Footer = () => {
<ShadowText>
<Link
href="https://docs.twenty.com/"
value="Developers"
aria-label="Visit Twenty's developer documentation"
value={i18n._('Developers')}
aria-label={i18n._("Visit Twenty's developer documentation")}
/>
</ShadowText>
</Column>
</Row>
<ShadowText>
Twenty.com Public Benefit Corporation
<br />
2261 Market Street #5275
<br />
San Francisco, CA 94114
<>
{i18n._('Twenty.com, Public Benefit Corporation')}
<br />
{i18n._('San Francisco / Paris')}
</>
</ShadowText>
</>
</Container>
);
};

View File

@ -1,9 +1,11 @@
import { Column, Container, Row } from '@react-email/components';
import React, { PropsWithChildren } from 'react';
import React from 'react';
import { emailTheme } from 'src/common-style';
type HighlightedContainerProps = PropsWithChildren;
type HighlightedContainerProps = {
children: JSX.Element | JSX.Element[] | string;
};
const highlightedContainerStyle = {
background: emailTheme.background.colors.highlight,

View File

@ -1,5 +1,5 @@
import { Text } from '@react-email/text';
import { ReactNode } from 'react';
import { Text } from '@react-email/components';
import { JSX } from 'react';
import { emailTheme } from 'src/common-style';
@ -13,7 +13,7 @@ const highlightedStyle = {
};
type HighlightedTextProps = {
value: ReactNode;
value: JSX.Element | JSX.Element[] | string | undefined;
centered?: boolean;
};

View File

@ -1,5 +1,4 @@
import { Link as EmailLink } from '@react-email/components';
import { ReactNode } from 'react';
import { emailTheme } from 'src/common-style';
@ -8,7 +7,7 @@ const linkStyle = {
};
type LinkProps = {
value: ReactNode;
value: JSX.Element | JSX.Element[] | string;
href: string;
color?: string;
};

View File

@ -1,14 +1,16 @@
import { PropsWithChildren as MainTextProps } from 'react';
import { Text } from '@react-email/text';
import { Text } from '@react-email/components';
import { emailTheme } from 'src/common-style';
type MainTextProps = {
children: JSX.Element | JSX.Element[] | string;
};
const mainTextStyle = {
fontFamily: emailTheme.font.family,
fontSize: emailTheme.font.size.md,
fontWeight: emailTheme.font.weight.regular,
color: emailTheme.font.colors.primary,
margin: '0 0 12px 0',
lineHeight: emailTheme.font.lineHeight,
};

View File

@ -1,8 +1,11 @@
import { PropsWithChildren as ShadowTextProps } from 'react';
import { Text } from '@react-email/text';
import { Text } from '@react-email/components';
import { emailTheme } from 'src/common-style';
type ShadowTextProps = {
children: JSX.Element | JSX.Element[] | string;
};
const shadowTextStyle = {
fontSize: emailTheme.font.size.sm,
fontWeight: emailTheme.font.weight.regular,

View File

@ -1,10 +1,9 @@
import { ReactNode } from 'react';
import { Heading } from '@react-email/components';
import { emailTheme } from 'src/common-style';
type SubTitleProps = {
value: ReactNode;
value: JSX.Element | JSX.Element[] | string;
};
const subTitleStyle = {

View File

@ -1,10 +1,9 @@
import { ReactNode } from 'react';
import { Heading } from '@react-email/components';
import { emailTheme } from 'src/common-style';
type TitleProps = {
value: ReactNode;
value: JSX.Element | JSX.Element[] | string;
};
const titleStyle = {

View File

@ -1,16 +1,16 @@
import { Footer } from 'src/components/Footer';
import { i18n } from '@lingui/core';
import { MainText } from 'src/components/MainText';
import { SubTitle } from 'src/components/SubTitle';
export const WhatIsTwenty = () => {
return (
<>
<SubTitle value="What is Twenty?" />
<SubTitle value={i18n._('What is Twenty?')} />
<MainText>
It's a CRM, a software to help businesses manage their customer data and
relationships efficiently.
{i18n._(
"It's a CRM, a software to help businesses manage their customer data and relationships efficiently.",
)}
</MainText>
<Footer />
</>
);
};