You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/web/routes/blocks/feature-split/+page.svelte

184 lines
6.3 KiB

<script lang="ts">
/**
* FeatureSplit demo. Full-bleed on the page; device widths from `./preview`.
*/
import { Stack } from '$uix/eidos/components/stack';
import { Group } from '$uix/eidos/components/group';
import { Wrap } from '$uix/eidos/components/wrap';
import { Text } from '$uix/eidos/components/text';
import { Code } from '$uix/eidos/components/code';
import { ToggleGroup } from '$uix/eidos/components/toggle-group';
import BlockDemo from '../_lib/BlockDemo.svelte';
import FeatureSplitSite from './FeatureSplitSite.svelte';
import DocRow from '../_lib/DocRow.svelte';
let count = $state(3);
let startReversed = $state(false);
let dir = $state<'ltr' | 'rtl'>('ltr');
const previewSrc = $derived(
`/blocks/feature-split/preview?count=${count}&start=${startReversed ? 'media' : 'copy'}&dir=${dir}`
);
</script>
<BlockDemo
name="Feature split"
slug="$blocks/feature-split"
{previewSrc}
previewHeight="820px"
meta={[
{ key: 'compone', value: 'Section · Container · Grid · Mockup · Heading · Text · Icon' },
{ key: 'tipo', value: 'compound (.Row repite)' },
{ key: 'media', value: 'Mockup (browser · phone)' },
{ key: 'strings propias', value: '0' }
]}
>
{#snippet preview()}
<FeatureSplitSite {count} {startReversed} />
{/snippet}
{#snippet lede()}
La <strong>brecha nº1 del dossier</strong>: una afirmación de producto junto a un screenshot,
alternando lados fila a fila. La media se compone con <Code>Mockup</Code> (cromo de navegador o
teléfono), el primitivo de media que cierra ese hueco de raíz.
{/snippet}
{#snippet controls()}
<Wrap gap={5}>
<Group gap={2} align="center" justify="start">
<Text size="sm" color="muted">filas</Text>
<ToggleGroup
selectionMode="single"
size="sm"
attached
value={[String(count)]}
onValueChange={(v) => (count = Number(v[0] ?? count))}
aria-label="número de filas"
>
{#each [1, 2, 3] as value (value)}
<ToggleGroup.Item value={String(value)}>{value}</ToggleGroup.Item>
{/each}
</ToggleGroup>
</Group>
<Group gap={2} align="center" justify="start">
<Text size="sm" color="muted">primera fila</Text>
<ToggleGroup
selectionMode="single"
size="sm"
attached
value={[startReversed ? 'media' : 'copy']}
onValueChange={(v) => (startReversed = (v[0] ?? 'copy') === 'media')}
aria-label="lado de la media en la primera fila"
>
<ToggleGroup.Item value="copy">texto→media</ToggleGroup.Item>
<ToggleGroup.Item value="media">media→texto</ToggleGroup.Item>
</ToggleGroup>
</Group>
<Group gap={2} align="center" justify="start">
<Text size="sm" color="muted">dir</Text>
<ToggleGroup
selectionMode="single"
size="sm"
attached
value={[dir]}
onValueChange={(v) => (dir = (v[0] ?? dir) as typeof dir)}
aria-label="dirección (solo la vista previa)"
>
<ToggleGroup.Item value="ltr">ltr</ToggleGroup.Item>
<ToggleGroup.Item value="rtl">rtl</ToggleGroup.Item>
</ToggleGroup>
</Group>
</Wrap>
{/snippet}
{#snippet composition()}
<Stack gap={4}>
<Text color="muted">
El block coloca las filas; cada fila arma dos columnas y la app pone la copy y la media. Es
compound porque la <Code>.Row</Code> se repite.
</Text>
<Stack gap={3}>
<DocRow term=".Row">
<Code>Grid</Code> de 2 columnas; <Code>reversed</Code> mueve la media al inicio vía
<Code>grid-column</Code>, dejando la copy PRIMERA en el DOM (orden de lectura intacto).
</DocRow>
<DocRow term="media">
Slot de la app: aquí un <Code>Mockup</Code> —<Code>chrome="browser"</Code> o
<Code>"phone"</Code>—, el primitivo de media del canon.
</DocRow>
<DocRow term=".Eyebrow · .Title · .Text">
<Code>Text</Code> primary + <Code>Heading</Code> (h2) + <Code>Text</Code> apagado. La app
pone las palabras.
</DocRow>
<DocRow term=".Features · .Feature">
<Code>Stack</Code> de líneas; cada <Code>.Feature</Code> es un check (decorativo,
aria-hidden) + <Code>Text</Code>.
</DocRow>
<DocRow term=".Actions">
<Code>Group</Code> de <Code>Button</Code>/<Code>Link</Code>.
</DocRow>
</Stack>
</Stack>
{/snippet}
{#snippet api()}
<Stack gap={3}>
<DocRow term="FeatureSplit">
<Code>container</Code> (def. <Code>lg</Code>) · <Code>size</Code> (def. <Code>xl</Code>) ·
<Code>gap</Code> entre filas (def. <Code>12</Code>).
</DocRow>
<DocRow term=".Row">
<Code>reversed</Code> (bool) · <Code>media</Code> (snippet) · <Code>gap</Code> de la copy
(def. <Code>5</Code>).
</DocRow>
<DocRow term="Mockup (canon)">
<Code>chrome</Code>: <Code>'plain' | 'browser' | 'phone'</Code> · <Code>url</Code> para la
barra del navegador. Vive en <Code>$uix/eidos/components/mockup</Code> y lo componen varios
blocks.
</DocRow>
</Stack>
{/snippet}
{#snippet a11y()}
<Stack gap={3}>
<DocRow term="Orden de lectura">
La copy va SIEMPRE primera en el DOM; <Code>reversed</Code> solo cambia la columna (CSS
<Code>grid-column</Code>), así que lectores y teclado ven copy→media en toda fila.
</DocRow>
<DocRow term="Encabezados">
Cada fila un <Code>h2</Code> (ajustable por <Code>level</Code>). El check de cada feature es
decorativo (<Code>aria-hidden</Code>): la palabra lleva el significado.
</DocRow>
<DocRow term="Media">
El <Code>Mockup</Code> es cromo decorativo; si su contenido es una imagen informativa, la app
le pone <Code>alt</Code>.
</DocRow>
</Stack>
{/snippet}
{#snippet gaps()}
<Stack gap={3}>
<DocRow term="Banda de fondo por fila">
<strong>Diferido</strong> — la app envuelve una <Code>.Row</Code> en un <Code>Surface</Code>;
una prop sería azúcar.
</DocRow>
<DocRow term="Media pegajosa">
<strong>Diferido</strong> — el screenshot se ancla mientras la copy hace scroll; compondría
<Code>Sticky</Code>, se hace cuando una demo lo pida.
</DocRow>
</Stack>
{/snippet}
{#snippet notes()}
<Stack gap={3}>
<DocRow term="El primitivo Mockup">
Se construyó para este block y se retrofiteó en la demo del <Code>hero</Code>: cierra el
hueco de «tratamiento de media» del dossier de raíz, no lo falsea por demo. Cromo de
navegador (barra + dots + URL), teléfono (bisel + notch) y liso.
</DocRow>
</Stack>
{/snippet}
</BlockDemo>

Powered by TurnKey Linux.