import { useDevice } from '../DeviceToggle'; /** * The site's horizontal gutter: how far the content sits from the edge of the window. * * ── One setting, three places ── * * The header row, the content column and the footer's inner block all share the site's measure, and all * three want the same space at the edges. That is what makes this a GUTTER rather than three paddings * that happen to agree — and setting it once is the only arrangement in which they cannot drift. * * A section's own padding still exists and composes on top of this. This is the floor everything starts * from; `PaddingTab` is the per-band control, and it stays for the pages. * * ── All three widths at once, and NOT tied to the device toggle ── * * The per-band control does it the other way: one set of inputs writing to whichever width the preview * is showing. That is right when there are two axes and three bands, where showing everything would be * eighteen inputs. * * Here there is one axis and one value, so all three fit on a row — and seeing them together is the * point. A gutter is a progression, 4 then 8 then 12, and it is judged as one: reading it off three * separate visits to the same control is how a site ends up tighter on a tablet than on a phone. */ export type Gutter = Partial>; /** The device toggle's names, and the breakpoint each one writes. */ const BREAKPOINT = { desktop: 'lg', tablet: 'md', mobile: 'base' } as const; /** What a width falls back to: the nearest smaller one that has a value. */ const inherited = (gutter: Gutter, key: 'base' | 'md' | 'lg'): number | null => { const below = { base: [], md: ['base'], lg: ['md', 'base'] } as const; for (const smaller of below[key]) { const step = gutter[smaller]; if (typeof step === 'number') return step; } return null; }; export const GutterTab = ({ gutter, steps, onChange, }: { gutter: Gutter; /** The scale, sent by the API so this file holds no copy of it. */ steps: number[]; onChange: (gutter: Gutter) => void; }) => { const [device] = useDevice(); const key = BREAKPOINT[device]; const set = (value: string) => { const next = { ...gutter }; // Removed rather than stored as null: an absence is what "inherit" means. if (value === '') delete next[key]; else next[key] = Number(value); onChange(next); }; const own = gutter[key]; const from = inherited(gutter, key); return (
); };