d58ec64e10
## Summary
Reworks the product page's closing section, and in doing so makes every
signoff closer width-driven.
### 1. Replace the Demo section with a register Signoff (`6a5f0c34bf`)
The product page ended on a static `AppPreview` mockup ("Try it live").
Swap it for the shared `Signoff` closer — a focused register CTA, the
same component the customers / why-twenty / partners pages use — so the
page ends by driving sign-ups instead of re-showing the product.
- New `ProductSignoff`: heading "Start moving faster today.", a
supporting line, and the **Get started + Talk to us** pair (matching
`CustomersCatalogSignoff`). Uses `SITE_URLS.appWelcome` per the
site-urls rule rather than inlining the URL.
- Removes the now-unused `product-demo` section and its 192KB background
asset.
### 2. Make Signoff headings width-driven (`0365c0d2ea`)
The signoff headings forced their two-line break with a literal `\n` in
the translated string — against the site's typography principle (fluid
type + `text-wrap: balance`, no `<br>`).
- `Signoff` now carries one default **`615px`** heading measure; all
five closers drop `\n`.
- The width was **measured, not guessed**: each heading was rendered
headlessly in the real production fonts (Aleo 300 body, Host Grotesk 300
accent — each heading mixes both) at the desktop size with `text-wrap:
balance`, then I found the common window where every heading breaks
identically: whyTwenty `[565–820]`, customers `[425–800]`, partner
`[380–730]`, product `[380–660]` — `615` sits in all of them. Each was
then verified to reproduce its exact current break at 615px.
- **Affects 4 other pages** (why-twenty, customers, customers/[slug],
partners) — all verified to render identically, and headings now reflow
on narrow viewports instead of being pinned by `\n`.
- Drops the one-off `headingMaxWidth` prop (now unused).
## Test plan
- oxfmt, oxlint, check-conventions, typecheck — all green.
- Headless measurement confirms all five signoff headings reproduce
their current desktop break at 615px (no visual regression).
- Visually confirmed the product closer and the four sibling signoffs.
95 lines
2.0 KiB
TypeScript
95 lines
2.0 KiB
TypeScript
import { styled } from '@linaria/react';
|
|
import { type ReactNode } from 'react';
|
|
|
|
import { mediaUp, type Scheme, spacing } from '@/tokens';
|
|
|
|
import { Body } from './Body';
|
|
import { GuideCrosshair } from './GuideCrosshair';
|
|
import { Heading } from './Heading';
|
|
import { SectionShell } from './SectionShell';
|
|
|
|
type SignoffCrosshairSide = 'left' | 'right';
|
|
|
|
const SIGNOFF_CROSSHAIR_Y = '198px';
|
|
const SIGNOFF_CROSSHAIR_X: Record<SignoffCrosshairSide, string> = {
|
|
left: 'calc(50% - 334px)',
|
|
right: 'calc(50% + 334px)',
|
|
};
|
|
|
|
const SignoffStack = styled.div`
|
|
align-items: center;
|
|
display: flex;
|
|
flex-direction: column;
|
|
padding-block: ${spacing(20)};
|
|
text-align: center;
|
|
|
|
${mediaUp('md')} {
|
|
justify-content: center;
|
|
min-height: 759px;
|
|
padding-block: 0;
|
|
}
|
|
`;
|
|
|
|
const HeadingMeasure = styled.div`
|
|
max-width: 615px;
|
|
width: 100%;
|
|
`;
|
|
|
|
// Measure tuned to a clean break without coupling a <br> into the translation.
|
|
const Subline = styled.div`
|
|
margin-top: ${spacing(2)};
|
|
max-width: 400px;
|
|
width: 100%;
|
|
`;
|
|
|
|
const Actions = styled.div`
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: ${spacing(3)};
|
|
justify-content: center;
|
|
margin-top: ${spacing(6)};
|
|
`;
|
|
|
|
export type SignoffProps = {
|
|
body: string;
|
|
children: ReactNode;
|
|
crosshairSide?: SignoffCrosshairSide;
|
|
heading: string;
|
|
scheme?: Scheme;
|
|
};
|
|
|
|
export function Signoff({
|
|
body,
|
|
children,
|
|
crosshairSide = 'right',
|
|
heading,
|
|
scheme = 'light',
|
|
}: SignoffProps) {
|
|
return (
|
|
<SectionShell
|
|
background={
|
|
<GuideCrosshair
|
|
crossX={SIGNOFF_CROSSHAIR_X[crosshairSide]}
|
|
crossY={SIGNOFF_CROSSHAIR_Y}
|
|
/>
|
|
}
|
|
rhythm="flush"
|
|
scheme={scheme}
|
|
>
|
|
<SignoffStack>
|
|
<HeadingMeasure>
|
|
<Heading as="h2" size="lg" weight="light">
|
|
{heading}
|
|
</Heading>
|
|
</HeadingMeasure>
|
|
<Subline>
|
|
<Body muted size="sm">
|
|
{body}
|
|
</Body>
|
|
</Subline>
|
|
<Actions>{children}</Actions>
|
|
</SignoffStack>
|
|
</SectionShell>
|
|
);
|
|
}
|