Files
twenty/packages/twenty-website/src/sections/home-stepper/components/HomeStepperVisualFrame.tsx
T
Abdullah. 5a657129f0 Split website stepper into home-stepper and product-stepper sections (#22149)
Reorganizes the flat `sections/stepper/` (30 files — two distinct
steppers plus shared code) into two product-feature-style sections, and
moves the shared code to the shared layers.

- **`sections/home-stepper/`** — the home-page stepper. Renamed
`Stepper` → `HomeStepper` (and the home components → `HomeStepperLottie`
/ `HomeStepperSteps` / `HomeStepperVisualFrame`) for symmetry with
`ProductStepper`. Shell at the root + `components/`/`data/`/`utils/` +
barrel.
- **`sections/product-stepper/`** — the product-page stepper, same
structure.

The 3 files both steppers shared can't live in a shared *section* —
`check-conventions` forbids a section importing another section. So they
moved to the shared layers:
- `StepperProgressRail`, `StepperSwipeDeck` → `ui/`
- `useBreakpointStepSync` → `platform/motion`

Both consumer pages repointed (`@/sections/home-stepper`,
`@/sections/product-stepper`); the row-gap allowlist in
`check-conventions.mjs` updated to the new paths; explanatory comments
stripped across the moved files (CSS-in-template comments and `'use
client'` kept).

Pure reorganization — no behavior change. typecheck + lint + build all
green.
2026-06-25 12:24:22 +02:00

73 lines
2.0 KiB
TypeScript

import { styled } from '@linaria/react';
import { HalftoneImageBackdrop } from '@/platform/visuals/rigs/HalftoneImageBackdrop';
import { STEPPER_BACKDROP } from '../data/stepper-backdrop-config';
import { type ReactNode } from 'react';
import { color } from '@/tokens';
const FRAME_MASK_PATH =
'M4 0H668a4 4 0 0 1 4 4V701a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V499L28 462V215L0 178V4a4 4 0 0 1 4-4Z';
const frameMask = `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 672 705' preserveAspectRatio='none'%3E%3Cpath d='${encodeURIComponent(FRAME_MASK_PATH)}' fill='black'/%3E%3C/svg%3E")`;
const FrameRoot = styled.div`
aspect-ratio: 672 / 705;
contain: layout style paint;
position: relative;
width: 100%;
`;
const MaskedBackdrop = styled.div`
background-color: ${color('graphite')};
inset: 0;
isolation: isolate;
mask-image: ${frameMask};
mask-position: center;
mask-repeat: no-repeat;
mask-size: 100% 100%;
overflow: hidden;
position: absolute;
z-index: 0;
`;
const SlideArea = styled.div`
inset: 0;
position: absolute;
z-index: 1;
`;
const FrameBorder = styled.svg`
inset: 0;
overflow: visible;
pointer-events: none;
position: absolute;
z-index: 2;
`;
export function HomeStepperVisualFrame({ children }: { children: ReactNode }) {
return (
<FrameRoot data-stepper-visual-pointer-root="">
<MaskedBackdrop aria-hidden data-illustration="stepper-backdrop">
<HalftoneImageBackdrop
imageUrl={STEPPER_BACKDROP.imageUrl}
pointerRootSelector="[data-stepper-visual-pointer-root]"
reducedMotionMode="poster"
settings={STEPPER_BACKDROP.settings}
/>
</MaskedBackdrop>
<SlideArea>{children}</SlideArea>
<FrameBorder aria-hidden preserveAspectRatio="none" viewBox="0 0 672 705">
<path
d={FRAME_MASK_PATH}
fill="none"
stroke={color('silver')}
strokeLinejoin="round"
strokeWidth={1}
vectorEffect="non-scaling-stroke"
/>
</FrameBorder>
</FrameRoot>
);
}