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/uix/components/scatter-chart/+page.svelte

230 lines
9.6 KiB

<script lang="ts">
import { ScatterChart } from '$uix/eidos/components/chart';
import { compileMorfo } from '$uix/morfo';
import { chartMorfo } from '@/uix/morfo/components/chart';
type Tab = 'live' | 'examples' | 'api' | 'morfo' | 'recipe' | 'a11y';
let tab = $state<Tab>('live');
const data = [
{ x: 5, alpha: 12, beta: 22 },
{ x: 12, alpha: 19, beta: 18 },
{ x: 18, alpha: 15, beta: 30 },
{ x: 25, alpha: 28, beta: 24 },
{ x: 31, alpha: 24, beta: 36 },
{ x: 38, alpha: 35, beta: 29 },
{ x: 44, alpha: 31, beta: 44 },
{ x: 52, alpha: 42, beta: 38 },
{ x: 60, alpha: 38, beta: 51 },
{ x: 68, alpha: 49, beta: 46 }
];
let radius = $state(3.5);
let multi = $state(false);
let grid = $state(true);
let niceY = $state(true);
let height = $state(260);
let showTooltip = $state(true);
const radii = [2.5, 3.5, 5];
const heights = [200, 260, 320];
const seriesKeys = $derived(multi ? ['alpha', 'beta'] : 'alpha');
const compiled = compileMorfo(chartMorfo);
const partsList = $derived([...compiled.parts.byKebab.values()]);
const snippet = $derived(
[
"<script lang='ts'>",
" import { ScatterChart } from '$uix/eidos/components/chart';",
'',
' // rows: a numeric x + one or more y series',
' const data = [',
' { x: 5, alpha: 12, beta: 22 },',
' { x: 12, alpha: 19, beta: 18 }',
' // …',
' ];',
'</' + 'script>',
'',
'<ScatterChart',
' {data}',
' x="x"',
multi ? " y={['alpha', 'beta']}" : ' y="alpha"',
' xScale="linear"',
radius !== 3.5 && ` radius={${radius}}`,
!grid && ' noGrid',
!niceY && ' niceY={false}',
height !== 260 && ` height={${height}}`,
'/>'
]
.filter(Boolean)
.join('\n')
);
</script>
<div data-uix-canvas-inner>
<header>
<div data-uix-eyebrow>Charts · Scatter chart</div>
<h1 data-uix-page-title>Scatter chart</h1>
<p data-uix-page-lede>
Points over a continuous x/y, one circle per datum, on the zero-dependency <code>$libs/plots</code>
engine. Multiple series overlay with distinct palette colours; adjustable point radius.
</p>
<div data-uix-page-meta>
<span data-uix-meta-pill><span data-uix-meta-key>parts</span>{compiled.parts.order.length}</span>
<span data-uix-meta-pill><span data-uix-meta-key>render</span>svg · 0-dep</span>
<span data-uix-meta-pill><span data-uix-meta-key>series</span>{multi ? 2 : 1}</span>
<span data-uix-meta-pill><span data-uix-meta-key>scale</span>linear</span>
</div>
</header>
<div data-uix-stage>
<div data-uix-stage-area>
<ScatterChart {data} x="x" y={seriesKeys} xScale="linear" {radius} {height} {niceY} tooltip={showTooltip} noGrid={!grid} ariaLabel="Scatter plot" />
</div>
<div data-uix-stage-trace>
<span data-uix-stage-trace-key>renders</span>
<span><span data-uix-stage-trace-event>{multi ? 2 : 1} series</span> · r {radius}</span>
<span style="margin-inline-start: auto;"><span data-uix-stage-trace-key>height</span> {height}px</span>
</div>
</div>
<div data-uix-tabs role="tablist">
<button data-uix-tab data-active={tab === 'live'} onclick={() => (tab = 'live')}>Live</button>
<button data-uix-tab data-active={tab === 'examples'} onclick={() => (tab = 'examples')}>Examples</button>
<button data-uix-tab data-active={tab === 'api'} onclick={() => (tab = 'api')}>API</button>
<button data-uix-tab data-active={tab === 'morfo'} onclick={() => (tab = 'morfo')}>
<span data-uix-layer-badge="morfo">morfo</span>
<span data-uix-tab-count>{partsList.length}p</span>
</button>
<button data-uix-tab data-active={tab === 'recipe'} onclick={() => (tab = 'recipe')}>Recipe</button>
<button data-uix-tab data-active={tab === 'a11y'} onclick={() => (tab = 'a11y')}>A11y</button>
</div>
{#if tab === 'live'}
<section data-uix-section>
<h2 data-uix-section-title>Controls</h2>
<p data-uix-section-desc>Pure <span data-uix-layer-badge="eidos">eidos</span> display — every control changes the live chart above.</p>
<div data-uix-controls>
<label data-uix-control>
<span data-uix-control-label>point radius</span>
<span data-uix-chips role="radiogroup">
{#each radii as r}<button data-uix-chip data-active={radius === r} onclick={() => (radius = r)}>{r}</button>{/each}
</span>
</label>
<label data-uix-control>
<span data-uix-control-label>height</span>
<span data-uix-chips role="radiogroup">
{#each heights as h}<button data-uix-chip data-active={height === h} onclick={() => (height = h)}>{h}</button>{/each}
</span>
</label>
<label data-uix-control>
<span data-uix-control-label>series</span>
<span data-uix-switch><input type="checkbox" bind:checked={multi} /><span data-uix-switch-label>{multi ? 'alpha + beta' : 'alpha only'}</span></span>
</label>
<label data-uix-control>
<span data-uix-control-label>grid</span>
<span data-uix-switch><input type="checkbox" bind:checked={grid} /><span data-uix-switch-label>{grid ? 'on' : 'off'}</span></span>
</label>
<label data-uix-control>
<span data-uix-control-label>niceY</span>
<span data-uix-switch><input type="checkbox" bind:checked={niceY} /><span data-uix-switch-label>{niceY ? 'on' : 'off'}</span></span>
</label>
<label data-uix-control>
<span data-uix-control-label>tooltip</span>
<span data-uix-switch><input type="checkbox" bind:checked={showTooltip} /><span data-uix-switch-label>{showTooltip ? 'on' : 'off'}</span></span>
</label>
</div>
<div data-uix-code>
<div data-uix-code-head>
<span data-uix-layer-badge="eidos">eidos</span>
<span>ScatterChart preset</span>
<span data-uix-code-lang>svelte</span>
</div>
<pre><code>{snippet}</code></pre>
</div>
</section>
{/if}
{#if tab === 'examples'}
<section data-uix-section>
<h2 data-uix-section-title>Examples</h2>
<div data-uix-stage-area style="display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1rem;">
<ScatterChart {data} x="x" y="alpha" xScale="linear" title="Single series" height={200} />
<ScatterChart {data} x="x" y="alpha" xScale="linear" radius={5} title="Bigger points" height={200} />
<ScatterChart {data} x="x" y={['alpha', 'beta']} xScale="linear" title="Two series" height={200} />
</div>
</section>
{/if}
{#if tab === 'api'}
<section data-uix-section>
<h2 data-uix-section-title>API reference</h2>
<div data-uix-table-wrap>
<table data-uix-table>
<thead><tr><th>Prop</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td class="name">data</td><td class="type">{`readonly Record<string, unknown>[]`}</td><td class="default empty">—</td><td>Rows of data.</td></tr>
<tr><td class="name">x</td><td class="type">string</td><td class="default empty">—</td><td>x value key (numeric).</td></tr>
<tr><td class="name">y</td><td class="type">{`string | string[]`}</td><td class="default empty">—</td><td>Series key(s).</td></tr>
<tr><td class="name">xScale</td><td class="type">'linear' | 'time' | 'band' | 'point'</td><td class="default">'linear'</td><td>x mapping.</td></tr>
<tr><td class="name">radius</td><td class="type">number</td><td class="default">3.5</td><td>Point radius.</td></tr>
<tr><td class="name">noGrid / niceY</td><td class="type">boolean</td><td class="default">false / true</td><td>Chrome toggles.</td></tr>
<tr><td class="name">height</td><td class="type">number</td><td class="default">260</td><td>Plot height.</td></tr>
<tr><td class="name">title / ariaLabel</td><td class="type">string</td><td class="default empty">—</td><td>Title / accessible name.</td></tr>
</tbody>
</table>
</div>
</section>
{/if}
{#if tab === 'morfo'}
<section data-uix-section>
<h2 data-uix-section-title><span data-uix-layer-badge="morfo">morfo</span> · declarative contract</h2>
<p data-uix-section-desc>Source: <code>src/uix/morfo/components/chart.ts</code>. The chart family shares one <code>scope:['eidos']</code> contract.</p>
<div data-uix-table-wrap>
<table data-uix-table>
<thead><tr><th>Part</th><th>Marker</th><th>Element</th><th>Role</th><th>Optional</th></tr></thead>
<tbody>
{#each partsList as part}
<tr><td class="name">{part.kebab}</td><td><code data-uix-part-marker>[{part.marker}]</code></td><td class="type">&lt;{part.defaultElement}&gt;</td><td class="type">{part.role ?? '—'}</td><td class="default">{part.optional ? 'yes' : 'no'}</td></tr>
{/each}
</tbody>
</table>
</div>
</section>
{/if}
{#if tab === 'recipe'}
<section data-uix-section>
<h2 data-uix-section-title>Eidos recipe</h2>
<p data-uix-section-desc>No <code>--chart-*</code> tokens — styles from global theme tokens.</p>
<div data-uix-table-wrap>
<table data-uix-table>
<thead><tr><th>Surface</th><th>Token</th></tr></thead>
<tbody>
<tr><td class="name">point</td><td class="type">var(--color-{'{'}role{'}'}-solid) per series</td></tr>
<tr><td class="name">axis / grid</td><td class="type">var(--color-border-default / -subtle)</td></tr>
<tr><td class="name">labels</td><td class="type">var(--color-content-secondary)</td></tr>
</tbody>
</table>
</div>
</section>
{/if}
{#if tab === 'a11y'}
<section data-uix-section>
<h2 data-uix-section-title>Accessibility</h2>
<div data-uix-table-wrap>
<table data-uix-table>
<thead><tr><th>Part</th><th>Attribute</th><th>Value</th></tr></thead>
<tbody>
<tr><td class="name">provider (svg)</td><td>role / aria-label</td><td class="type">"img" / ariaLabel</td></tr>
<tr><td class="name">grid / axis</td><td>aria-hidden</td><td class="type">"true"</td></tr>
</tbody>
</table>
</div>
</section>
{/if}
</div>

Powered by TurnKey Linux.