feat(primitivas): capa gráfica y de movimiento reutilizable
Diez primitivas que dan a la landing el "gráfico y movimiento" que pidió la dueña, todas con guarda de prefers-reduced-motion: - FondoPuntos / PatronPuntos — el patrón de puntos del manual - TarjetaSpotlight, TextoDesenfoque, ContadorNumero — realce y reveal - Carrusel — deslizable, con contador, autoplay pausable - Icono, SimboloTresLineas, IlustracionInflexion — línea, sin relleno - FondoFoto — duotono azul/dorado sobre foto useAutoStep en lib/motion.ts comparte la forma del autoplay del carrusel para indicadores de paso que no son carrusel. IlustracionInflexion documenta un detalle que muerde: motion.path aplica su propio andamiaje de dasharray aunque no reciba initial/animate, así que la rama de reduced motion renderiza <path> planos en vez de intentar neutralizar los animados. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a9758a92f9
commit
5b400cb161
19 files changed
+881
No files matched your search
@@ -0,0 +1,46 @@
|
||||
// "Patrón de puntos" from the Manual de Identidad Visual (recursos visuales).
|
||||
// Geometry measured off the manual: the dots shrink and tighten from left to
|
||||
// right, resolving complexity into focus — the same idea as the ≡ symbol.
|
||||
// Colour comes from `currentColor`, so callers set it with a text-* class.
|
||||
|
||||
const R0 = 5.5; // radius of the leftmost dot
|
||||
const R_DECAY = 0.847; // per column
|
||||
const S0 = 29; // gap between the first two columns
|
||||
const S_DECAY = 0.97; // per column
|
||||
const ROW_GAP = 24.5;
|
||||
|
||||
export function PatronPuntos({
|
||||
rows = 3,
|
||||
cols = 8,
|
||||
className = '',
|
||||
}: {
|
||||
rows?: number;
|
||||
cols?: number;
|
||||
className?: string;
|
||||
}) {
|
||||
const columns: { cx: number; r: number }[] = [];
|
||||
let cx = R0;
|
||||
for (let i = 0; i < cols; i++) {
|
||||
const r = R0 * R_DECAY ** i;
|
||||
columns.push({ cx, r });
|
||||
cx += S0 * S_DECAY ** i;
|
||||
}
|
||||
const last = columns[columns.length - 1];
|
||||
const width = last.cx + last.r;
|
||||
const height = (rows - 1) * ROW_GAP + 2 * R0;
|
||||
|
||||
return (
|
||||
<svg
|
||||
viewBox={`0 0 ${width.toFixed(1)} ${height.toFixed(1)}`}
|
||||
className={className}
|
||||
aria-hidden="true"
|
||||
focusable="false"
|
||||
>
|
||||
{Array.from({ length: rows }, (_, row) =>
|
||||
columns.map(({ cx: x, r }, col) => (
|
||||
<circle key={`${row}-${col}`} cx={x.toFixed(2)} cy={(R0 + row * ROW_GAP).toFixed(2)} r={r.toFixed(2)} fill="currentColor" />
|
||||
)),
|
||||
)}
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user