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.
194 lines
6.8 KiB
194 lines
6.8 KiB
<script lang="ts">
|
|
/**
|
|
* StatsBand 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 StatsBandSite from './StatsBandSite.svelte';
|
|
import DocRow from '../_lib/DocRow.svelte';
|
|
|
|
let columns = $state(0); // 0 = fluido
|
|
let withCount = $state(true);
|
|
let dir = $state<'ltr' | 'rtl'>('ltr');
|
|
|
|
const previewSrc = $derived(
|
|
`/blocks/stats-band/preview?columns=${columns}&count=${withCount}&dir=${dir}`
|
|
);
|
|
</script>
|
|
|
|
<BlockDemo
|
|
name="Stats band"
|
|
slug="$blocks/stats-band"
|
|
{previewSrc}
|
|
previewHeight="620px"
|
|
meta={[
|
|
{ key: 'compone', value: 'Section · Container · AutoGrid · Metrics · CountUp · Motion' },
|
|
{ key: 'tipo', value: 'compound (.Stat repite)' },
|
|
{ key: 'superación', value: 'count-up (ninguna ref puede)' },
|
|
{ key: 'strings propias', value: '0' }
|
|
]}
|
|
>
|
|
{#snippet preview()}
|
|
<StatsBandSite {columns} {withCount} />
|
|
{/snippet}
|
|
|
|
{#snippet lede()}
|
|
La fila de cifras que respalda lo que la página acaba de afirmar. Compone el <Code>Metrics</Code
|
|
>
|
|
del canon para la semántica de KPI y <Code>CountUp</Code> para la cifra que se cuenta sola al entrar
|
|
en pantalla — <strong>lo único de este tier que ninguna referencia puede shipear</strong>,
|
|
porque todas entregan markup estático.
|
|
{/snippet}
|
|
|
|
{#snippet controls()}
|
|
<Wrap gap={5}>
|
|
<Group gap={2} align="center" justify="start">
|
|
<Text size="sm" color="muted">columnas</Text>
|
|
<ToggleGroup
|
|
selectionMode="single"
|
|
size="sm"
|
|
attached
|
|
value={[String(columns)]}
|
|
onValueChange={(v) => (columns = Number(v[0] ?? columns))}
|
|
aria-label="columnas"
|
|
>
|
|
<ToggleGroup.Item value="0">fluido</ToggleGroup.Item>
|
|
{#each [2, 3, 4] 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">count-up</Text>
|
|
<ToggleGroup
|
|
selectionMode="single"
|
|
size="sm"
|
|
attached
|
|
value={[withCount ? 'sí' : 'no']}
|
|
onValueChange={(v) => (withCount = (v[0] ?? 'sí') === 'sí')}
|
|
aria-label="contar las cifras"
|
|
>
|
|
<ToggleGroup.Item value="sí">sí</ToggleGroup.Item>
|
|
<ToggleGroup.Item value="no">no</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 y escalona; la semántica de KPI es del <Code>Metrics</Code> del canon y el conteo,
|
|
del <Code>CountUp</Code>. Cifras y palabras son de la app.
|
|
</Text>
|
|
<Stack gap={3}>
|
|
<DocRow term="raíz">
|
|
<Code><section></Code> + <Code>Section</Code> + <Code>Container</Code> +
|
|
<Code>AutoGrid</Code> con <Code>data-stagger</Code>: fluido por
|
|
<Code>minChildWidth</Code> o con <Code>columns</Code> fijas.
|
|
</DocRow>
|
|
<DocRow term=".Stat">
|
|
<Code>Motion trigger="viewport"</Code> envolviendo un <Code>Metrics</Code>. ES el reveal,
|
|
así que debe seguir siendo hijo directo de la banda para recibir su índice estructural.
|
|
</DocRow>
|
|
<DocRow term=".Value">
|
|
<Code>Metrics.Value</Code>; con <Code>count</Code> compone <Code>CountUp</Code>. El
|
|
formato es locale-aware y reduced-motion salta al valor final — ambas cosas del
|
|
<Code>CountUp</Code>, no del block.
|
|
</DocRow>
|
|
<DocRow term=".Label"><Code>Metrics.Label</Code>. Las palabras, de la app.</DocRow>
|
|
</Stack>
|
|
</Stack>
|
|
{/snippet}
|
|
|
|
{#snippet api()}
|
|
<Stack gap={3}>
|
|
<DocRow term="StatsBand">
|
|
<Code>containerSize</Code> (def. <Code>lg</Code>) · <Code>sectionSize</Code> (def. <Code
|
|
>lg</Code
|
|
>) ·
|
|
<Code>columns</Code> o <Code>minChildWidth</Code> (def. <Code>12rem</Code>) ·
|
|
<Code>gap</Code> (def. <Code>8</Code>).
|
|
</DocRow>
|
|
<DocRow term=".Stat">
|
|
Todo lo de <Code>Metrics</Code>: <Code>align</Code> (def. <Code>center</Code> — una banda son
|
|
cifras centradas, no tarjetas de panel), <Code>sectionSize</Code> (def. <Code>lg</Code>),
|
|
<Code>live</Code>…
|
|
</DocRow>
|
|
<DocRow term=".Value">
|
|
<Code>count</Code> (number, opt-in) + <Code>countOptions</Code> (todo lo de
|
|
<Code>CountUp</Code> menos <Code>to</Code>). Sin <Code>count</Code>, la cifra la pone la app
|
|
por children.
|
|
</DocRow>
|
|
</Stack>
|
|
{/snippet}
|
|
|
|
{#snippet a11y()}
|
|
<Stack gap={3}>
|
|
<DocRow term="Movimiento">
|
|
El conteo respeta <Code>prefers-reduced-motion</Code>: salta directo al valor final, sin
|
|
animar. Lo resuelve el <Code>CountUp</Code>, no el block.
|
|
</DocRow>
|
|
<DocRow term="Cifras">
|
|
El formato numérico sale de <Code>uix.format</Code> (separadores por idioma), así que la cifra
|
|
se lee correcta en cada locale sin que la app la reescriba.
|
|
</DocRow>
|
|
<DocRow term="Estructura">
|
|
Sin encabezados: una banda son datos, no una sección con título. Si la página necesita uno,
|
|
lo pone alrededor.
|
|
</DocRow>
|
|
</Stack>
|
|
{/snippet}
|
|
|
|
{#snippet gaps()}
|
|
<Stack gap={3}>
|
|
<DocRow term="Split con imagen">
|
|
<strong>Diferido</strong> — la banda junto a una foto: otra disposición (2 columnas), que
|
|
recurre en las refs. Entra como <Code>layout</Code> o hermano cuando una demo lo pida.
|
|
</DocRow>
|
|
<DocRow term="Timeline / stepped">
|
|
<strong>Diferido</strong> — el <Code>Timeline</Code> del canon existe; es otra sección, no una
|
|
banda.
|
|
</DocRow>
|
|
<DocRow term="Delta / tendencia por cifra">
|
|
<strong>App-land</strong> — <Code>Metrics.Delta</Code> se compone dentro del
|
|
<Code>.Stat</Code> hoy; re-exponerlo solo añadiría superficie.
|
|
</DocRow>
|
|
</Stack>
|
|
{/snippet}
|
|
|
|
{#snippet notes()}
|
|
<Stack gap={3}>
|
|
<DocRow term="El count-up es opt-in, nunca por defecto">
|
|
Una cifra que se anima sin que el lector lo pida es ruido, y algunas no son contables
|
|
(«99,98 %»). Por eso <Code>count</Code> se pide explícitamente.
|
|
</DocRow>
|
|
<DocRow term="El block no formatea ni escribe">
|
|
Ni una palabra ni un separador decimal salen de aquí: las palabras por children, el formato
|
|
por <Code>uix.format</Code> dentro del <Code>CountUp</Code>.
|
|
</DocRow>
|
|
</Stack>
|
|
{/snippet}
|
|
</BlockDemo>
|