diff --git a/packages/twenty-website-new/public/images/home/stepper/background-shape.png b/packages/twenty-website-new/public/images/home/stepper/background-shape.png new file mode 100644 index 0000000000..bc06894a5a Binary files /dev/null and b/packages/twenty-website-new/public/images/home/stepper/background-shape.png differ diff --git a/packages/twenty-website-new/public/images/home/stepper/background.png b/packages/twenty-website-new/public/images/home/stepper/background.png new file mode 100644 index 0000000000..822dfe28fb Binary files /dev/null and b/packages/twenty-website-new/public/images/home/stepper/background.png differ diff --git a/packages/twenty-website-new/public/images/home/stepper/step-one-one.png b/packages/twenty-website-new/public/images/home/stepper/step-one-one.png new file mode 100644 index 0000000000..963e7c91fa Binary files /dev/null and b/packages/twenty-website-new/public/images/home/stepper/step-one-one.png differ diff --git a/packages/twenty-website-new/public/images/home/stepper/step-one-three.png b/packages/twenty-website-new/public/images/home/stepper/step-one-three.png new file mode 100644 index 0000000000..18fd9d94b5 Binary files /dev/null and b/packages/twenty-website-new/public/images/home/stepper/step-one-three.png differ diff --git a/packages/twenty-website-new/public/images/home/stepper/step-one-two.png b/packages/twenty-website-new/public/images/home/stepper/step-one-two.png new file mode 100644 index 0000000000..3b592dea57 Binary files /dev/null and b/packages/twenty-website-new/public/images/home/stepper/step-one-two.png differ diff --git a/packages/twenty-website-new/public/images/home/stepper/step-three-four.png b/packages/twenty-website-new/public/images/home/stepper/step-three-four.png new file mode 100644 index 0000000000..815f5f4b40 Binary files /dev/null and b/packages/twenty-website-new/public/images/home/stepper/step-three-four.png differ diff --git a/packages/twenty-website-new/public/images/home/stepper/step-three-one.png b/packages/twenty-website-new/public/images/home/stepper/step-three-one.png new file mode 100644 index 0000000000..4862c48aaf Binary files /dev/null and b/packages/twenty-website-new/public/images/home/stepper/step-three-one.png differ diff --git a/packages/twenty-website-new/public/images/home/stepper/step-three-three.png b/packages/twenty-website-new/public/images/home/stepper/step-three-three.png new file mode 100644 index 0000000000..bdfaee41c2 Binary files /dev/null and b/packages/twenty-website-new/public/images/home/stepper/step-three-three.png differ diff --git a/packages/twenty-website-new/public/images/home/stepper/step-three-two.png b/packages/twenty-website-new/public/images/home/stepper/step-three-two.png new file mode 100644 index 0000000000..aa9f12e271 Binary files /dev/null and b/packages/twenty-website-new/public/images/home/stepper/step-three-two.png differ diff --git a/packages/twenty-website-new/public/images/home/stepper/step-two-four.png b/packages/twenty-website-new/public/images/home/stepper/step-two-four.png new file mode 100644 index 0000000000..f9404c1b6a Binary files /dev/null and b/packages/twenty-website-new/public/images/home/stepper/step-two-four.png differ diff --git a/packages/twenty-website-new/public/images/home/stepper/step-two-one.png b/packages/twenty-website-new/public/images/home/stepper/step-two-one.png new file mode 100644 index 0000000000..cbd8da81cf Binary files /dev/null and b/packages/twenty-website-new/public/images/home/stepper/step-two-one.png differ diff --git a/packages/twenty-website-new/public/images/home/stepper/step-two-three.png b/packages/twenty-website-new/public/images/home/stepper/step-two-three.png new file mode 100644 index 0000000000..63e3e65c63 Binary files /dev/null and b/packages/twenty-website-new/public/images/home/stepper/step-two-three.png differ diff --git a/packages/twenty-website-new/public/images/home/stepper/step-two-two.png b/packages/twenty-website-new/public/images/home/stepper/step-two-two.png new file mode 100644 index 0000000000..4cfd743549 Binary files /dev/null and b/packages/twenty-website-new/public/images/home/stepper/step-two-two.png differ diff --git a/packages/twenty-website-new/public/images/pricing/engagement-band/overlay.png b/packages/twenty-website-new/public/images/pricing/engagement-band/overlay.png new file mode 100644 index 0000000000..4304b15fb4 Binary files /dev/null and b/packages/twenty-website-new/public/images/pricing/engagement-band/overlay.png differ diff --git a/packages/twenty-website-new/public/images/product/demo/background.png b/packages/twenty-website-new/public/images/product/demo/background.png new file mode 100644 index 0000000000..62075b9bc3 Binary files /dev/null and b/packages/twenty-website-new/public/images/product/demo/background.png differ diff --git a/packages/twenty-website-new/public/images/product/demo/kanban.png b/packages/twenty-website-new/public/images/product/demo/kanban.png new file mode 100644 index 0000000000..aaf81353a3 Binary files /dev/null and b/packages/twenty-website-new/public/images/product/demo/kanban.png differ diff --git a/packages/twenty-website-new/public/images/product/stepper/background-shape.png b/packages/twenty-website-new/public/images/product/stepper/background-shape.png new file mode 100644 index 0000000000..efd5b78f2c Binary files /dev/null and b/packages/twenty-website-new/public/images/product/stepper/background-shape.png differ diff --git a/packages/twenty-website-new/public/images/product/stepper/background.png b/packages/twenty-website-new/public/images/product/stepper/background.png new file mode 100644 index 0000000000..846ada6b20 Binary files /dev/null and b/packages/twenty-website-new/public/images/product/stepper/background.png differ diff --git a/packages/twenty-website-new/public/images/product/stepper/step-one.png b/packages/twenty-website-new/public/images/product/stepper/step-one.png new file mode 100644 index 0000000000..f3b737fde9 Binary files /dev/null and b/packages/twenty-website-new/public/images/product/stepper/step-one.png differ diff --git a/packages/twenty-website-new/public/images/product/stepper/step-three.png b/packages/twenty-website-new/public/images/product/stepper/step-three.png new file mode 100644 index 0000000000..44ecba1bc8 Binary files /dev/null and b/packages/twenty-website-new/public/images/product/stepper/step-three.png differ diff --git a/packages/twenty-website-new/public/images/product/stepper/step-two.png b/packages/twenty-website-new/public/images/product/stepper/step-two.png new file mode 100644 index 0000000000..faff8d7671 Binary files /dev/null and b/packages/twenty-website-new/public/images/product/stepper/step-two.png differ diff --git a/packages/twenty-website-new/public/images/product/tabs/background-shape.png b/packages/twenty-website-new/public/images/product/tabs/background-shape.png new file mode 100644 index 0000000000..dac49f263a Binary files /dev/null and b/packages/twenty-website-new/public/images/product/tabs/background-shape.png differ diff --git a/packages/twenty-website-new/public/images/product/tabs/background.png b/packages/twenty-website-new/public/images/product/tabs/background.png new file mode 100644 index 0000000000..cc903b05b2 Binary files /dev/null and b/packages/twenty-website-new/public/images/product/tabs/background.png differ diff --git a/packages/twenty-website-new/public/images/product/tabs/deals.png b/packages/twenty-website-new/public/images/product/tabs/deals.png new file mode 100644 index 0000000000..248883a37e Binary files /dev/null and b/packages/twenty-website-new/public/images/product/tabs/deals.png differ diff --git a/packages/twenty-website-new/public/images/product/tabs/history.png b/packages/twenty-website-new/public/images/product/tabs/history.png new file mode 100644 index 0000000000..57332618a6 Binary files /dev/null and b/packages/twenty-website-new/public/images/product/tabs/history.png differ diff --git a/packages/twenty-website-new/public/images/product/tabs/tasks.png b/packages/twenty-website-new/public/images/product/tabs/tasks.png new file mode 100644 index 0000000000..8155e441fd Binary files /dev/null and b/packages/twenty-website-new/public/images/product/tabs/tasks.png differ diff --git a/packages/twenty-website-new/public/images/product/tabs/workflow.png b/packages/twenty-website-new/public/images/product/tabs/workflow.png new file mode 100644 index 0000000000..ea28fbb379 Binary files /dev/null and b/packages/twenty-website-new/public/images/product/tabs/workflow.png differ diff --git a/packages/twenty-website-new/src/app/(home)/constants/faq.ts b/packages/twenty-website-new/src/app/(home)/constants/faq.ts new file mode 100644 index 0000000000..8cab0a6aab --- /dev/null +++ b/packages/twenty-website-new/src/app/(home)/constants/faq.ts @@ -0,0 +1,71 @@ +import { FaqDataType } from '@/sections/Faq/types'; + +export const FAQ_DATA: FaqDataType = { + illustration: { + src: 'https://app.endlesstools.io/embed/0510f6d4-e09b-4470-86f8-7fb8d9db4c45', + title: 'Endless Tools Editor', + }, + eyebrow: { + heading: { + text: 'Any Questions?', + fontFamily: 'sans', + }, + }, + heading: [ + { + text: 'Stop fighting custom.\n', + fontFamily: 'serif', + }, + { + text: ' Start building, with Twenty', + fontFamily: 'sans', + }, + ], + questions: [ + { + question: { + text: 'How long does it take to get started?', + fontFamily: 'sans', + }, + answer: { + text: "Toute personne souhaitant investir dans l'immobilier de luxe, qu'elle soit expérimentée ou novice, peut soumettre une candidature pour rejoindre le Kretz Club.", + }, + }, + { + question: { + text: 'Can I migrate from Salesforce or HubSpot?', + fontFamily: 'sans', + }, + answer: { + text: 'Yes. We provide migration tools and support to help you move your data from Salesforce, HubSpot, and other CRMs into Twenty.', + }, + }, + { + question: { + text: 'Do I need a developer to customize Twenty?', + fontFamily: 'sans', + }, + answer: { + text: 'Twenty is designed to be customizable without code. For advanced customizations, our API and documentation support developer-led extensions.', + }, + }, + { + question: { + text: 'Is my data secure?', + fontFamily: 'sans', + }, + answer: { + text: 'We take security seriously. Your data is encrypted at rest and in transit, and you can self-host to keep full control.', + }, + }, + { + question: { + text: 'How does AI usage pricing work?', + fontFamily: 'sans', + }, + answer: { + text: 'AI features are billed based on usage. See our pricing page for details and current rates.', + }, + }, + ], +}; diff --git a/packages/twenty-website-new/src/app/(home)/constants/hero.ts b/packages/twenty-website-new/src/app/(home)/constants/hero.ts index 95ed63264a..300b5b4e16 100644 --- a/packages/twenty-website-new/src/app/(home)/constants/hero.ts +++ b/packages/twenty-website-new/src/app/(home)/constants/hero.ts @@ -1,6 +1,6 @@ -import { HeroDataType } from '@/sections/Hero/types'; +import { HeroHomeDataType } from '@/sections/Hero/types'; -export const HERO_DATA: HeroDataType = { +export const HERO_DATA: HeroHomeDataType = { heading: [ { text: 'Build', fontFamily: 'sans' }, { text: ' your Enterprise CRM ', fontFamily: 'serif' }, @@ -9,4 +9,12 @@ export const HERO_DATA: HeroDataType = { body: { text: 'Twenty gives technical teams the building blocks for a custom CRM that meets complex business needs and quickly adapts as the business evolves.', }, + background: { + src: '/images/home/hero/background.png', + alt: '', + }, + foreground: { + src: '/images/home/hero/foreground.png', + alt: '', + }, }; diff --git a/packages/twenty-website-new/src/app/(home)/constants/menu.ts b/packages/twenty-website-new/src/app/(home)/constants/menu.ts new file mode 100644 index 0000000000..27fca34645 --- /dev/null +++ b/packages/twenty-website-new/src/app/(home)/constants/menu.ts @@ -0,0 +1,43 @@ +import type { MenuDataType } from '@/sections/Menu/types'; + +export const MENU_DATA: MenuDataType = { + navItems: [ + { label: 'Product', href: '/product' }, + { label: 'Pricing', href: '/pricing' }, + { label: 'Partners', href: '/partner' }, + { label: 'Why Twenty', href: '/why-twenty' }, + ], + socialLinks: [ + { + ariaLabel: 'GitHub (opens in new tab)', + href: 'https://github.com/twentyhq/twenty', + icon: 'github', + label: '39.8K', + showInDesktop: true, + showInDrawer: true, + }, + { + ariaLabel: 'Discord (opens in new tab)', + className: 'discord-link', + href: 'https://discord.gg/cx5n4Jzs57', + icon: 'discord', + label: '5.6K', + showInDesktop: true, + showInDrawer: true, + }, + { + ariaLabel: 'LinkedIn (opens in new tab)', + href: 'https://www.linkedin.com/company/twenty', + icon: 'linkedin', + showInDesktop: false, + showInDrawer: true, + }, + { + ariaLabel: 'X (opens in new tab)', + href: 'https://x.com/twentycrm', + icon: 'x', + showInDesktop: false, + showInDrawer: true, + }, + ], +}; diff --git a/packages/twenty-website-new/src/app/(home)/constants/stepper.ts b/packages/twenty-website-new/src/app/(home)/constants/stepper.ts new file mode 100644 index 0000000000..fa8710cf61 --- /dev/null +++ b/packages/twenty-website-new/src/app/(home)/constants/stepper.ts @@ -0,0 +1,101 @@ +import type { HeroStepperDataType } from '@/sections/HeroStepper/types'; + +export const STEPPER_DATA: HeroStepperDataType = { + steps: [ + { + heading: [ + { + text: 'Begin with production-grade', + fontFamily: 'serif', + }, + { + text: ' building blocks', + fontFamily: 'sans', + }, + ], + body: { + text: 'Compose your CRM and internal apps with a single extensibility toolkit. Data model, layout, and automation.', + }, + images: [ + { + src: '/images/home/stepper/step-one-one.png', + alt: 'Twenty modules for logic, data model, and layout', + }, + { + src: '/images/home/stepper/step-one-two.png', + alt: 'Twenty data model and layout building blocks', + }, + { + src: '/images/home/stepper/step-one-three.png', + alt: 'Twenty automation and extensibility toolkit', + }, + ], + }, + { + heading: [ + { + text: 'Continue iteration', + fontFamily: 'serif', + }, + { + text: ' without friction', + fontFamily: 'sans', + }, + ], + body: { + text: 'Enjoy unlimited customization using the AI coding tools you already love. Adapt your CRM to fit the way your business grows and wins.', + }, + images: [ + { + src: '/images/home/stepper/step-two-one.png', + alt: 'Twenty CRM adapted with familiar development tools', + }, + { + src: '/images/home/stepper/step-two-two.png', + alt: 'Customizing Twenty with AI-assisted coding workflows', + }, + { + src: '/images/home/stepper/step-two-three.png', + alt: 'Iterating on Twenty as your business grows', + }, + { + src: '/images/home/stepper/step-two-four.png', + alt: 'Twenty workspace tailored to your team', + }, + ], + }, + { + heading: [ + { + text: 'Stay in control with our', + fontFamily: 'serif', + }, + { + text: ' open-source software', + fontFamily: 'sans', + }, + ], + body: { + text: "Don't get locked into someone else's ecosystem. Twenty's developer experience looks like normal software, with local setup, real data, live testing, and no proprietary tooling.", + }, + images: [ + { + src: '/images/home/stepper/step-three-one.png', + alt: 'Twenty open-source CRM in a normal local development setup', + }, + { + src: '/images/home/stepper/step-three-two.png', + alt: 'Twenty developer experience with real data and live testing', + }, + { + src: '/images/home/stepper/step-three-three.png', + alt: 'Twenty without proprietary vendor lock-in', + }, + { + src: '/images/home/stepper/step-three-four.png', + alt: 'Twenty as transparent, self-hosted software', + }, + ], + }, + ], +}; diff --git a/packages/twenty-website-new/src/app/(home)/constants/three-cards-feature.ts b/packages/twenty-website-new/src/app/(home)/constants/three-cards-feature.ts index 7ce6586fd4..6ae39d14cf 100644 --- a/packages/twenty-website-new/src/app/(home)/constants/three-cards-feature.ts +++ b/packages/twenty-website-new/src/app/(home)/constants/three-cards-feature.ts @@ -17,18 +17,30 @@ export const THREE_CARDS_FEATURE_DATA: ThreeCardsFeatureCardsDataType = { body: { text: "Twenty makes it simple. It's clean, intuitive, and built to feel like Notion.", }, + image: { + src: '/images/home/three-cards-feature/familiar-interface.png', + alt: 'Familiar interface', + }, }, { heading: { text: 'Fast path to action', fontFamily: 'sans' }, body: { text: 'Smart patterns, shortcuts, and layouts make everyday tasks faster and easier to execute.', }, + image: { + src: '/images/home/three-cards-feature/fast-path.png', + alt: 'Fast path', + }, }, { heading: { text: 'Live data and AI Built', fontFamily: 'sans' }, body: { text: 'Everything updates in real time, with AI chat always ready to help you move faster.', }, + image: { + src: '/images/home/three-cards-feature/live-data.png', + alt: 'Live data', + }, }, ], }; diff --git a/packages/twenty-website-new/src/app/(home)/constants/three-cards-illustration.ts b/packages/twenty-website-new/src/app/(home)/constants/three-cards-illustration.ts index 8de854a9ed..3ab2fdedc1 100644 --- a/packages/twenty-website-new/src/app/(home)/constants/three-cards-illustration.ts +++ b/packages/twenty-website-new/src/app/(home)/constants/three-cards-illustration.ts @@ -22,6 +22,10 @@ export const THREE_CARDS_ILLUSTRATION_DATA: ThreeCardsIllustrationDataType = { role: { text: 'Head of Engineering' }, company: { text: 'Mid-Market Fintech' }, }, + illustration: { + src: 'https://app.endlesstools.io/embed/ea42603a-8644-4634-8b7a-9b7bd9a8d899', + title: 'Endless Tools Editor', + }, }, { heading: { text: 'AI for rapid iterations', fontFamily: 'sans' }, @@ -33,6 +37,10 @@ export const THREE_CARDS_ILLUSTRATION_DATA: ThreeCardsIllustrationDataType = { role: { text: 'Head of Engineering' }, company: { text: 'Mid-Market Fintech' }, }, + illustration: { + src: 'https://app.endlesstools.io/embed/99a4f00e-bb70-4192-82e1-24e9ce8cd136', + title: 'Endless Tools Editor', + }, }, { heading: { text: 'Control without drag', fontFamily: 'sans' }, @@ -44,6 +52,10 @@ export const THREE_CARDS_ILLUSTRATION_DATA: ThreeCardsIllustrationDataType = { role: { text: 'Head of Engineering' }, company: { text: 'Mid-Market Fintech' }, }, + illustration: { + src: 'https://app.endlesstools.io/embed/ba47c943-9565-412e-ae45-4ec092c149aa', + title: 'Endless Tools Editor', + }, }, ], }; diff --git a/packages/twenty-website-new/src/app/(home)/page.tsx b/packages/twenty-website-new/src/app/(home)/page.tsx index e598332292..f8176a01cb 100644 --- a/packages/twenty-website-new/src/app/(home)/page.tsx +++ b/packages/twenty-website-new/src/app/(home)/page.tsx @@ -1,11 +1,15 @@ +import { FAQ_DATA } from '@/app/(home)/constants/faq'; import { HERO_DATA } from '@/app/(home)/constants/hero'; +import { MENU_DATA } from '@/app/(home)/constants/menu'; import { PROBLEM_DATA } from '@/app/(home)/constants/problem'; import { THREE_CARDS_FEATURE_DATA } from '@/app/(home)/constants/three-cards-feature'; import { THREE_CARDS_ILLUSTRATION_DATA } from '@/app/(home)/constants/three-cards-illustration'; import { TRUSTED_BY_DATA } from '@/app/(home)/constants/trusted-by'; import { Body, Eyebrow, Heading, LinkButton } from '@/design-system/components'; import { Pages } from '@/enums/pages'; +import { Faq } from '@/sections/Faq/components'; import { Hero } from '@/sections/Hero/components'; +import { Menu } from '@/sections/Menu/components'; import { Problem } from '@/sections/Problem/components'; import { ThreeCards } from '@/sections/ThreeCards/components'; import { TrustedBy } from '@/sections/TrustedBy/components'; @@ -14,6 +18,18 @@ import { theme } from '@/theme'; export default function HomePage() { return ( <> + + + + + + + @@ -26,7 +42,10 @@ export default function HomePage() { variant="contained" /> - + @@ -67,6 +86,8 @@ export default function HomePage() { /> + {/* */} + + + + + + + + + + + + + ); } diff --git a/packages/twenty-website-new/src/app/layout.tsx b/packages/twenty-website-new/src/app/layout.tsx index 2ef8d8527b..c2300d7d59 100644 --- a/packages/twenty-website-new/src/app/layout.tsx +++ b/packages/twenty-website-new/src/app/layout.tsx @@ -1,5 +1,4 @@ import { Footer } from '@/sections/Footer/components'; -import { Menu } from '@/sections/Menu/components'; import { theme } from '@/theme'; import { cssVariables } from '@/theme/css-variables'; import { css } from '@linaria/core'; @@ -69,12 +68,6 @@ export default function RootLayout({ - - - - - - {children} diff --git a/packages/twenty-website-new/src/app/partner/constants/engagement-band.ts b/packages/twenty-website-new/src/app/partner/constants/engagement-band.ts new file mode 100644 index 0000000000..bd683d2b08 --- /dev/null +++ b/packages/twenty-website-new/src/app/partner/constants/engagement-band.ts @@ -0,0 +1,11 @@ +import type { EngagementBandDataType } from '@/sections/EngagementBand/types'; + +export const ENGAGEMENT_BAND_DATA: EngagementBandDataType = { + heading: { + text: 'Looking for a partners', + fontFamily: 'serif', + }, + body: { + text: 'Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.', + }, +}; diff --git a/packages/twenty-website-new/src/app/partner/constants/hero.ts b/packages/twenty-website-new/src/app/partner/constants/hero.ts index 7983f82b32..7f66155d7d 100644 --- a/packages/twenty-website-new/src/app/partner/constants/hero.ts +++ b/packages/twenty-website-new/src/app/partner/constants/hero.ts @@ -1,6 +1,6 @@ -import { HeroDataType } from '@/sections/Hero/types'; +import { HeroIllustrationDataType } from '@/sections/Hero/types'; -export const HERO_DATA: HeroDataType = { +export const HERO_DATA: HeroIllustrationDataType = { heading: [ { text: 'Become a ', fontFamily: 'serif' }, { text: 'Twenty Partner', fontFamily: 'sans' }, @@ -8,4 +8,8 @@ export const HERO_DATA: HeroDataType = { body: { text: "We're building the #1 open-source CRM, but we can't do it alone. Join our partner ecosystem and grow with us.", }, + illustration: { + src: 'https://app.endlesstools.io/embed/1c6c8259-3276-4cf2-84d8-6b7e87e7ec95', + title: 'Endless Tools Editor', + }, }; diff --git a/packages/twenty-website-new/src/app/partner/constants/three-cards-illustration.ts b/packages/twenty-website-new/src/app/partner/constants/three-cards-illustration.ts index 857319c75b..f91393a1ac 100644 --- a/packages/twenty-website-new/src/app/partner/constants/three-cards-illustration.ts +++ b/packages/twenty-website-new/src/app/partner/constants/three-cards-illustration.ts @@ -24,6 +24,10 @@ export const THREE_CARDS_ILLUSTRATION_DATA: ThreeCardsIllustrationDataType = { { text: 'Soon: earn revenue' }, ], attribution: undefined, + illustration: { + src: 'https://app.endlesstools.io/embed/627cb43a-5b5f-41a7-9642-26e66b9c4890', + title: 'Endless Tools Editor', + }, }, { heading: { text: 'Content & Community Partners', fontFamily: 'sans' }, @@ -36,6 +40,10 @@ export const THREE_CARDS_ILLUSTRATION_DATA: ThreeCardsIllustrationDataType = { { text: 'Marketing assets & brand resources' }, ], attribution: undefined, + illustration: { + src: 'https://app.endlesstools.io/embed/4ef11ab1-d013-46dd-bf2e-cbf913370a8a', + title: 'Endless Tools Editor', + }, }, { heading: { text: 'Solutions Partners', fontFamily: 'sans' }, @@ -48,6 +56,10 @@ export const THREE_CARDS_ILLUSTRATION_DATA: ThreeCardsIllustrationDataType = { { text: 'Dedicated partner support' }, ], attribution: undefined, + illustration: { + src: 'https://app.endlesstools.io/embed/624e9b40-f52c-4da2-9a2e-72d1fb2b5356', + title: 'Endless Tools Editor', + }, }, ], }; diff --git a/packages/twenty-website-new/src/app/partner/page.tsx b/packages/twenty-website-new/src/app/partner/page.tsx index 1fe36e8668..61f7e8526c 100644 --- a/packages/twenty-website-new/src/app/partner/page.tsx +++ b/packages/twenty-website-new/src/app/partner/page.tsx @@ -1,9 +1,15 @@ +import { FAQ_DATA } from '@/app/(home)/constants/faq'; +import { MENU_DATA } from '@/app/(home)/constants/menu'; import { TRUSTED_BY_DATA } from '@/app/(home)/constants/trusted-by'; +import { ENGAGEMENT_BAND_DATA } from '@/app/partner/constants/engagement-band'; import { HERO_DATA } from '@/app/partner/constants/hero'; import { THREE_CARDS_ILLUSTRATION_DATA } from '@/app/partner/constants/three-cards-illustration'; import { Body, Eyebrow, Heading, LinkButton } from '@/design-system/components'; import { Pages } from '@/enums/pages'; +import { EngagementBand } from '@/sections/EngagementBand/components'; +import { Faq } from '@/sections/Faq/components'; import { Hero } from '@/sections/Hero/components'; +import { Menu } from '@/sections/Menu/components'; import { ThreeCards } from '@/sections/ThreeCards/components'; import { TrustedBy } from '@/sections/TrustedBy/components'; import { theme } from '@/theme'; @@ -11,6 +17,18 @@ import { theme } from '@/theme'; export default function PartnerPage() { return ( <> + + + + + + + @@ -31,8 +49,7 @@ export default function PartnerPage() { /> @@ -45,8 +62,31 @@ export default function PartnerPage() { /> + + + + + + + + + + + + - + + + + + + + + + + + + + ); } diff --git a/packages/twenty-website-new/src/app/pricing/constants/engagement-band.ts b/packages/twenty-website-new/src/app/pricing/constants/engagement-band.ts new file mode 100644 index 0000000000..0dd078380b --- /dev/null +++ b/packages/twenty-website-new/src/app/pricing/constants/engagement-band.ts @@ -0,0 +1,11 @@ +import type { EngagementBandDataType } from '@/sections/EngagementBand/types'; + +export const ENGAGEMENT_BAND_DATA: EngagementBandDataType = { + heading: { + text: 'Want a tailored made plan?', + fontFamily: 'serif', + }, + body: { + text: 'Help customers implement, customize,and succeed with Twenty. Combine sales and services to grow your business.', + }, +}; diff --git a/packages/twenty-website-new/src/app/pricing/constants/hero.ts b/packages/twenty-website-new/src/app/pricing/constants/hero.ts index 7a8abeb9f3..26d0541ddb 100644 --- a/packages/twenty-website-new/src/app/pricing/constants/hero.ts +++ b/packages/twenty-website-new/src/app/pricing/constants/hero.ts @@ -1,6 +1,6 @@ -import { HeroDataType } from '@/sections/Hero/types'; +import { HeroBaseDataType } from '@/sections/Hero/types'; -export const HERO_DATA: HeroDataType = { +export const HERO_DATA: HeroBaseDataType = { heading: [ { text: 'A pricing that scales ', fontFamily: 'serif' }, { text: 'with your need', fontFamily: 'sans' }, diff --git a/packages/twenty-website-new/src/app/pricing/constants/plans.ts b/packages/twenty-website-new/src/app/pricing/constants/plans.ts new file mode 100644 index 0000000000..b68034ea87 --- /dev/null +++ b/packages/twenty-website-new/src/app/pricing/constants/plans.ts @@ -0,0 +1,131 @@ +const PRO_HEADING = { fontFamily: 'sans' as const, text: 'Pro' }; +const ORGANIZATION_HEADING = { + fontFamily: 'sans' as const, + text: 'Organization', +}; + +const PRO_ILLUSTRATION = { + src: 'https://app.endlesstools.io/embed/207b0732-c6ef-414e-add5-462e68689a2e', + title: 'Endless Tools Editor', +}; + +const ORGANIZATION_ILLUSTRATION = { + src: 'https://app.endlesstools.io/embed/588638be-e22e-4467-b701-3f36e900613d', + title: 'Endless Tools Editor', +}; + +const PRO_FEATURES_TITLE = { text: 'Key Features' }; +const ORGANIZATION_FEATURES_TITLE = { text: 'everything in pro +' }; + +const PRO_BULLETS_DEFAULT = [ + { text: 'Full customisation' }, + { text: 'AI Agents with custom skills' }, + { text: '1K automation credits' }, + { text: 'Standard support' }, + { text: 'Add-on AI (1-month trial)' }, +]; + +const PRO_BULLETS_SELF_HOST_MONTHLY = [ + { text: 'Full customisation' }, + { text: 'AI Agents with custom skills' }, + { text: 'Standard support' }, + { text: 'Add-on AI (1-month trial)' }, +]; + +const PRO_BULLETS_SELF_HOST_YEARLY = [ + { text: 'Full customisation' }, + { text: 'AI Agents with custom skills' }, + { text: 'Standard support' }, + { text: 'Add-on AI (1-month trial)' }, +]; + +const ORGANIZATION_BULLETS = [ + { text: 'Roles & Permissions' }, + { text: 'SAML/OIDC SSO' }, + { text: '2K automation credits' }, + { text: 'Priority support' }, + { text: 'Add-on AI full time' }, +]; + +import type { PlansDataType } from '@/sections/Plans/types'; + +export const PLANS_DATA = { + organization: { + cells: { + cloud: { + monthly: { + featureBullets: ORGANIZATION_BULLETS, + price: { + body: { text: '/month, paid monthly' }, + heading: { fontFamily: 'sans', text: '$25 USD' }, + }, + }, + yearly: { + featureBullets: ORGANIZATION_BULLETS, + price: { + body: { text: '/month, paid yearly' }, + heading: { fontFamily: 'sans', text: '$19 USD' }, + }, + }, + }, + selfHost: { + monthly: { + featureBullets: ORGANIZATION_BULLETS, + price: { + body: { text: '/month, paid monthly' }, + heading: { fontFamily: 'sans', text: '$25 USD' }, + }, + }, + yearly: { + featureBullets: ORGANIZATION_BULLETS, + price: { + body: { text: '/month, paid yearly' }, + heading: { fontFamily: 'sans', text: '$19 USD' }, + }, + }, + }, + }, + featuresTitle: ORGANIZATION_FEATURES_TITLE, + heading: ORGANIZATION_HEADING, + illustration: ORGANIZATION_ILLUSTRATION, + }, + pro: { + cells: { + cloud: { + monthly: { + featureBullets: PRO_BULLETS_DEFAULT, + price: { + body: { text: '/month, paid monthly' }, + heading: { fontFamily: 'sans', text: '$12 USD' }, + }, + }, + yearly: { + featureBullets: PRO_BULLETS_DEFAULT, + price: { + body: { text: '/month, paid yearly' }, + heading: { fontFamily: 'sans', text: '$9 USD' }, + }, + }, + }, + selfHost: { + monthly: { + featureBullets: PRO_BULLETS_SELF_HOST_MONTHLY, + price: { + body: { text: '/month, paid monthly' }, + heading: { fontFamily: 'sans', text: '$0 USD' }, + }, + }, + yearly: { + featureBullets: PRO_BULLETS_SELF_HOST_YEARLY, + price: { + body: { text: '/month, paid yearly' }, + heading: { fontFamily: 'sans', text: '$0 USD' }, + }, + }, + }, + }, + featuresTitle: PRO_FEATURES_TITLE, + heading: PRO_HEADING, + illustration: PRO_ILLUSTRATION, + }, +} satisfies PlansDataType; diff --git a/packages/twenty-website-new/src/app/pricing/page.tsx b/packages/twenty-website-new/src/app/pricing/page.tsx index 3c119728de..2274edb056 100644 --- a/packages/twenty-website-new/src/app/pricing/page.tsx +++ b/packages/twenty-website-new/src/app/pricing/page.tsx @@ -1,15 +1,86 @@ +import { FAQ_DATA } from '@/app/(home)/constants/faq'; +import { MENU_DATA } from '@/app/(home)/constants/menu'; +import { ENGAGEMENT_BAND_DATA } from '@/app/partner/constants/engagement-band'; import { HERO_DATA } from '@/app/pricing/constants/hero'; +import { Eyebrow, LinkButton } from '@/design-system/components'; import { Pages } from '@/enums/pages'; +import { EngagementBand } from '@/sections/EngagementBand/components'; +import { Faq } from '@/sections/Faq/components'; import { Hero } from '@/sections/Hero/components'; +import { Menu } from '@/sections/Menu/components'; +import { Plans } from '@/sections/Plans/components'; import { theme } from '@/theme'; export default function PricingPage() { return ( <> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); } diff --git a/packages/twenty-website-new/src/app/product/constants/demo.ts b/packages/twenty-website-new/src/app/product/constants/demo.ts new file mode 100644 index 0000000000..026d55ab78 --- /dev/null +++ b/packages/twenty-website-new/src/app/product/constants/demo.ts @@ -0,0 +1,24 @@ +import type { DemoDataType } from '@/sections/Demo/types'; + +export const DEMO_DATA: DemoDataType = { + eyebrow: { + heading: { + text: 'Try it live', + fontFamily: 'sans', + }, + }, + heading: [ + { + text: 'A demo worth a', + fontFamily: 'serif', + }, + { + text: ' thousand words', + fontFamily: 'sans', + }, + ], + image: { + src: '/images/product/demo/kanban.png', + alt: '', + }, +}; diff --git a/packages/twenty-website-new/src/app/product/constants/hero.ts b/packages/twenty-website-new/src/app/product/constants/hero.ts index 9e0eeec7c7..989fed27ca 100644 --- a/packages/twenty-website-new/src/app/product/constants/hero.ts +++ b/packages/twenty-website-new/src/app/product/constants/hero.ts @@ -1,6 +1,6 @@ -import { HeroDataType } from '@/sections/Hero/types'; +import { HeroIllustrationDataType } from '@/sections/Hero/types'; -export const HERO_DATA: HeroDataType = { +export const HERO_DATA: HeroIllustrationDataType = { heading: [ { text: 'The CRM that moves ', fontFamily: 'serif' }, { text: 'as fast as you do', fontFamily: 'sans' }, @@ -8,4 +8,8 @@ export const HERO_DATA: HeroDataType = { body: { text: 'Modern interface. AI assistance. All the features you need, ready from day one.', }, + illustration: { + src: 'https://app.endlesstools.io/embed/0bcf3ac2-58cf-4cd5-90bd-e8fada9816a9', + title: 'Endless Tools Editor', + }, }; diff --git a/packages/twenty-website-new/src/app/product/constants/stepper.ts b/packages/twenty-website-new/src/app/product/constants/stepper.ts new file mode 100644 index 0000000000..22fdbd4fbc --- /dev/null +++ b/packages/twenty-website-new/src/app/product/constants/stepper.ts @@ -0,0 +1,67 @@ +import type { ProductStepperDataType } from '@/sections/ProductStepper/types'; + +export const STEPPER_DATA: ProductStepperDataType = { + eyebrow: { + heading: { + text: 'Customization', + fontFamily: 'sans', + }, + }, + heading: [ + { + text: 'Go the extra mile', + fontFamily: 'serif', + }, + { + text: ' with no-code', + fontFamily: 'sans', + }, + ], + body: { + text: 'Need a quick change? Skip the engineering ticket. Customize your workspace in minutes.', + }, + steps: [ + { + icon: 'users', + heading: { + text: 'Data model', + fontFamily: 'sans', + }, + body: { + text: 'Add objects and fields', + }, + image: { + src: '/images/product/stepper/step-one.png', + alt: 'Twenty data model: add objects and fields', + }, + }, + { + icon: 'check', + heading: { + text: 'Automation', + fontFamily: 'sans', + }, + body: { + text: 'Create a workflow', + }, + image: { + src: '/images/product/stepper/step-two.png', + alt: 'Twenty automation: create a workflow', + }, + }, + { + icon: 'eye', + heading: { + text: 'Layout', + fontFamily: 'sans', + }, + body: { + text: 'Tailor record pages, menus, and views', + }, + image: { + src: '/images/product/stepper/step-three.png', + alt: 'Twenty layout: record pages, menus, and views', + }, + }, + ], +}; diff --git a/packages/twenty-website-new/src/app/product/constants/tabs.ts b/packages/twenty-website-new/src/app/product/constants/tabs.ts new file mode 100644 index 0000000000..4210515744 --- /dev/null +++ b/packages/twenty-website-new/src/app/product/constants/tabs.ts @@ -0,0 +1,65 @@ +import type { TabsDataType } from '@/sections/Tabs/types'; + +export const TABS_DATA: TabsDataType = { + eyebrow: { + heading: { + text: 'AI & Automation', + fontFamily: 'sans', + }, + }, + heading: [ + { + text: 'AI that actually\nhelps you ', + fontFamily: 'serif', + }, + { + text: 'work faster', + fontFamily: 'sans', + }, + ], + body: { + text: 'The AI understands your CRM and takes action.', + }, + tabs: [ + { + body: { + text: 'Show me all deals closing this month', + }, + icon: 'search', + image: { + src: '/images/product/tabs/deals.png', + alt: 'Deals view', + }, + }, + { + body: { + text: 'Create follow-up tasks for my top 10 accounts', + }, + icon: 'eye', + image: { + src: '/images/product/tabs/tasks.png', + alt: 'Tasks view', + }, + }, + { + body: { + text: "Summarize this customer's history", + }, + icon: 'edit', + image: { + src: '/images/product/tabs/history.png', + alt: 'History view', + }, + }, + { + body: { + text: 'Create a workflow that send an email sequence', + }, + icon: 'check', + image: { + src: '/images/product/tabs/workflow.png', + alt: 'Workflow view', + }, + }, + ], +}; diff --git a/packages/twenty-website-new/src/app/product/constants/three-cards.ts b/packages/twenty-website-new/src/app/product/constants/three-cards.ts index 57902ca01c..563c3ea41b 100644 --- a/packages/twenty-website-new/src/app/product/constants/three-cards.ts +++ b/packages/twenty-website-new/src/app/product/constants/three-cards.ts @@ -17,6 +17,10 @@ export const THREE_CARDS_ILLUSTRATION_DATA: ThreeCardsIllustrationDataType = { }, benefits: undefined, attribution: undefined, + illustration: { + src: 'https://app.endlesstools.io/embed/21767ad6-67f4-4941-a668-6cf772c27621', + title: 'Endless Tools Editor', + }, }, { heading: { text: 'Real-time data', fontFamily: 'sans' }, @@ -25,6 +29,10 @@ export const THREE_CARDS_ILLUSTRATION_DATA: ThreeCardsIllustrationDataType = { }, benefits: undefined, attribution: undefined, + illustration: { + src: 'https://app.endlesstools.io/embed/9c504c9c-46f9-423c-98b3-2e840ddb3b1e', + title: 'Endless Tools Editor', + }, }, { heading: { text: 'Stay in Flow', fontFamily: 'sans' }, @@ -33,6 +41,10 @@ export const THREE_CARDS_ILLUSTRATION_DATA: ThreeCardsIllustrationDataType = { }, benefits: undefined, attribution: undefined, + illustration: { + src: 'https://app.endlesstools.io/embed/8d577747-2718-4e7e-87a6-dd9c334f3903', + title: 'Endless Tools Editor', + }, }, ], }; diff --git a/packages/twenty-website-new/src/app/product/page.tsx b/packages/twenty-website-new/src/app/product/page.tsx index 681c9be58c..f44c91f59b 100644 --- a/packages/twenty-website-new/src/app/product/page.tsx +++ b/packages/twenty-website-new/src/app/product/page.tsx @@ -1,9 +1,17 @@ +import { FAQ_DATA } from '@/app/(home)/constants/faq'; +import { MENU_DATA } from '@/app/(home)/constants/menu'; import { TRUSTED_BY_DATA } from '@/app/(home)/constants/trusted-by'; +import { DEMO_DATA } from '@/app/product/constants/demo'; import { HERO_DATA } from '@/app/product/constants/hero'; +import { TABS_DATA } from '@/app/product/constants/tabs'; import { THREE_CARDS_ILLUSTRATION_DATA } from '@/app/product/constants/three-cards'; import { Body, Eyebrow, Heading, LinkButton } from '@/design-system/components'; import { Pages } from '@/enums/pages'; +import { Demo } from '@/sections/Demo/components'; +import { Faq } from '@/sections/Faq/components'; import { Hero } from '@/sections/Hero/components'; +import { Menu } from '@/sections/Menu/components'; +import { Tabs } from '@/sections/Tabs/components'; import { ThreeCards } from '@/sections/ThreeCards/components'; import { TrustedBy } from '@/sections/TrustedBy/components'; import { theme } from '@/theme'; @@ -11,6 +19,18 @@ import { theme } from '@/theme'; export default function ProductPage() { return ( <> + + + + + + + @@ -24,37 +44,89 @@ export default function ProductPage() { /> - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + {/* */} + + + + + + + + + + + + + + + + + + + + + ); } diff --git a/packages/twenty-website-new/src/app/why-twenty/constants/hero.ts b/packages/twenty-website-new/src/app/why-twenty/constants/hero.ts index 7db806d429..4ce36be1c6 100644 --- a/packages/twenty-website-new/src/app/why-twenty/constants/hero.ts +++ b/packages/twenty-website-new/src/app/why-twenty/constants/hero.ts @@ -1,6 +1,6 @@ -import { HeroDataType } from '@/sections/Hero/types'; +import { HeroWhyTwentyDataType } from '@/sections/Hero/types'; -export const HERO_DATA: HeroDataType = { +export const HERO_DATA: HeroWhyTwentyDataType = { heading: [ { text: 'The future of CRM is built, ', fontFamily: 'serif' }, { text: 'not bought.', fontFamily: 'sans' }, @@ -8,4 +8,12 @@ export const HERO_DATA: HeroDataType = { body: { text: 'Most packaged software makes companies more similar. CRM is no exception. AI is turning software into a commodity. That does not make your go-to-market a commodity. It makes it the battleground.', }, + image: { + src: '/images/why-twenty/hero/background.png', + alt: '', + }, + illustration: { + src: 'https://app.endlesstools.io/embed/479566da-0f55-44ef-99fe-90350aa88b9c', + title: 'Endless Tools Editor', + }, }; diff --git a/packages/twenty-website-new/src/app/why-twenty/page.tsx b/packages/twenty-website-new/src/app/why-twenty/page.tsx index 69a3b2550d..6fb441d33c 100644 --- a/packages/twenty-website-new/src/app/why-twenty/page.tsx +++ b/packages/twenty-website-new/src/app/why-twenty/page.tsx @@ -1,14 +1,37 @@ +import { MENU_DATA } from '@/app/(home)/constants/menu'; import { HERO_DATA } from '@/app/why-twenty/constants/hero'; import { Pages } from '@/enums/pages'; import { Hero } from '@/sections/Hero/components'; +import { Menu } from '@/sections/Menu/components'; import { theme } from '@/theme'; export default function WhyTwentyPage() { return ( - - - - - + <> + + + + + + + + + + + + + ); } diff --git a/packages/twenty-website-new/src/icons/index.ts b/packages/twenty-website-new/src/icons/index.ts index 0b42ff0411..5fb9c89d62 100644 --- a/packages/twenty-website-new/src/icons/index.ts +++ b/packages/twenty-website-new/src/icons/index.ts @@ -1,4 +1,13 @@ export { CLIENT_ICONS, FlexportIcon, ZapierIcon } from "./clients"; +export { + CheckIcon, + EditIcon, + EyeIcon, + INFORMATIVE_ICONS, + SearchIcon, + UsersIcon, + type InformativeIconProps, +} from "./informative"; export { ArrowLeftIcon } from "./functional/ArrowLeft"; export { ArrowRightIcon } from "./functional/ArrowRight"; export { ArrowRightUpIcon } from "./functional/ArrowRightUp"; @@ -9,7 +18,11 @@ export { PlusIcon } from "./functional/Plus"; export { RectangleFillIcon } from "./functional/RectangleFill"; export { RectangleOutlineIcon } from "./functional/RectangleOutline"; export { Logo } from "./logo/Logo"; -export { DiscordIcon } from "./social/Discord"; -export { GitHubIcon } from "./social/GitHub"; -export { LinkedInIcon } from "./social/LinkedIn"; -export { XIcon } from "./social/X"; +export { + DiscordIcon, + GitHubIcon, + LinkedInIcon, + SOCIAL_ICONS, + XIcon, + type SocialIconProps, +} from './social'; diff --git a/packages/twenty-website-new/src/icons/informative/Check.tsx b/packages/twenty-website-new/src/icons/informative/Check.tsx new file mode 100644 index 0000000000..3801583f05 --- /dev/null +++ b/packages/twenty-website-new/src/icons/informative/Check.tsx @@ -0,0 +1,25 @@ +type CheckIconProps = { size: number; color: string }; + +export function CheckIcon({ size, color }: CheckIconProps) { + return ( + + + + + ); +} diff --git a/packages/twenty-website-new/src/icons/informative/Edit.tsx b/packages/twenty-website-new/src/icons/informative/Edit.tsx new file mode 100644 index 0000000000..933e26bd48 --- /dev/null +++ b/packages/twenty-website-new/src/icons/informative/Edit.tsx @@ -0,0 +1,30 @@ +'use client'; + +import { useId } from 'react'; + +type EditIconProps = { size: number; color: string }; + +export function EditIcon({ size, color }: EditIconProps) { + const clipPathId = useId().replace(/:/g, ''); + + return ( + + + + + + + + + + + + ); +} diff --git a/packages/twenty-website-new/src/icons/informative/Eye.tsx b/packages/twenty-website-new/src/icons/informative/Eye.tsx new file mode 100644 index 0000000000..2cb8aefa79 --- /dev/null +++ b/packages/twenty-website-new/src/icons/informative/Eye.tsx @@ -0,0 +1,27 @@ +type EyeIconProps = { size: number; color: string }; + +export function EyeIcon({ size, color }: EyeIconProps) { + const height = (size * 13) / 16; + + return ( + + + + + ); +} diff --git a/packages/twenty-website-new/src/icons/informative/Search.tsx b/packages/twenty-website-new/src/icons/informative/Search.tsx new file mode 100644 index 0000000000..1da1f56654 --- /dev/null +++ b/packages/twenty-website-new/src/icons/informative/Search.tsx @@ -0,0 +1,29 @@ +type SearchIconProps = { size: number; color: string }; + +export function SearchIcon({ size, color }: SearchIconProps) { + return ( + + + + + ); +} diff --git a/packages/twenty-website-new/src/icons/informative/index.ts b/packages/twenty-website-new/src/icons/informative/index.ts new file mode 100644 index 0000000000..5c3ad32d33 --- /dev/null +++ b/packages/twenty-website-new/src/icons/informative/index.ts @@ -0,0 +1,29 @@ +import { createElement, type ComponentType } from 'react'; +import { CheckIcon } from './Check'; +import { EditIcon } from './Edit'; +import { EyeIcon } from './Eye'; +import { SearchIcon } from './Search'; +import { UsersIcon } from './Users'; + +export { CheckIcon } from './Check'; +export { EditIcon } from './Edit'; +export { EyeIcon } from './Eye'; +export { SearchIcon } from './Search'; +export { UsersIcon } from './Users'; + +export type InformativeIconProps = { size: number; color: string }; + +function InformativeUsersIcon({ size, color }: InformativeIconProps) { + return createElement(UsersIcon, { size, fillColor: color }); +} + +export const INFORMATIVE_ICONS: Record< + string, + ComponentType +> = { + check: CheckIcon, + edit: EditIcon, + eye: EyeIcon, + search: SearchIcon, + users: InformativeUsersIcon, +}; diff --git a/packages/twenty-website-new/src/icons/social/index.ts b/packages/twenty-website-new/src/icons/social/index.ts new file mode 100644 index 0000000000..634f47f7c0 --- /dev/null +++ b/packages/twenty-website-new/src/icons/social/index.ts @@ -0,0 +1,19 @@ +import type { ComponentType } from 'react'; +import { DiscordIcon } from './Discord'; +import { GitHubIcon } from './GitHub'; +import { LinkedInIcon } from './LinkedIn'; +import { XIcon } from './X'; + +export { DiscordIcon } from './Discord'; +export { GitHubIcon } from './GitHub'; +export { LinkedInIcon } from './LinkedIn'; +export { XIcon } from './X'; + +export type SocialIconProps = { size: number; fillColor: string }; + +export const SOCIAL_ICONS: Record> = { + discord: DiscordIcon, + github: GitHubIcon, + linkedin: LinkedInIcon, + x: XIcon, +}; diff --git a/packages/twenty-website-new/src/sections/Demo/components/Cta/Cta.tsx b/packages/twenty-website-new/src/sections/Demo/components/Cta/Cta.tsx new file mode 100644 index 0000000000..09c2942cd7 --- /dev/null +++ b/packages/twenty-website-new/src/sections/Demo/components/Cta/Cta.tsx @@ -0,0 +1,16 @@ +import { theme } from '@/theme'; +import { styled } from '@linaria/react'; +import type { ReactNode } from 'react'; + +const CTAsContainer = styled.div` + display: flex; + flex-wrap: wrap; + gap: ${theme.spacing(4)}; + justify-content: center; +`; + +type CtaProps = { children: ReactNode }; + +export function Cta({ children }: CtaProps) { + return {children}; +} diff --git a/packages/twenty-website-new/src/sections/Demo/components/Heading/Heading.tsx b/packages/twenty-website-new/src/sections/Demo/components/Heading/Heading.tsx new file mode 100644 index 0000000000..2f6047da9b --- /dev/null +++ b/packages/twenty-website-new/src/sections/Demo/components/Heading/Heading.tsx @@ -0,0 +1,20 @@ +import { Heading as BaseHeading } from '@/design-system/components'; +import type { HeadingType } from '@/design-system/components/Heading/types/Heading'; +import { theme } from '@/theme'; +import { styled } from '@linaria/react'; + +const StyledHeading = styled(BaseHeading)` + max-width: 360px; + + @media (min-width: ${theme.breakpoints.md}px) { + max-width: 672px; + } +`; + +type HeadingProps = { + segments: HeadingType[]; +}; + +export function Heading({ segments }: HeadingProps) { + return ; +} diff --git a/packages/twenty-website-new/src/sections/Demo/components/Root/Root.tsx b/packages/twenty-website-new/src/sections/Demo/components/Root/Root.tsx new file mode 100644 index 0000000000..d0d26c5892 --- /dev/null +++ b/packages/twenty-website-new/src/sections/Demo/components/Root/Root.tsx @@ -0,0 +1,89 @@ +import { Container } from '@/design-system/components'; +import { theme } from '@/theme'; +import { css } from '@linaria/core'; +import { styled } from '@linaria/react'; +import NextImage from 'next/image'; +import type { ReactNode } from 'react'; + +const RootWrapper = styled.div` + display: grid; + grid-template-columns: 1fr; + position: relative; + width: 100%; +`; + +const BackgroundLayer = styled.div` + align-self: stretch; + grid-column: 1; + grid-row: 1; + opacity: 0.6; + pointer-events: none; + position: relative; + width: 100%; + z-index: 0; +`; + +const PatternLayer = styled.div` + bottom: 0; + height: 60%; + left: 50%; + position: absolute; + transform: translateX(-50%); + width: 100%; +`; + +const patternImageClassName = css` + object-fit: cover; + object-position: center top; +`; + +const StyledSection = styled.section` + grid-column: 1; + grid-row: 1; + position: relative; + width: 100%; + z-index: 1; +`; + +const StyledContainer = styled(Container)` + display: grid; + grid-template-columns: 1fr; + justify-items: center; + padding-bottom: ${theme.spacing(16)}; + padding-left: ${theme.spacing(4)}; + padding-right: ${theme.spacing(4)}; + padding-top: ${theme.spacing(16)}; + row-gap: ${theme.spacing(6)}; + text-align: center; + width: 100%; + + @media (min-width: ${theme.breakpoints.md}px) { + padding-bottom: ${theme.spacing(24)}; + padding-left: ${theme.spacing(10)}; + padding-right: ${theme.spacing(10)}; + padding-top: ${theme.spacing(24)}; + } +`; + +type RootProps = { children: ReactNode }; + +export function Root({ children }: RootProps) { + return ( + + + + + + + + {children} + + + ); +} diff --git a/packages/twenty-website-new/src/sections/Demo/components/Screenshot/Screenshot.tsx b/packages/twenty-website-new/src/sections/Demo/components/Screenshot/Screenshot.tsx new file mode 100644 index 0000000000..6ddbe7d2b7 --- /dev/null +++ b/packages/twenty-website-new/src/sections/Demo/components/Screenshot/Screenshot.tsx @@ -0,0 +1,42 @@ +import type { ImageType } from '@/design-system/components/Image/types/Image'; +import { theme } from '@/theme'; +import { css } from '@linaria/core'; +import { styled } from '@linaria/react'; +import NextImage from 'next/image'; + +const ScreenshotRoot = styled.div` + aspect-ratio: 136 / 69; + border-radius: ${theme.radius(4)}; + overflow: hidden; + position: relative; + width: 100%; + max-width: 800px; + margin-top: ${theme.spacing(12)}; + margin-bottom: ${theme.spacing(11)}; + + @media (min-width: ${theme.breakpoints.md}px) { + border-radius: ${theme.radius(6)}; + margin-top: ${theme.spacing(19)}; + margin-bottom: ${theme.spacing(11)}; + } +`; + +const screenshotImageClassName = css` + object-fit: cover; +`; + +type ScreenshotProps = { image: ImageType }; + +export function Screenshot({ image }: ScreenshotProps) { + return ( + + + + ); +} diff --git a/packages/twenty-website-new/src/sections/Demo/components/index.ts b/packages/twenty-website-new/src/sections/Demo/components/index.ts new file mode 100644 index 0000000000..071af37668 --- /dev/null +++ b/packages/twenty-website-new/src/sections/Demo/components/index.ts @@ -0,0 +1,6 @@ +import { Cta } from './Cta/Cta'; +import { Heading } from './Heading/Heading'; +import { Root } from './Root/Root'; +import { Screenshot } from './Screenshot/Screenshot'; + +export const Demo = { Cta, Heading, Root, Screenshot }; diff --git a/packages/twenty-website-new/src/sections/Demo/types/DemoData.ts b/packages/twenty-website-new/src/sections/Demo/types/DemoData.ts new file mode 100644 index 0000000000..c41a421e24 --- /dev/null +++ b/packages/twenty-website-new/src/sections/Demo/types/DemoData.ts @@ -0,0 +1,9 @@ +import type { EyebrowType } from '@/design-system/components/Eyebrow/types/Eyebrow'; +import type { HeadingType } from '@/design-system/components/Heading/types/Heading'; +import type { ImageType } from '@/design-system/components/Image/types/Image'; + +export type DemoDataType = { + eyebrow: EyebrowType; + heading: HeadingType[]; + image: ImageType; +}; diff --git a/packages/twenty-website-new/src/sections/Demo/types/index.ts b/packages/twenty-website-new/src/sections/Demo/types/index.ts new file mode 100644 index 0000000000..b2d705eeb3 --- /dev/null +++ b/packages/twenty-website-new/src/sections/Demo/types/index.ts @@ -0,0 +1 @@ +export type { DemoDataType } from './DemoData'; diff --git a/packages/twenty-website-new/src/sections/EngagementBand/EngagementBandShape.tsx b/packages/twenty-website-new/src/sections/EngagementBand/EngagementBandShape.tsx new file mode 100644 index 0000000000..ac777ac571 --- /dev/null +++ b/packages/twenty-website-new/src/sections/EngagementBand/EngagementBandShape.tsx @@ -0,0 +1,34 @@ +const ENGAGEMENT_BAND_SHAPE_PATH = + 'M0 4a4 4 0 0 1 4-4h1352a4 4 0 0 1 4 4v89.502a8 8 0 0 1-2.57 5.873l-35.13 32.498a8 8 0 0 1-5.43 2.127H4a4 4 0 0 1-4-4z'; + +type EngagementBandShapeProps = { + fillColor: string; +}; + +export function EngagementBandShape({ fillColor }: EngagementBandShapeProps) { + return ( +
+ + + +
+ ); +} diff --git a/packages/twenty-website-new/src/sections/EngagementBand/components/Actions/Actions.tsx b/packages/twenty-website-new/src/sections/EngagementBand/components/Actions/Actions.tsx new file mode 100644 index 0000000000..bb7d8b9bb7 --- /dev/null +++ b/packages/twenty-website-new/src/sections/EngagementBand/components/Actions/Actions.tsx @@ -0,0 +1,24 @@ +import { theme } from '@/theme'; +import { styled } from '@linaria/react'; +import type { ReactNode } from 'react'; + +const StyledActions = styled.div` + display: grid; + grid-template-columns: 1fr; + justify-items: start; + min-width: 0; + position: relative; + z-index: 1; + + @media (min-width: ${theme.breakpoints.md}px) { + justify-items: end; + } +`; + +type ActionsProps = { + children: ReactNode; +}; + +export function Actions({ children }: ActionsProps) { + return {children}; +} diff --git a/packages/twenty-website-new/src/sections/EngagementBand/components/Body/Body.tsx b/packages/twenty-website-new/src/sections/EngagementBand/components/Body/Body.tsx new file mode 100644 index 0000000000..2528a4a3ab --- /dev/null +++ b/packages/twenty-website-new/src/sections/EngagementBand/components/Body/Body.tsx @@ -0,0 +1,16 @@ +import { Body as BaseBody } from '@/design-system/components'; +import type { BodyType } from '@/design-system/components/Body/types/Body'; +import { styled } from '@linaria/react'; + +const StyledBody = styled(BaseBody)` + max-width: 668px; + opacity: 0.9; +`; + +type BodyProps = { + body: BodyType; +}; + +export function Body({ body }: BodyProps) { + return ; +} diff --git a/packages/twenty-website-new/src/sections/EngagementBand/components/Copy/Copy.tsx b/packages/twenty-website-new/src/sections/EngagementBand/components/Copy/Copy.tsx new file mode 100644 index 0000000000..ecbf9ea38c --- /dev/null +++ b/packages/twenty-website-new/src/sections/EngagementBand/components/Copy/Copy.tsx @@ -0,0 +1,21 @@ +import { theme } from '@/theme'; +import { styled } from '@linaria/react'; +import type { ReactNode } from 'react'; + +const StyledCopy = styled.div` + display: grid; + grid-template-columns: 1fr; + max-width: 100%; + min-width: 0; + position: relative; + row-gap: ${theme.spacing(2)}; + z-index: 1; +`; + +type CopyProps = { + children: ReactNode; +}; + +export function Copy({ children }: CopyProps) { + return {children}; +} diff --git a/packages/twenty-website-new/src/sections/EngagementBand/components/Heading/Heading.tsx b/packages/twenty-website-new/src/sections/EngagementBand/components/Heading/Heading.tsx new file mode 100644 index 0000000000..79f5d07f93 --- /dev/null +++ b/packages/twenty-website-new/src/sections/EngagementBand/components/Heading/Heading.tsx @@ -0,0 +1,20 @@ +import { Heading as BaseHeading } from '@/design-system/components'; +import type { HeadingType } from '@/design-system/components/Heading/types/Heading'; +import { theme } from '@/theme'; +import { styled } from '@linaria/react'; + +const StyledHeading = styled(BaseHeading)` + white-space: pre-line; + + @media (min-width: ${theme.breakpoints.md}px) { + max-width: 668px; + } +`; + +type HeadingProps = { + segments: HeadingType; +}; + +export function Heading({ segments }: HeadingProps) { + return ; +} diff --git a/packages/twenty-website-new/src/sections/EngagementBand/components/Root/Root.tsx b/packages/twenty-website-new/src/sections/EngagementBand/components/Root/Root.tsx new file mode 100644 index 0000000000..89fab7ed1f --- /dev/null +++ b/packages/twenty-website-new/src/sections/EngagementBand/components/Root/Root.tsx @@ -0,0 +1,35 @@ +import { Container } from '@/design-system/components'; +import { theme } from '@/theme'; +import { styled } from '@linaria/react'; +import type { ReactNode } from 'react'; + +const StyledSection = styled.section` + width: 100%; +`; + +const StyledContainer = styled(Container)` + min-width: 0; + padding-bottom: ${theme.spacing(20)}; + padding-left: ${theme.spacing(4)}; + padding-right: ${theme.spacing(4)}; + padding-top: ${theme.spacing(6)}; + width: 100%; + + @media (min-width: ${theme.breakpoints.md}px) { + padding-left: ${theme.spacing(10)}; + padding-right: ${theme.spacing(10)}; + } +`; + +type RootProps = { + backgroundColor: string; + children: ReactNode; +}; + +export function Root({ backgroundColor, children }: RootProps) { + return ( + + {children} + + ); +} diff --git a/packages/twenty-website-new/src/sections/EngagementBand/components/Strip/Strip.tsx b/packages/twenty-website-new/src/sections/EngagementBand/components/Strip/Strip.tsx new file mode 100644 index 0000000000..002678345a --- /dev/null +++ b/packages/twenty-website-new/src/sections/EngagementBand/components/Strip/Strip.tsx @@ -0,0 +1,80 @@ +import { EngagementBandShape } from '@/sections/EngagementBand/EngagementBandShape'; +import { theme } from '@/theme'; +import { css } from '@linaria/core'; +import { styled } from '@linaria/react'; +import NextImage from 'next/image'; +import type { ReactNode } from 'react'; + +const ENGAGEMENT_BAND_OVERLAY_SRC = + '/images/pricing/engagement-band/overlay.png'; + +const OverlayLayer = styled.div` + bottom: 0; + left: 60%; + pointer-events: none; + position: absolute; + right: 0; + top: 0; + z-index: 0; +`; + +const overlayImageClassName = css` + object-fit: cover; + object-position: right center; +`; + +const StyledStrip = styled.div` + border-radius: ${theme.radius(1)}; + display: grid; + grid-template-columns: 1fr; + max-width: 100%; + min-width: 0; + overflow: hidden; + padding-top: ${theme.spacing(6)}; + padding-right: ${theme.spacing(4)}; + padding-bottom: ${theme.spacing(6)}; + padding-left: ${theme.spacing(6)}; + position: relative; + row-gap: ${theme.spacing(6)}; + z-index: 0; + + @media (min-width: ${theme.breakpoints.md}px) { + align-items: center; + column-gap: ${theme.spacing(2)}; + grid-template-columns: minmax(0, 668px) minmax(0, 1fr); + padding-right: ${theme.spacing(16)}; + row-gap: 0; + } + + &[data-variant='primary'] { + color: ${theme.colors.primary.text[100]}; + } + + &[data-variant='secondary'] { + color: ${theme.colors.secondary.text[100]}; + } +`; + +type StripProps = { + children: ReactNode; + fillColor: string; + variant: 'primary' | 'secondary'; +}; + +export function Strip({ children, fillColor, variant }: StripProps) { + return ( + + + + + + {children} + + ); +} diff --git a/packages/twenty-website-new/src/sections/EngagementBand/components/index.ts b/packages/twenty-website-new/src/sections/EngagementBand/components/index.ts new file mode 100644 index 0000000000..7e57749e96 --- /dev/null +++ b/packages/twenty-website-new/src/sections/EngagementBand/components/index.ts @@ -0,0 +1,15 @@ +import { Actions } from './Actions/Actions'; +import { Body } from './Body/Body'; +import { Copy } from './Copy/Copy'; +import { Heading } from './Heading/Heading'; +import { Root } from './Root/Root'; +import { Strip } from './Strip/Strip'; + +export const EngagementBand = { + Actions, + Body, + Copy, + Heading, + Root, + Strip, +}; diff --git a/packages/twenty-website-new/src/sections/EngagementBand/types/EngagementBandData.ts b/packages/twenty-website-new/src/sections/EngagementBand/types/EngagementBandData.ts new file mode 100644 index 0000000000..42285fa99a --- /dev/null +++ b/packages/twenty-website-new/src/sections/EngagementBand/types/EngagementBandData.ts @@ -0,0 +1,7 @@ +import type { BodyType } from '@/design-system/components/Body/types/Body'; +import type { HeadingType } from '@/design-system/components/Heading/types/Heading'; + +export type EngagementBandDataType = { + body: BodyType; + heading: HeadingType; +}; diff --git a/packages/twenty-website-new/src/sections/EngagementBand/types/index.ts b/packages/twenty-website-new/src/sections/EngagementBand/types/index.ts new file mode 100644 index 0000000000..1c6d688860 --- /dev/null +++ b/packages/twenty-website-new/src/sections/EngagementBand/types/index.ts @@ -0,0 +1 @@ +export type { EngagementBandDataType } from './EngagementBandData'; diff --git a/packages/twenty-website-new/src/sections/Faq/components/Cta/Cta.tsx b/packages/twenty-website-new/src/sections/Faq/components/Cta/Cta.tsx new file mode 100644 index 0000000000..3a65dd915b --- /dev/null +++ b/packages/twenty-website-new/src/sections/Faq/components/Cta/Cta.tsx @@ -0,0 +1,18 @@ +import { theme } from '@/theme'; +import { styled } from '@linaria/react'; +import type { ReactNode } from 'react'; + +const StyledCta = styled.div` + column-gap: ${theme.spacing(2)}; + display: grid; + grid-template-columns: auto auto; + justify-content: start; +`; + +type CtaProps = { + children: ReactNode; +}; + +export function Cta({ children }: CtaProps) { + return {children}; +} diff --git a/packages/twenty-website-new/src/sections/Faq/components/Heading/Heading.tsx b/packages/twenty-website-new/src/sections/Faq/components/Heading/Heading.tsx new file mode 100644 index 0000000000..79f86ca19e --- /dev/null +++ b/packages/twenty-website-new/src/sections/Faq/components/Heading/Heading.tsx @@ -0,0 +1,28 @@ +import { Heading as BaseHeading } from '@/design-system/components'; +import type { HeadingType } from '@/design-system/components/Heading/types/Heading'; +import { theme } from '@/theme'; +import { css } from '@linaria/core'; + +const faqHeadingClassName = css` + white-space: pre-line; + + @media (min-width: ${theme.breakpoints.md}px) { + max-width: 700px; + } +`; + +type HeadingProps = { + segments: HeadingType[]; +}; + +export function Heading({ segments }: HeadingProps) { + return ( + + ); +} diff --git a/packages/twenty-website-new/src/sections/Faq/components/Intro/Intro.tsx b/packages/twenty-website-new/src/sections/Faq/components/Intro/Intro.tsx new file mode 100644 index 0000000000..b73d532ca7 --- /dev/null +++ b/packages/twenty-website-new/src/sections/Faq/components/Intro/Intro.tsx @@ -0,0 +1,17 @@ +import { theme } from '@/theme'; +import { styled } from '@linaria/react'; +import type { ReactNode } from 'react'; + +const StyledIntro = styled.div` + display: grid; + grid-template-columns: 1fr; + row-gap: ${theme.spacing(6)}; +`; + +type IntroProps = { + children: ReactNode; +}; + +export function Intro({ children }: IntroProps) { + return {children}; +} diff --git a/packages/twenty-website-new/src/sections/Faq/components/Item/Item.tsx b/packages/twenty-website-new/src/sections/Faq/components/Item/Item.tsx new file mode 100644 index 0000000000..80b8f73cbb --- /dev/null +++ b/packages/twenty-website-new/src/sections/Faq/components/Item/Item.tsx @@ -0,0 +1,206 @@ +'use client'; + +import { + Accordion as BaseAccordion, + type AccordionTriggerState, +} from '@base-ui/react/accordion'; +import { + MinusIcon, + PlusIcon, + RectangleFillIcon, + RectangleOutlineIcon, +} from '@/icons'; +import { theme } from '@/theme'; +import { styled } from '@linaria/react'; +import { IconButton } from '@/design-system/components'; +import type { FaqQuestionType } from '@/sections/Faq/types/FaqQuestion'; + +const QuestionText = styled.span` + color: ${theme.colors.secondary.text[40]}; + font-size: 2rem; + font-weight: ${theme.font.weight.regular}; + grid-column: 3; + line-height: 1.25; + min-width: 0; + overflow-wrap: break-word; + transition: color 0.3s cubic-bezier(0.4, 0, 0.2, 1); +`; + +const QuestionIconLayer = styled.span` + bottom: 0; + display: block; + left: 0; + position: absolute; + right: 0; + top: 7px; + transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1); + + &[data-layer='outline'] { + opacity: 1; + } + + &[data-layer='fill'] { + opacity: 0; + } +`; + +const ToggleContainer = styled.div` + grid-column: 5; + margin-top: ${theme.spacing(0.5)}; + + button::after { + bottom: 0; + content: ''; + left: 0; + position: absolute; + right: 0; + top: 0; + } +`; + +export const ItemRow = styled.div` + border-top: 1px solid ${theme.colors.secondary.text[40]}; + display: grid; + grid-template-columns: 14px 12px 1fr 32px 36px; + padding-bottom: ${theme.spacing(6)}; + padding-top: ${theme.spacing(6)}; + row-gap: ${theme.spacing(2)}; + + &[data-open] ${QuestionText} { + color: ${theme.colors.secondary.text[100]}; + } + + &[data-open] ${QuestionIconLayer}[data-layer='outline'] { + opacity: 0; + } + + &[data-open] ${QuestionIconLayer}[data-layer='fill'] { + opacity: 1; + } + + @media (min-width: ${theme.breakpoints.md}px) { + grid-template-columns: 14px 60px 1fr 80px 36px; + row-gap: ${theme.spacing(4)}; + } +`; + +const Header = styled.h3` + display: grid; + grid-column: 1 / -1; + grid-template-columns: subgrid; + margin-bottom: 0; + margin-left: 0; + margin-right: 0; + margin-top: 0; + position: relative; + + &:hover ${QuestionText} { + color: #ffffff; + } + + &:hover ${QuestionIconLayer}[data-layer='outline'] { + opacity: 0; + } + + &:hover ${QuestionIconLayer}[data-layer='fill'] { + opacity: 1; + } + + &:hover ${ToggleContainer} button { + border-color: ${theme.colors.secondary.text[100]}; + } +`; + +const QuestionIconContainer = styled.span` + grid-column: 1; + height: 12px; + position: relative; + width: 12px; +`; + +const AnswerWrapper = styled.div` + display: grid; + grid-column: 3; + grid-template-rows: 0fr; + opacity: 0; + transition: + grid-template-rows 0.4s cubic-bezier(0.4, 0, 0.2, 1), + opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1), + visibility 0.4s cubic-bezier(0.4, 0, 0.2, 1); + visibility: hidden; + + &[data-open] { + grid-template-rows: 1fr; + opacity: 1; + visibility: visible; + } +`; + +const AnswerInner = styled.div` + overflow: hidden; +`; + +const AnswerText = styled.div` + color: ${theme.colors.secondary.text[100]}; + font-family: ${theme.font.family.sans}; + font-size: ${theme.font.size(4)}; + line-height: 1.5; + margin: 0; +`; + +type ItemProps = { + question: FaqQuestionType; + value: string; +}; + +export function Item({ question, value }: ItemProps) { + return ( + }> + }> + + + + + + + + + + {question.question.text} + + + { + const isOpen = state.open; + return ( + + ); + }} + /> + + + + } keepMounted> + + {question.answer.text} + + + + ); +} diff --git a/packages/twenty-website-new/src/sections/Faq/components/Items/Items.tsx b/packages/twenty-website-new/src/sections/Faq/components/Items/Items.tsx new file mode 100644 index 0000000000..9407d2b48b --- /dev/null +++ b/packages/twenty-website-new/src/sections/Faq/components/Items/Items.tsx @@ -0,0 +1,36 @@ +'use client'; + +import { Accordion as BaseAccordion } from '@base-ui/react/accordion'; +import { theme } from '@/theme'; +import { styled } from '@linaria/react'; +import type { FaqQuestionType } from '@/sections/Faq/types/FaqQuestion'; +import { Item } from '../Item/Item'; + +type ItemsProps = { + questions: FaqQuestionType[]; +}; + +const AccordionList = styled.div` + margin-bottom: 0; + margin-left: auto; + margin-right: auto; + margin-top: 0; + + @media (min-width: ${theme.breakpoints.md}px) { + width: 66%; + } +`; + +export function Items({ questions }: ItemsProps) { + return ( + }> + {questions.map((faqQuestion, index) => ( + + ))} + + ); +} diff --git a/packages/twenty-website-new/src/sections/Faq/components/Root/Root.tsx b/packages/twenty-website-new/src/sections/Faq/components/Root/Root.tsx new file mode 100644 index 0000000000..202a264864 --- /dev/null +++ b/packages/twenty-website-new/src/sections/Faq/components/Root/Root.tsx @@ -0,0 +1,43 @@ +import { Container } from '@/design-system/components'; +import type { IllustrationType } from '@/design-system/components/Illustration/types/Illustration'; +import { theme } from '@/theme'; +import { styled } from '@linaria/react'; +import type { ReactNode } from 'react'; + +const StyledSection = styled.section` + background-color: ${theme.colors.secondary.background[100]}; + color: ${theme.colors.secondary.text[100]}; + overflow: hidden; + position: relative; + width: 100%; +`; + +const StyledContainer = styled(Container)` + display: grid; + grid-template-columns: 1fr; + padding-bottom: ${theme.spacing(30)}; + padding-left: ${theme.spacing(6)}; + padding-right: ${theme.spacing(6)}; + padding-top: ${theme.spacing(30)}; + position: relative; + row-gap: ${theme.spacing(20)}; + z-index: 1; + + @media (min-width: ${theme.breakpoints.md}px) { + padding-left: ${theme.spacing(10)}; + padding-right: ${theme.spacing(10)}; + } +`; + +type RootProps = { + children: ReactNode; + illustration: IllustrationType; +}; + +export function Root({ children, illustration }: RootProps) { + return ( + + {children} + + ); +} diff --git a/packages/twenty-website-new/src/sections/Faq/components/index.ts b/packages/twenty-website-new/src/sections/Faq/components/index.ts new file mode 100644 index 0000000000..2357213052 --- /dev/null +++ b/packages/twenty-website-new/src/sections/Faq/components/index.ts @@ -0,0 +1,13 @@ +import { Cta } from './Cta/Cta'; +import { Heading } from './Heading/Heading'; +import { Intro } from './Intro/Intro'; +import { Items } from './Items/Items'; +import { Root } from './Root/Root'; + +export const Faq = { + Cta, + Heading, + Intro, + Items, + Root, +}; diff --git a/packages/twenty-website-new/src/sections/Faq/types/FaqData.ts b/packages/twenty-website-new/src/sections/Faq/types/FaqData.ts new file mode 100644 index 0000000000..d908145b9d --- /dev/null +++ b/packages/twenty-website-new/src/sections/Faq/types/FaqData.ts @@ -0,0 +1,11 @@ +import { EyebrowType } from '@/design-system/components/Eyebrow/types/Eyebrow'; +import { HeadingType } from '@/design-system/components/Heading/types/Heading'; +import { IllustrationType } from '@/design-system/components/Illustration/types/Illustration'; +import { FaqQuestionType } from '@/sections/Faq/types/FaqQuestion'; + +export type FaqDataType = { + illustration: IllustrationType; + eyebrow: EyebrowType; + heading: HeadingType[]; + questions: FaqQuestionType[]; +}; diff --git a/packages/twenty-website-new/src/sections/Faq/types/FaqQuestion.ts b/packages/twenty-website-new/src/sections/Faq/types/FaqQuestion.ts new file mode 100644 index 0000000000..187c1e357a --- /dev/null +++ b/packages/twenty-website-new/src/sections/Faq/types/FaqQuestion.ts @@ -0,0 +1,7 @@ +import { BodyType } from '@/design-system/components/Body/types/Body'; +import { HeadingType } from '@/design-system/components/Heading/types/Heading'; + +export type FaqQuestionType = { + question: HeadingType; + answer: BodyType; +}; diff --git a/packages/twenty-website-new/src/sections/Faq/types/index.ts b/packages/twenty-website-new/src/sections/Faq/types/index.ts new file mode 100644 index 0000000000..08f9220111 --- /dev/null +++ b/packages/twenty-website-new/src/sections/Faq/types/index.ts @@ -0,0 +1,2 @@ +export type { FaqDataType } from './FaqData'; +export type { FaqQuestionType } from './FaqQuestion'; diff --git a/packages/twenty-website-new/src/sections/Footer/components/Bottom/Bottom.tsx b/packages/twenty-website-new/src/sections/Footer/components/Bottom/Bottom.tsx index 8f9a4ca65e..c66f74234e 100644 --- a/packages/twenty-website-new/src/sections/Footer/components/Bottom/Bottom.tsx +++ b/packages/twenty-website-new/src/sections/Footer/components/Bottom/Bottom.tsx @@ -6,8 +6,10 @@ const BottomGrid = styled.div` display: grid; font-size: ${theme.font.size(3)}; gap: ${theme.spacing(6)}; - grid-template-columns: 1fr 1fr; + grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-rows: auto auto; + min-width: 0; + width: 100%; `; const Copyright = styled.div` diff --git a/packages/twenty-website-new/src/sections/Footer/components/Social/Social.tsx b/packages/twenty-website-new/src/sections/Footer/components/Social/Social.tsx index 558620aff7..f9b96fd002 100644 --- a/packages/twenty-website-new/src/sections/Footer/components/Social/Social.tsx +++ b/packages/twenty-website-new/src/sections/Footer/components/Social/Social.tsx @@ -8,12 +8,18 @@ import React from 'react'; const SocialContainer = styled.nav` align-items: center; display: flex; + flex-wrap: wrap; gap: ${theme.spacing(6)}; grid-column: 1 / -1; grid-row: 1; + justify-content: center; + max-width: 100%; + min-width: 0; @media (min-width: ${theme.breakpoints.md}px) { + flex-wrap: nowrap; grid-column: 2; + justify-content: flex-end; justify-self: end; } `; @@ -29,11 +35,13 @@ const SocialItem = styled.a` align-items: center; color: ${theme.colors.primary.text[100]}; display: flex; + flex-shrink: 0; font-size: ${theme.font.size(3)}; font-weight: ${theme.font.weight.medium}; gap: ${theme.spacing(3)}; line-height: 14px; text-decoration: none; + white-space: nowrap; &:focus-visible { outline: 1px solid ${theme.colors.highlight[100]}; diff --git a/packages/twenty-website-new/src/sections/Hero/components/Body/Body.tsx b/packages/twenty-website-new/src/sections/Hero/components/Body/Body.tsx index df7e8cc92b..b50bd50654 100644 --- a/packages/twenty-website-new/src/sections/Hero/components/Body/Body.tsx +++ b/packages/twenty-website-new/src/sections/Hero/components/Body/Body.tsx @@ -9,28 +9,32 @@ import { styled } from '@linaria/react'; const BodyContainer = styled.div` color: ${theme.colors.primary.text[60]}; margin-top: calc(${theme.spacing(2)} - ${theme.spacing(6)}); - width: 360px; + max-width: 360px; + width: 100%; + + &[data-page=${Pages.WhyTwenty}] { + color: ${theme.colors.secondary.text[100]}; + } @media (min-width: ${theme.breakpoints.md}px) { &[data-page=${Pages.Home}] { - width: 591px; + max-width: 591px; } &[data-page=${Pages.Partner}] { - width: 500px; + max-width: 500px; } &[data-page=${Pages.Pricing}] { - width: 500px; + max-width: 500px; } &[data-page=${Pages.Product}] { - width: 591px; + max-width: 591px; } &[data-page=${Pages.WhyTwenty}] { - width: 443px; - color: ${theme.colors.secondary.text[100]}; + max-width: 443px; } } `; diff --git a/packages/twenty-website-new/src/sections/Hero/components/Heading/Heading.tsx b/packages/twenty-website-new/src/sections/Hero/components/Heading/Heading.tsx index 0f3d230580..beaa696183 100644 --- a/packages/twenty-website-new/src/sections/Hero/components/Heading/Heading.tsx +++ b/packages/twenty-website-new/src/sections/Hero/components/Heading/Heading.tsx @@ -7,15 +7,16 @@ import { theme } from '@/theme'; import { styled } from '@linaria/react'; const HeadingContainer = styled.div` - width: 360px; + max-width: 360px; + width: 100%; word-wrap: break-word; - @media (min-width: ${theme.breakpoints.md}px) { - width: 672px; + &[data-page=${Pages.WhyTwenty}] { + color: ${theme.colors.secondary.text[100]}; + } - &[data-page=${Pages.WhyTwenty}] { - color: ${theme.colors.secondary.text[100]}; - } + @media (min-width: ${theme.breakpoints.md}px) { + max-width: 672px; } `; diff --git a/packages/twenty-website-new/src/sections/Hero/components/HomeVisual/HomeVisual.tsx b/packages/twenty-website-new/src/sections/Hero/components/HomeVisual/HomeVisual.tsx index 68c41fedcf..c8eb569ad4 100644 --- a/packages/twenty-website-new/src/sections/Hero/components/HomeVisual/HomeVisual.tsx +++ b/packages/twenty-website-new/src/sections/Hero/components/HomeVisual/HomeVisual.tsx @@ -1,4 +1,5 @@ import { Image } from '@/design-system/components'; +import type { ImageType } from '@/design-system/components/Image/types/Image'; import { theme } from '@/theme'; import { styled } from '@linaria/react'; @@ -25,7 +26,8 @@ const StyledBackgroundImage = styled(Image)` width: 98%; @media (min-width: ${theme.breakpoints.md}px) { - width: 850px; + max-width: 850px; + width: 100%; } `; @@ -41,15 +43,21 @@ const StyledForegroundImage = styled(Image)` justify-self: center; margin-right: ${theme.spacing(40)}; margin-top: ${theme.spacing(17.5)}; - width: 800px; + max-width: 800px; + width: 100%; } `; -export function HomeVisual() { +type HomeVisualProps = { + background: ImageType; + foreground: ImageType; +}; + +export function HomeVisual({ background, foreground }: HomeVisualProps) { return ( - - + + ); } diff --git a/packages/twenty-website-new/src/sections/Hero/components/Illustration/Illustration.tsx b/packages/twenty-website-new/src/sections/Hero/components/Illustration/Illustration.tsx index 11eb01c4ea..b221cc1866 100644 --- a/packages/twenty-website-new/src/sections/Hero/components/Illustration/Illustration.tsx +++ b/packages/twenty-website-new/src/sections/Hero/components/Illustration/Illustration.tsx @@ -1,31 +1,36 @@ -import { IllustrationType } from '@/design-system/components/Illustration/types/Illustration'; +import type { IllustrationType } from '@/design-system/components/Illustration/types/Illustration'; import { theme } from '@/theme'; import { styled } from '@linaria/react'; const StyledIllustrationContainer = styled.div` + justify-self: stretch; margin-top: ${theme.spacing(6)}; + max-width: 100%; + min-width: 0; width: 100%; `; -type IllustrationProps = IllustrationType & { +type IllustrationProps = { + illustration: IllustrationType; backgroundColor: string; }; export function Illustration({ - src, - title, + illustration, backgroundColor, }: IllustrationProps) { return (