/** * DesignCanvas — 变体并排网格布局 * * 用于展示2+个静态设计variations让用户对比选择。 * 每个variation有label,可hover放大。 * * 用法: * * *
...你的设计1...
*
* *
...你的设计2...
*
* *
...你的设计3...
*
*
* * 配合React+Babel使用。放在合适的script里,然后window.DesignCanvas/window.Variation可用。 */ const canvasStyles = { container: { minHeight: '100vh', background: '#F5F5F0', padding: '40px 60px', fontFamily: '-apple-system, "SF Pro Text", "PingFang SC", sans-serif', }, header: { marginBottom: 48, maxWidth: 900, }, title: { fontSize: 36, fontWeight: 600, marginBottom: 12, color: '#1A1A1A', letterSpacing: '-0.02em', }, subtitle: { fontSize: 16, color: '#666', lineHeight: 1.5, }, grid: { display: 'grid', gap: 32, }, cell: { display: 'flex', flexDirection: 'column', gap: 12, }, cellHeader: { display: 'flex', alignItems: 'baseline', gap: 12, paddingBottom: 8, borderBottom: '1px solid #E0E0DA', }, label: { fontSize: 14, fontWeight: 600, color: '#1A1A1A', letterSpacing: '-0.01em', }, description: { fontSize: 13, color: '#888', }, frame: { background: '#fff', borderRadius: 4, border: '1px solid #E0E0DA', overflow: 'hidden', position: 'relative', transition: 'transform 0.2s ease, box-shadow 0.2s ease', cursor: 'pointer', }, frameInner: { position: 'relative', width: '100%', }, badge: { position: 'absolute', top: 12, left: 12, background: 'rgba(0, 0, 0, 0.7)', color: '#fff', padding: '3px 8px', borderRadius: 4, fontSize: 11, fontWeight: 500, letterSpacing: '0.5px', textTransform: 'uppercase', zIndex: 10, pointerEvents: 'none', }, }; function DesignCanvas({ title, subtitle, columns = 3, children }) { const [expanded, setExpanded] = React.useState(null); const gridStyle = { ...canvasStyles.grid, gridTemplateColumns: `repeat(${columns}, 1fr)`, }; return (
{(title || subtitle) && (
{title &&

{title}

} {subtitle &&

{subtitle}

}
)}
{React.Children.map(children, (child, idx) => React.isValidElement(child) ? React.cloneElement(child, { _index: idx, _expanded: expanded === idx, _onToggle: () => setExpanded(expanded === idx ? null : idx), }) : child )}
{expanded !== null && (
setExpanded(null)} style={{ position: 'fixed', inset: 0, background: 'rgba(0, 0, 0, 0.75)', zIndex: 1000, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 40, cursor: 'zoom-out', }} >
e.stopPropagation()} style={{ background: '#fff', borderRadius: 8, overflow: 'hidden', maxWidth: '90vw', maxHeight: '90vh', position: 'relative', }} > {React.Children.toArray(children)[expanded]}
)}
); } function Variation({ label, description, number, children, _index, _expanded, _onToggle, aspectRatio = '4 / 3' }) { const displayNumber = number || String(_index + 1).padStart(2, '0'); return (
{displayNumber} {label} {description && — {description}}
{ e.currentTarget.style.boxShadow = '0 8px 24px rgba(0,0,0,0.08)'; }} onMouseLeave={e => { e.currentTarget.style.boxShadow = 'none'; }} >
{children}
); } if (typeof window !== 'undefined') { Object.assign(window, { DesignCanvas, Variation }); }