- Rename theme untitled-ui -> Grafito: route /temas/grafito, theme ids
grafito-light/dark, grafitoConfig, brand/hero/footer/index.
- Palette: Grafito now carries the full 32-scale library (spreads the
framework's 31 Radix scales + brand carbon, overriding the brand-tuned
gray/violet/blue + intents). Each directly usable as --scale-{name}-{step}.
- Roles: hierarchy explicit (primary->carbon, secondary->violet,
tertiary->blue); the 6 intents auto-derive from the palette by convention
(step 9). THEME_SCALES derived from palette keys, labelled by COLOR NAME.
- Demo Color section -> 3 groups (Paleta / Roles jerarquia / Intents
auto-derivados) + scaling control in the topbar.
Verified in browser: 32 distinct scales emitted, intents auto-derive
(affirm=teal, risk=amber, loss=plum), no validation error.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
active-uix
parent
152d2ad960
commit
89147d0e1b
File diff suppressed because it is too large
Load Diff
@ -1,836 +0,0 @@
|
||||
<script lang="ts">
|
||||
/**
|
||||
* Página de theming — Untitled UI.
|
||||
* Muestra todos los elementos del tema: paletas de color (roles + rampas
|
||||
* de 12 pasos + superficies), tipografía, espaciado, radios, sombras,
|
||||
* tamaños y el aspecto real de los controles con todas sus variantes.
|
||||
*/
|
||||
import { onMount } from 'svelte'
|
||||
import Button from '$uix/eidos/components/button'
|
||||
import Badge from '$uix/eidos/components/badge'
|
||||
import Card from '$uix/eidos/components/card'
|
||||
import Field from '$uix/eidos/components/field'
|
||||
import Select from '$uix/eidos/components/select'
|
||||
import Checkbox from '$uix/eidos/components/checkbox'
|
||||
import RadioGroup from '$uix/eidos/components/radio-group'
|
||||
import Switch from '$uix/eidos/components/switch'
|
||||
import Slider from '$uix/eidos/components/slider'
|
||||
import Progress from '$uix/eidos/components/progress'
|
||||
import Banner from '$uix/eidos/components/banner'
|
||||
import Avatar from '$uix/eidos/components/avatar'
|
||||
import Separator from '$uix/eidos/components/separator'
|
||||
import Tabs from '$uix/eidos/components/tabs'
|
||||
import Accordion from '$uix/eidos/components/accordion'
|
||||
import Toggle from '$uix/eidos/components/toggle'
|
||||
import ToggleGroup from '$uix/eidos/components/toggle-group'
|
||||
import Toolbar from '$uix/eidos/components/toolbar'
|
||||
import Popover from '$uix/eidos/components/popover'
|
||||
import Dialog from '$uix/eidos/components/dialog'
|
||||
import DropdownMenu from '$uix/eidos/components/dropdown-menu'
|
||||
import ContextMenu from '$uix/eidos/components/context-menu'
|
||||
import Menubar from '$uix/eidos/components/menubar'
|
||||
import Tooltip from '$uix/eidos/components/tooltip'
|
||||
import {
|
||||
THEME_ROLES,
|
||||
THEME_SCALES,
|
||||
COLOR_STEPS
|
||||
} from '../_lib/untitled-ui'
|
||||
|
||||
// ── Hex resolución (lee los literales de las escalas en runtime) ──
|
||||
let hex = $state<Record<string, string>>({})
|
||||
|
||||
function readHex() {
|
||||
if (typeof document === 'undefined') return
|
||||
const cs = getComputedStyle(document.documentElement)
|
||||
const out: Record<string, string> = {}
|
||||
for (const sc of THEME_SCALES) {
|
||||
for (const step of COLOR_STEPS) {
|
||||
const v = cs.getPropertyValue(`--scale-${sc.name}-${step}`).trim()
|
||||
if (v) out[`${sc.name}-${step}`] = v
|
||||
}
|
||||
}
|
||||
hex = out
|
||||
}
|
||||
|
||||
function luminance(value: string): number {
|
||||
const m = value.replace('#', '')
|
||||
if (m.length < 6) return 0.5
|
||||
const r = parseInt(m.slice(0, 2), 16) / 255
|
||||
const g = parseInt(m.slice(2, 4), 16) / 255
|
||||
const b = parseInt(m.slice(4, 6), 16) / 255
|
||||
return 0.2126 * r + 0.7152 * g + 0.0722 * b
|
||||
}
|
||||
|
||||
const stepInk = (key: string) =>
|
||||
luminance(hex[key] ?? '#000000') > 0.55 ? '#101828' : '#ffffff'
|
||||
|
||||
onMount(() => {
|
||||
readHex()
|
||||
const obs = new MutationObserver(() => readHex())
|
||||
obs.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ['data-mode', 'data-theme']
|
||||
})
|
||||
return () => obs.disconnect()
|
||||
})
|
||||
|
||||
// ── Datos de las secciones de tokens ──────────────────────────────
|
||||
const TYPE_STYLES = [
|
||||
{ key: 'hero', label: 'Hero', sample: 'Diseña lo que ocurre' },
|
||||
{ key: 'h1', label: 'Heading 1', sample: 'The quick brown fox' },
|
||||
{ key: 'h2', label: 'Heading 2', sample: 'The quick brown fox' },
|
||||
{ key: 'h3', label: 'Heading 3', sample: 'The quick brown fox jumps' },
|
||||
{ key: 'h4', label: 'Heading 4', sample: 'The quick brown fox jumps over' },
|
||||
{ key: 'body', label: 'Body', sample: 'The quick brown fox jumps over the lazy dog.' },
|
||||
{ key: 'label', label: 'Label', sample: 'Email address' },
|
||||
{ key: 'caption', label: 'Caption', sample: 'Last updated 3 minutes ago' },
|
||||
{ key: 'code', label: 'Code', sample: 'const theme = "untitled-ui"' }
|
||||
]
|
||||
|
||||
const SPACE = ['0', '0-5', '1', '1-5', '2', '2-5', '3', '3-5', '4', '5', '6', '8', '10', '12', '16']
|
||||
const RADII = ['none', 'sm', 'md', 'lg', 'xl', 'xxl']
|
||||
const SHADOWS = ['1', '2', '3', '4', '5', '6']
|
||||
const SIZES = ['xxs', 'xs', 'sm', 'md', 'lg', 'xl', 'xxl']
|
||||
|
||||
const BTN_VARIANTS = ['solid', 'soft', 'surface', 'outline', 'ghost', 'plain'] as const
|
||||
const BTN_SIZES = ['xs', 'sm', 'md', 'lg', 'xl'] as const
|
||||
const CHIP_VARIANTS = ['soft', 'solid', 'outline', 'ghost'] as const
|
||||
const BADGE_COLORS = [
|
||||
'primary',
|
||||
'neutral',
|
||||
'affirm',
|
||||
'fulfill',
|
||||
'risk',
|
||||
'threat',
|
||||
'loss'
|
||||
] as const
|
||||
|
||||
// ── Estado de los controles interactivos ──────────────────────────
|
||||
let email = $state('olivia@untitledui.com')
|
||||
let fruit = $state<string[]>(['mango'])
|
||||
let agree = $state(true)
|
||||
let notify = $state(false)
|
||||
let plan = $state('pro')
|
||||
let wifi = $state(true)
|
||||
let analytics = $state(false)
|
||||
let volume = $state([64])
|
||||
|
||||
let tab = $state('overview')
|
||||
let tabsPills = $state('account')
|
||||
let faq = $state<string[]>(['what'])
|
||||
|
||||
let bold = $state(true)
|
||||
let fmt = $state<string[]>(['bold'])
|
||||
let align = $state<string[]>(['left'])
|
||||
let toolbarFmt = $state<string[]>(['bold'])
|
||||
|
||||
// ── Estado de los overlays / menús ────────────────────────────────
|
||||
let menuNotifications = $state(true)
|
||||
let menuTheme = $state('system')
|
||||
let menubarValue = $state('')
|
||||
|
||||
</script>
|
||||
|
||||
{#snippet plusIcon()}
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M12 5v14M5 12h14" />
|
||||
</svg>
|
||||
{/snippet}
|
||||
|
||||
{#snippet arrowIcon()}
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M5 12h14M13 6l6 6-6 6" />
|
||||
</svg>
|
||||
{/snippet}
|
||||
|
||||
<!-- ═══ Hero ═══════════════════════════════════════════════════════ -->
|
||||
<section data-temas-hero>
|
||||
<h1>Untitled UI · Carbon</h1>
|
||||
<p>
|
||||
Tema para activeUIX sobre el sistema de theming de Eidos. Primario <strong>carbón</strong>
|
||||
monocromo, tipografía Inter, grises fríos, radios de 8px, sombras en capas y anillos de foco
|
||||
suaves — los 9 roles canónicos retintados, sin inventar variants ni roles nuevos.
|
||||
</p>
|
||||
<div data-temas-hero-meta>
|
||||
<span data-temas-pill><i style="background: var(--color-primary-solid)"></i> Carbon · #1F2024</span>
|
||||
<span data-temas-pill><i style="background: var(--color-content-primary)"></i> Inter</span>
|
||||
<span data-temas-pill><i style="background: var(--color-fulfill-solid)"></i> 9 roles · 5 variants</span>
|
||||
<span data-temas-pill><i style="background: var(--color-border-strong)"></i> Light · Dark · Density</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ═══ Color ══════════════════════════════════════════════════════ -->
|
||||
<section data-temas-section>
|
||||
<div data-temas-section-head>
|
||||
<h2>Color</h2>
|
||||
<p>Los 9 roles canónicos mapeados a las paletas de Untitled UI. El theme retinta; los roles son canon fijo del framework.</p>
|
||||
</div>
|
||||
|
||||
<div data-temas-stack>
|
||||
<p data-temas-subhead>Roles semánticos</p>
|
||||
<div data-temas-roles>
|
||||
{#each THEME_ROLES as r}
|
||||
<div data-temas-role>
|
||||
<div data-temas-role-solid style="background: var(--color-{r.role}-solid)"></div>
|
||||
<div data-temas-role-body>
|
||||
<strong>{r.label}</strong>
|
||||
<small>{r.note}</small>
|
||||
<div data-temas-role-tints>
|
||||
<i style="background: var(--color-{r.role}-track)"></i>
|
||||
<i style="background: var(--color-{r.role}-element)"></i>
|
||||
<i style="background: var(--color-{r.role}-border)"></i>
|
||||
<i style="background: var(--color-{r.role}-text)"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-temas-stack>
|
||||
<p data-temas-subhead>Escalas físicas · 12 pasos</p>
|
||||
{#each THEME_SCALES as sc}
|
||||
<div data-temas-ramp>
|
||||
<div data-temas-ramp-head>
|
||||
<strong>{sc.label}</strong>
|
||||
<code>{hex[`${sc.name}-9`] ?? `--scale-${sc.name}-9`}</code>
|
||||
</div>
|
||||
<div data-temas-ramp-steps>
|
||||
{#each COLOR_STEPS as step}
|
||||
<div
|
||||
data-temas-step
|
||||
style="background: var(--scale-{sc.name}-{step}); color: {stepInk(`${sc.name}-${step}`)}"
|
||||
title={hex[`${sc.name}-${step}`] ?? ''}
|
||||
>
|
||||
{step}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<div data-temas-stack>
|
||||
<p data-temas-subhead>Superficies, contenido y bordes</p>
|
||||
<div data-temas-surfaces>
|
||||
<div data-temas-surface style="background: var(--color-surface-default)">
|
||||
<span>surface</span><code>default</code>
|
||||
</div>
|
||||
<div data-temas-surface style="background: var(--color-surface-raised)">
|
||||
<span>surface</span><code>raised</code>
|
||||
</div>
|
||||
<div data-temas-surface style="background: var(--color-surface-muted)">
|
||||
<span>surface</span><code>muted</code>
|
||||
</div>
|
||||
<div data-temas-surface style="background: var(--color-content-primary); color: var(--color-surface-default)">
|
||||
<span>content</span><code style="color: inherit; opacity: .7">primary</code>
|
||||
</div>
|
||||
<div data-temas-surface style="background: var(--color-content-secondary); color: var(--color-surface-default)">
|
||||
<span>content</span><code style="color: inherit; opacity: .7">secondary</code>
|
||||
</div>
|
||||
<div data-temas-surface style="background: var(--color-surface-raised); border-color: var(--color-border-strong); border-width: 2px">
|
||||
<span>border</span><code>strong</code>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ═══ Tipografía ═════════════════════════════════════════════════ -->
|
||||
<section data-temas-section>
|
||||
<div data-temas-section-head>
|
||||
<h2>Tipografía</h2>
|
||||
<p>Inter para display y texto. Named styles del sistema (hero → caption + code).</p>
|
||||
</div>
|
||||
<div data-temas-panel>
|
||||
{#each TYPE_STYLES as t}
|
||||
<div data-temas-type-row>
|
||||
<div data-temas-type-meta>
|
||||
<strong>{t.label}</strong>
|
||||
<code>--style-{t.key}</code>
|
||||
</div>
|
||||
<div
|
||||
data-temas-type-sample
|
||||
style="font-family: var(--style-{t.key}-font-family); font-size: var(--style-{t.key}-font-size); font-weight: var(--style-{t.key}-font-weight); line-height: var(--style-{t.key}-line-height); letter-spacing: var(--style-{t.key}-letter-spacing);"
|
||||
>
|
||||
{t.sample}
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ═══ Espaciado / Radio / Sombra / Tamaño ════════════════════════ -->
|
||||
<section data-temas-section>
|
||||
<div data-temas-section-head>
|
||||
<h2>Espaciado, radio, sombra y tamaño</h2>
|
||||
<p>Primitivas estables del tema. La escala base es de 4px; controles a 8px de radio.</p>
|
||||
</div>
|
||||
|
||||
<div data-temas-fieldset>
|
||||
<div data-temas-panel data-temas-stack>
|
||||
<p data-temas-subhead>Spacing</p>
|
||||
{#each SPACE as k}
|
||||
<div data-temas-space-row>
|
||||
<code>--space-{k}</code>
|
||||
<div data-temas-space-bar style="inline-size: var(--space-{k})"></div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<div data-temas-stack>
|
||||
<div data-temas-panel data-temas-stack>
|
||||
<p data-temas-subhead>Radius</p>
|
||||
<div data-temas-tiles>
|
||||
{#each RADII as k}
|
||||
<div data-temas-radius-tile style="border-radius: var(--radius-{k})">{k}</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-temas-panel data-temas-stack>
|
||||
<p data-temas-subhead>Sizes · control-height</p>
|
||||
{#each SIZES as k}
|
||||
<div data-temas-size-row>
|
||||
<div data-temas-size-bar style="block-size: var(--size-{k}-control-height)">{k}</div>
|
||||
<code style="color: var(--color-content-muted); font-family: var(--font-mono); font-size: var(--font-size-xs)">var(--size-{k}-control-height)</code>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-temas-panel data-temas-stack>
|
||||
<p data-temas-subhead>Shadows</p>
|
||||
<div data-temas-tiles>
|
||||
{#each SHADOWS as k}
|
||||
<div data-temas-shadow-tile style="box-shadow: var(--shadow-{k})">shadow-{k}</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ═══ Botones ════════════════════════════════════════════════════ -->
|
||||
<section data-temas-section>
|
||||
<div data-temas-section-head>
|
||||
<h2>Botones</h2>
|
||||
<p>6 variants · 9 roles · 5 tamaños · estados. El primario es carbón; el texto sobre sólidos de color resuelve a blanco.</p>
|
||||
</div>
|
||||
|
||||
<div data-temas-demo>
|
||||
<div data-temas-demo-block>
|
||||
<p data-temas-subhead>Variants</p>
|
||||
<div data-temas-cluster>
|
||||
{#each BTN_VARIANTS as v}
|
||||
<Button variant={v}>{v}</Button>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-temas-demo-block>
|
||||
<p data-temas-subhead>Roles e intents</p>
|
||||
<div data-temas-cluster>
|
||||
<Button color="primary">Primary</Button>
|
||||
<Button color="secondary" variant="surface">Secondary</Button>
|
||||
<Button color="neutral" variant="outline">Neutral</Button>
|
||||
<Button intent="affirm">Affirm</Button>
|
||||
<Button intent="fulfill">Fulfill</Button>
|
||||
<Button intent="risk">Risk</Button>
|
||||
<Button intent="threat">Threat</Button>
|
||||
<Button intent="loss">Loss</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-temas-demo-block>
|
||||
<p data-temas-subhead>Tamaños</p>
|
||||
<div data-temas-cluster>
|
||||
{#each BTN_SIZES as sz}
|
||||
<Button size={sz}>Button {sz}</Button>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-temas-demo-block>
|
||||
<p data-temas-subhead>Con icono y estados</p>
|
||||
<div data-temas-cluster>
|
||||
<Button icon={plusIcon}>Nuevo</Button>
|
||||
<Button variant="outline" endIcon={arrowIcon}>Continuar</Button>
|
||||
<Button iconOnly icon={plusIcon} aria-label="Añadir" />
|
||||
<Button loading>Guardando</Button>
|
||||
<Button disabled>Desactivado</Button>
|
||||
<Button intent="threat" variant="soft">Eliminar</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ═══ Badges ═════════════════════════════════════════════════════ -->
|
||||
<section data-temas-section>
|
||||
<div data-temas-section-head>
|
||||
<h2>Badges</h2>
|
||||
<p>Pills de estado en los 4 chip-variants y la paleta completa de roles.</p>
|
||||
</div>
|
||||
<div data-temas-demo>
|
||||
<div data-temas-demo-block>
|
||||
<p data-temas-subhead>Colores (soft)</p>
|
||||
<div data-temas-cluster>
|
||||
{#each BADGE_COLORS as c}
|
||||
<Badge color={c} dot>{c}</Badge>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
<div data-temas-demo-block>
|
||||
<p data-temas-subhead>Variants</p>
|
||||
<div data-temas-cluster>
|
||||
{#each CHIP_VARIANTS as v}
|
||||
<Badge color="primary" variant={v}>{v}</Badge>
|
||||
{/each}
|
||||
<Badge color="fulfill" variant="soft">Activo</Badge>
|
||||
<Badge color="risk" variant="soft" removable onRemove={() => {}}>Filtro</Badge>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ═══ Formulario ═════════════════════════════════════════════════ -->
|
||||
<section data-temas-section>
|
||||
<div data-temas-section-head>
|
||||
<h2>Controles de formulario</h2>
|
||||
<p>Field, Select, Checkbox, Radio, Switch y Slider con el aspecto del tema.</p>
|
||||
</div>
|
||||
|
||||
<div data-temas-fieldset>
|
||||
<div data-temas-panel data-temas-stack>
|
||||
<Field name="email">
|
||||
<Field.Label>Email <Field.RequiredIndicator /></Field.Label>
|
||||
<Field.Control>
|
||||
<Field.Input type="email" bind:value={email} placeholder="tú@empresa.com" />
|
||||
</Field.Control>
|
||||
<Field.HelperText>Usaremos esto para iniciar sesión.</Field.HelperText>
|
||||
</Field>
|
||||
|
||||
<Field name="fruit">
|
||||
<Field.Label>Fruta favorita</Field.Label>
|
||||
<Select bind:value={fruit}>
|
||||
<Select.Trigger>
|
||||
<Select.Value placeholder="Elige una fruta" />
|
||||
<Select.Indicator />
|
||||
</Select.Trigger>
|
||||
<Select.Portal>
|
||||
<Select.Content sideOffset={6}>
|
||||
<Select.Viewport>
|
||||
<Select.Item value="mango" label="Mango">Mango<Select.ItemIndicator /></Select.Item>
|
||||
<Select.Item value="lychee" label="Lichi">Lichi<Select.ItemIndicator /></Select.Item>
|
||||
<Select.Item value="guava" label="Guayaba">Guayaba<Select.ItemIndicator /></Select.Item>
|
||||
<Select.Item value="papaya" label="Papaya">Papaya<Select.ItemIndicator /></Select.Item>
|
||||
</Select.Viewport>
|
||||
</Select.Content>
|
||||
</Select.Portal>
|
||||
</Select>
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
<div data-temas-panel data-temas-stack>
|
||||
<p data-temas-subhead>Selección</p>
|
||||
<label data-temas-cluster style="cursor: pointer">
|
||||
<Checkbox bind:checked={agree}><Checkbox.Indicator /></Checkbox>
|
||||
<span>Acepto los términos del servicio</span>
|
||||
</label>
|
||||
<label data-temas-cluster style="cursor: pointer">
|
||||
<Checkbox bind:checked={notify} color="affirm"><Checkbox.Indicator /></Checkbox>
|
||||
<span>Enviarme novedades del producto</span>
|
||||
</label>
|
||||
|
||||
<Separator />
|
||||
|
||||
<RadioGroup bind:value={plan}>
|
||||
<RadioGroup.Label data-temas-subhead>Plan</RadioGroup.Label>
|
||||
<label data-temas-cluster style="cursor: pointer">
|
||||
<RadioGroup.Item value="starter"><RadioGroup.Indicator /></RadioGroup.Item>
|
||||
<span>Starter</span>
|
||||
</label>
|
||||
<label data-temas-cluster style="cursor: pointer">
|
||||
<RadioGroup.Item value="pro"><RadioGroup.Indicator /></RadioGroup.Item>
|
||||
<span>Pro</span>
|
||||
</label>
|
||||
<label data-temas-cluster style="cursor: pointer">
|
||||
<RadioGroup.Item value="enterprise"><RadioGroup.Indicator /></RadioGroup.Item>
|
||||
<span>Enterprise</span>
|
||||
</label>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
|
||||
<div data-temas-panel data-temas-stack>
|
||||
<p data-temas-subhead>Switch & Slider</p>
|
||||
<label data-temas-cluster style="justify-content: space-between; cursor: pointer">
|
||||
<span>Wi-Fi</span>
|
||||
<Switch bind:checked={wifi}><Switch.Thumb /></Switch>
|
||||
</label>
|
||||
<label data-temas-cluster style="justify-content: space-between; cursor: pointer">
|
||||
<span>Analítica</span>
|
||||
<Switch bind:checked={analytics} intent="affirm"><Switch.Thumb /></Switch>
|
||||
</label>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div data-temas-stack style="gap: var(--space-2)">
|
||||
<span data-temas-subhead style="margin: 0">Volumen · {volume[0]}%</span>
|
||||
<Slider bind:value={volume} min={0} max={100} aria-label="Volumen">
|
||||
<Slider.Range />
|
||||
<Slider.Thumb index={0} />
|
||||
</Slider>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ═══ Feedback ═══════════════════════════════════════════════════ -->
|
||||
<section data-temas-section>
|
||||
<div data-temas-section-head>
|
||||
<h2>Feedback y estado</h2>
|
||||
<p>Banners por intent, progreso, avatares y tarjetas.</p>
|
||||
</div>
|
||||
|
||||
<div data-temas-stack>
|
||||
<Banner intent="primary" variant="soft">Tu prueba gratuita termina en 7 días. Mejora tu plan cuando quieras.</Banner>
|
||||
<Banner intent="fulfill" variant="soft">Cambios guardados correctamente.</Banner>
|
||||
<Banner intent="risk" variant="soft">Tu método de pago caduca pronto.</Banner>
|
||||
<Banner intent="threat" variant="soft">No se pudo procesar el pago. Revisa tus datos.</Banner>
|
||||
</div>
|
||||
|
||||
<div data-temas-fieldset>
|
||||
<div data-temas-panel data-temas-stack>
|
||||
<p data-temas-subhead>Progress</p>
|
||||
<Progress value={64} max={100}>
|
||||
<Progress.Label>Subiendo archivo</Progress.Label>
|
||||
<Progress.ValueText />
|
||||
<Progress.Indicator />
|
||||
</Progress>
|
||||
<div data-temas-cluster>
|
||||
<Progress value={72} max={100} shape="circular"><Progress.Indicator /></Progress>
|
||||
<Progress value={30} max={100} shape="circular"><Progress.Indicator /></Progress>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-temas-panel data-temas-stack>
|
||||
<p data-temas-subhead>Avatares</p>
|
||||
<div data-temas-cluster>
|
||||
<Avatar><Avatar.Fallback>OV</Avatar.Fallback></Avatar>
|
||||
<Avatar color="primary"><Avatar.Fallback>AM</Avatar.Fallback></Avatar>
|
||||
<Avatar color="affirm" variant="soft">
|
||||
<Avatar.Fallback>JV</Avatar.Fallback>
|
||||
<Avatar.Badge color="fulfill" position="bottom-end" dot />
|
||||
</Avatar>
|
||||
<Avatar color="risk" ring="soft"><Avatar.Fallback>SK</Avatar.Fallback></Avatar>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Card variant="soft" color="primary">
|
||||
<Card.Header>
|
||||
<Card.Title>Plan Pro</Card.Title>
|
||||
<Card.Description>Todo lo del Starter, más colaboración ilimitada.</Card.Description>
|
||||
</Card.Header>
|
||||
<Card.Body>
|
||||
<strong style="font-size: var(--font-size-xl)">$29</strong>
|
||||
<span style="color: var(--color-content-muted)"> / mes</span>
|
||||
</Card.Body>
|
||||
<Card.Footer>
|
||||
<Button block icon={arrowIcon}>Elegir Pro</Button>
|
||||
</Card.Footer>
|
||||
</Card>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ═══ Tabs ═══════════════════════════════════════════════════════ -->
|
||||
<section data-temas-section>
|
||||
<div data-temas-section-head>
|
||||
<h2>Tabs</h2>
|
||||
<p>Variantes line y pills. Indicador animado, foco con anillo carbón, activo en color primario.</p>
|
||||
</div>
|
||||
<div data-temas-fieldset>
|
||||
<div data-temas-panel data-temas-stack>
|
||||
<p data-temas-subhead>Line</p>
|
||||
<Tabs bind:value={tab} variant="line">
|
||||
<Tabs.List aria-label="Secciones de ejemplo">
|
||||
<Tabs.Trigger value="overview">Overview</Tabs.Trigger>
|
||||
<Tabs.Trigger value="activity">Activity</Tabs.Trigger>
|
||||
<Tabs.Trigger value="settings">Settings</Tabs.Trigger>
|
||||
<Tabs.Indicator />
|
||||
</Tabs.List>
|
||||
<Tabs.Content value="overview">Resumen de la cuenta y métricas clave del mes.</Tabs.Content>
|
||||
<Tabs.Content value="activity">Registro de actividad reciente del equipo.</Tabs.Content>
|
||||
<Tabs.Content value="settings">Preferencias de notificación y seguridad.</Tabs.Content>
|
||||
</Tabs>
|
||||
</div>
|
||||
<div data-temas-panel data-temas-stack>
|
||||
<p data-temas-subhead>Pills</p>
|
||||
<Tabs bind:value={tabsPills} variant="pills">
|
||||
<Tabs.List aria-label="Secciones de ejemplo">
|
||||
<Tabs.Trigger value="account">Account</Tabs.Trigger>
|
||||
<Tabs.Trigger value="team">Team</Tabs.Trigger>
|
||||
<Tabs.Trigger value="billing">Billing</Tabs.Trigger>
|
||||
<Tabs.Indicator />
|
||||
</Tabs.List>
|
||||
<Tabs.Content value="account">Datos de perfil y sesión.</Tabs.Content>
|
||||
<Tabs.Content value="team">Miembros e invitaciones.</Tabs.Content>
|
||||
<Tabs.Content value="billing">Plan, método de pago y facturas.</Tabs.Content>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ═══ Disclosure ═════════════════════════════════════════════════ -->
|
||||
<section data-temas-section>
|
||||
<div data-temas-section-head>
|
||||
<h2>Disclosure</h2>
|
||||
<p>Accordion (outline) — apertura única, chevron y foco coherentes con el tema.</p>
|
||||
</div>
|
||||
<div data-temas-panel>
|
||||
<Accordion bind:value={faq} type="single" variant="outline">
|
||||
<Accordion.Item value="what">
|
||||
<Accordion.Header><Accordion.Trigger>¿Qué es activeUIX?</Accordion.Trigger></Accordion.Header>
|
||||
<Accordion.Content>
|
||||
Un sistema de UI en cuatro capas — morfo, soma, sema y eidos — donde el theming vive en
|
||||
eidos y retinta los roles canónicos.
|
||||
</Accordion.Content>
|
||||
</Accordion.Item>
|
||||
<Accordion.Item value="theme">
|
||||
<Accordion.Header><Accordion.Trigger>¿Cómo se crea un tema?</Accordion.Trigger></Accordion.Header>
|
||||
<Accordion.Content>
|
||||
Con <code>ActiveEidos.create({ config })</code>: se remapean los 9 roles a paletas
|
||||
y se ajustan primitivas estables (tipografía, radio, sombra).
|
||||
</Accordion.Content>
|
||||
</Accordion.Item>
|
||||
<Accordion.Item value="dark">
|
||||
<Accordion.Header><Accordion.Trigger>¿Y el modo oscuro?</Accordion.Trigger></Accordion.Header>
|
||||
<Accordion.Content>
|
||||
El tema declara escalas light y dark; el primario carbón se invierte solo gracias al slot
|
||||
<code>contrast</code>.
|
||||
</Accordion.Content>
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<!-- ═══ Toggles ════════════════════════════════════════════════════ -->
|
||||
<section data-temas-section>
|
||||
<div data-temas-section-head>
|
||||
<h2>Toggles</h2>
|
||||
<p>Toggle suelto y toggle-group (segmentado, single + multiple). Activo en color primario.</p>
|
||||
</div>
|
||||
<div data-temas-demo>
|
||||
<div data-temas-demo-block>
|
||||
<p data-temas-subhead>Toggle</p>
|
||||
<div data-temas-cluster>
|
||||
<Toggle bind:pressed={bold}>Bold</Toggle>
|
||||
<Toggle variant="outline">Outline</Toggle>
|
||||
<Toggle variant="ghost">Ghost</Toggle>
|
||||
<Toggle disabled>Disabled</Toggle>
|
||||
</div>
|
||||
</div>
|
||||
<div data-temas-demo-block>
|
||||
<p data-temas-subhead>Toggle group · segmentado</p>
|
||||
<div data-temas-cluster>
|
||||
<ToggleGroup type="multiple" attached bind:value={fmt} aria-label="Formato de texto">
|
||||
<ToggleGroup.Item value="bold">B</ToggleGroup.Item>
|
||||
<ToggleGroup.Item value="italic">I</ToggleGroup.Item>
|
||||
<ToggleGroup.Item value="underline">U</ToggleGroup.Item>
|
||||
</ToggleGroup>
|
||||
<ToggleGroup type="single" attached bind:value={align} aria-label="Alineación">
|
||||
<ToggleGroup.Item value="left">Izq.</ToggleGroup.Item>
|
||||
<ToggleGroup.Item value="center">Centro</ToggleGroup.Item>
|
||||
<ToggleGroup.Item value="right">Der.</ToggleGroup.Item>
|
||||
</ToggleGroup>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ═══ Toolbar ════════════════════════════════════════════════════ -->
|
||||
<section data-temas-section>
|
||||
<div data-temas-section-head>
|
||||
<h2>Toolbar</h2>
|
||||
<p>Barra de herramientas con botones, separador y grupo segmentado.</p>
|
||||
</div>
|
||||
<div data-temas-panel>
|
||||
<Toolbar aria-label="Editor">
|
||||
<Toolbar.Button>Deshacer</Toolbar.Button>
|
||||
<Toolbar.Button>Rehacer</Toolbar.Button>
|
||||
<Toolbar.Separator />
|
||||
<Toolbar.Group type="multiple" bind:value={toolbarFmt} aria-label="Formato">
|
||||
<Toolbar.GroupItem value="bold">B</Toolbar.GroupItem>
|
||||
<Toolbar.GroupItem value="italic">I</Toolbar.GroupItem>
|
||||
<Toolbar.GroupItem value="underline">U</Toolbar.GroupItem>
|
||||
</Toolbar.Group>
|
||||
<Toolbar.Separator />
|
||||
<Toolbar.Button>Compartir</Toolbar.Button>
|
||||
</Toolbar>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<!-- ═══ Overlays ═══════════════════════════════════════════════════ -->
|
||||
<section data-temas-section>
|
||||
<div data-temas-section-head>
|
||||
<h2>Overlays</h2>
|
||||
<p>Popover y dialog — paneles portaleados con la superficie, borde y sombra del tema.</p>
|
||||
</div>
|
||||
<div data-temas-panel data-temas-cluster>
|
||||
<Popover>
|
||||
<Popover.Trigger>Abrir popover</Popover.Trigger>
|
||||
<Popover.Portal>
|
||||
<Popover.Content side="bottom" align="start" sideOffset={8}>
|
||||
<Popover.Arrow />
|
||||
<Popover.Title>Dimensiones</Popover.Title>
|
||||
<Popover.Description>Ajusta el ancho del panel lateral.</Popover.Description>
|
||||
<div data-temas-cluster style="margin-block-start: var(--space-3)">
|
||||
<Button size="sm">Aplicar</Button>
|
||||
<Popover.Close>Cerrar</Popover.Close>
|
||||
</div>
|
||||
</Popover.Content>
|
||||
</Popover.Portal>
|
||||
</Popover>
|
||||
|
||||
<Dialog>
|
||||
<Dialog.Trigger>Abrir dialog</Dialog.Trigger>
|
||||
<Dialog.Portal>
|
||||
<Dialog.Overlay />
|
||||
<Dialog.Content>
|
||||
<Dialog.Header>
|
||||
<Dialog.Title>¿Eliminar proyecto?</Dialog.Title>
|
||||
<Dialog.Description>
|
||||
Esta acción es permanente y no se puede deshacer.
|
||||
</Dialog.Description>
|
||||
</Dialog.Header>
|
||||
<Dialog.Footer>
|
||||
<Dialog.Close>Cancelar</Dialog.Close>
|
||||
<Button intent="threat">Eliminar</Button>
|
||||
</Dialog.Footer>
|
||||
</Dialog.Content>
|
||||
</Dialog.Portal>
|
||||
</Dialog>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ═══ Menús ══════════════════════════════════════════════════════ -->
|
||||
<section data-temas-section>
|
||||
<div data-temas-section-head>
|
||||
<h2>Menús</h2>
|
||||
<p>Dropdown, menubar, context menu y tooltip — todos portaleados, con la sombra del tema.</p>
|
||||
</div>
|
||||
<div data-temas-panel data-temas-stack>
|
||||
<p data-temas-subhead>Menubar</p>
|
||||
<Menubar bind:value={menubarValue}>
|
||||
<Menubar.Menu value="file">
|
||||
<Menubar.Trigger>Archivo</Menubar.Trigger>
|
||||
<Menubar.Portal>
|
||||
<Menubar.Content>
|
||||
<Menubar.Item>Nuevo documento</Menubar.Item>
|
||||
<Menubar.Item>Abrir…</Menubar.Item>
|
||||
<Menubar.Separator />
|
||||
<Menubar.Item>Guardar</Menubar.Item>
|
||||
</Menubar.Content>
|
||||
</Menubar.Portal>
|
||||
</Menubar.Menu>
|
||||
<Menubar.Menu value="edit">
|
||||
<Menubar.Trigger>Editar</Menubar.Trigger>
|
||||
<Menubar.Portal>
|
||||
<Menubar.Content>
|
||||
<Menubar.Item>Deshacer</Menubar.Item>
|
||||
<Menubar.Item>Rehacer</Menubar.Item>
|
||||
</Menubar.Content>
|
||||
</Menubar.Portal>
|
||||
</Menubar.Menu>
|
||||
<Menubar.Menu value="view">
|
||||
<Menubar.Trigger>Ver</Menubar.Trigger>
|
||||
<Menubar.Portal>
|
||||
<Menubar.Content>
|
||||
<Menubar.CheckboxItem bind:checked={menuNotifications}>
|
||||
Mostrar barra lateral
|
||||
</Menubar.CheckboxItem>
|
||||
</Menubar.Content>
|
||||
</Menubar.Portal>
|
||||
</Menubar.Menu>
|
||||
</Menubar>
|
||||
|
||||
<div data-temas-cluster>
|
||||
<DropdownMenu>
|
||||
<DropdownMenu.Trigger variant="outline">Opciones</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Content side="bottom" align="start" sideOffset={6}>
|
||||
<DropdownMenu.Group>
|
||||
<DropdownMenu.GroupHeading>Cuenta</DropdownMenu.GroupHeading>
|
||||
<DropdownMenu.Item>Perfil</DropdownMenu.Item>
|
||||
<DropdownMenu.Item>Facturación</DropdownMenu.Item>
|
||||
</DropdownMenu.Group>
|
||||
<DropdownMenu.Separator />
|
||||
<DropdownMenu.CheckboxItem bind:checked={menuNotifications}>
|
||||
Notificaciones
|
||||
</DropdownMenu.CheckboxItem>
|
||||
<DropdownMenu.Separator />
|
||||
<DropdownMenu.RadioGroup bind:value={menuTheme}>
|
||||
<DropdownMenu.RadioItem value="light">Claro</DropdownMenu.RadioItem>
|
||||
<DropdownMenu.RadioItem value="dark">Oscuro</DropdownMenu.RadioItem>
|
||||
<DropdownMenu.RadioItem value="system">Sistema</DropdownMenu.RadioItem>
|
||||
</DropdownMenu.RadioGroup>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu>
|
||||
|
||||
<Tooltip.Group delayDuration={250}>
|
||||
<Tooltip>
|
||||
<Tooltip.Trigger>Pasa el ratón</Tooltip.Trigger>
|
||||
<Tooltip.Portal>
|
||||
<Tooltip.Content>
|
||||
<Tooltip.Arrow />
|
||||
Tooltip con la superficie y la sombra del tema
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Portal>
|
||||
</Tooltip>
|
||||
</Tooltip.Group>
|
||||
</div>
|
||||
|
||||
<ContextMenu>
|
||||
<ContextMenu.Trigger>
|
||||
<div data-temas-ctx-target>Click derecho aquí</div>
|
||||
</ContextMenu.Trigger>
|
||||
<ContextMenu.Content>
|
||||
<ContextMenu.Item>Copiar</ContextMenu.Item>
|
||||
<ContextMenu.Item>Pegar</ContextMenu.Item>
|
||||
<ContextMenu.Separator />
|
||||
<ContextMenu.Item>Duplicar</ContextMenu.Item>
|
||||
</ContextMenu.Content>
|
||||
</ContextMenu>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ═══ Semántica ══════════════════════════════════════════════════ -->
|
||||
<section data-temas-section>
|
||||
<div data-temas-section-head>
|
||||
<h2>Semántica (sema)</h2>
|
||||
<p>
|
||||
La capa perceptual está activa: cada interacción emite una señal con familia + intent que se
|
||||
materializa en <strong>sonido</strong> (earcon), <strong>haptic</strong> (Vibration API) y una
|
||||
<strong>reacción visual</strong> <code>data-event-*</code> teñida por el intent del tema.
|
||||
Pulsa los botones — en un navegador con gesto de usuario sonarán.
|
||||
</p>
|
||||
</div>
|
||||
<div data-temas-panel data-temas-stack>
|
||||
<p data-temas-subhead>Intents perceptuales</p>
|
||||
<div data-temas-cluster>
|
||||
<Button intent="affirm">Affirm</Button>
|
||||
<Button intent="fulfill">Fulfill</Button>
|
||||
<Button intent="risk" variant="soft">Risk</Button>
|
||||
<Button intent="threat" variant="soft">Threat</Button>
|
||||
<Button intent="loss" variant="soft">Loss</Button>
|
||||
</div>
|
||||
<p style="color: var(--color-content-muted); font-size: var(--font-size-sm)">
|
||||
El motor (<code>EngineSemantic</code>) se cablea en el layout vía
|
||||
<code>createActiveUix({ events: { sound, haptic, components } })</code> con
|
||||
los packs sema por componente. Sonido y haptic son opt-in; aquí están encendidos.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer data-temas-foot>
|
||||
Tema <code>untitled-ui</code> · construido con <code>ActiveEidos.create({ config })</code> ·
|
||||
primario carbón + 9 roles canónicos retintados sobre Untitled UI.
|
||||
</footer>
|
||||
Loading…
Reference in new issue