Files
twenty/packages/twenty-website/src/partner-application/PartnerApplicationModal.tsx
T
Abdullah. 569d887d1e [Website] Cut over to the rebuilt site (#21825)
Renaming the package so any further PRs directed to the website are
targeted to the reworked code instead of diverging. Once merged, I will
start preparing this for deployment to dev to test before releasing to
prod. Any improvements will also be applied to this package.

I avoided making significant changes to API routes so nothing breaks,
but will test it thoroughly today to confirm. That said, everything is
ported - double checked.

Big diff PR, impossible to review, but last one! No more rebuilds.
2026-06-19 10:22:46 +02:00

100 lines
2.7 KiB
TypeScript

'use client';
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react';
import { css } from '@linaria/core';
import { styled } from '@linaria/react';
import dynamic from 'next/dynamic';
import { useEffect, useState } from 'react';
import {
buildSchemeContext,
DURATION,
EASING,
fontSize,
mediaUp,
semanticColor,
spacing,
} from '@/tokens';
import { Modal } from '@/ui';
const WizardFallback = styled.p`
color: ${semanticColor.inkMuted};
font-size: ${fontSize(4)};
padding-block: ${spacing(8)};
text-align: center;
`;
function WizardLoadingFallback() {
const { i18n } = useLingui();
return <WizardFallback>{i18n._(msg`Loading…`)}</WizardFallback>;
}
// The wizard — its fields, schemas, and country list — ships only when the
// modal first opens, never on a page load where the visitor does not apply.
const PartnerApplicationWizard = dynamic(
() =>
import('./wizard/PartnerApplicationWizard').then((mod) => ({
default: mod.PartnerApplicationWizard,
})),
{ loading: () => <WizardLoadingFallback />, ssr: false },
);
// The form sits in a narrow panel; the booking screen eases wider for the
// calendar. The Modal reads --modal-panel-width, so the change is a smooth
// transition rather than the old site's instant jump.
const formPanelClass = css`
transition: width ${DURATION.md} ${EASING.standard};
--modal-panel-width: min(360px, 100%);
${mediaUp('md')} {
--modal-panel-width: min(720px, 100%);
}
`;
const bookingPanelClass = css`
transition: width ${DURATION.md} ${EASING.standard};
--modal-panel-width: min(960px, 100%);
`;
// The near-black Modal panel is scheme-agnostic; the wizard reads semantic
// colours and the Button keys on [data-scheme], so it runs on a dark scope —
// the same context the full-page mount establishes.
const WizardScope = styled.div`
${buildSchemeContext('dark')}
`;
export function PartnerApplicationModal({
onClose,
open,
}: {
onClose: () => void;
open: boolean;
}) {
const { i18n } = useLingui();
const [hasReachedBooking, setHasReachedBooking] = useState(false);
// Reset the widened panel after the modal closes, while nothing is on screen,
// so a prior session's booking width can't flash on the next open.
useEffect(() => {
if (!open) setHasReachedBooking(false);
}, [open]);
return (
<Modal
ariaLabel={i18n._(msg`Partner application`)}
className={hasReachedBooking ? bookingPanelClass : formPanelClass}
onClose={onClose}
open={open}
>
<WizardScope data-scheme="dark">
<PartnerApplicationWizard
onSubmitted={() => setHasReachedBooking(true)}
onSuccess={onClose}
resetSignal={0}
/>
</WizardScope>
</Modal>
);
}