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/src/uix/eidos/components/tabs/README.md

9.2 KiB

Eidos Tabs

Visual wrapper over Soma Tabs. Eidos adds size, variant, collapse and motion presentation; Soma owns value, activation mode, roving focus, ARIA, presence and event emission.

Baselines

Platform Surface Comparison
Air (glm-5) Tabs, List, Trigger, Content; sizes xs-lg, variants line/surface/pills, mobile vertical collapse below md, behavior cue on value change. Covered. Eidos keeps the same variants and size range, generalizes collapse through collapseAt, and exposes motion through CSS/data attrs.
Radix Tabs Root, List, Trigger, Content; controlled/uncontrolled, orientation, dir, activation mode, list loop, forceMount. Covered by Soma/Eidos. Loop lives on root instead of list.
Bits UI Tabs Root, List, Trigger, Content; bindable value, automatic/manual activation, force-mounted transitions. Covered. Eidos keeps transitions declarative with motionPreset and content keepMounted.
Ark UI Tabs Root, List, Trigger, Content, Indicator; activation mode, deselectable, lazyMount, unmountOnExit, custom ids. Indicator is covered. deselectable is intentionally not supported; tabs remain one-of-many. lazyMount/unmountOnExit map to Soma default plus forceMount/keepMounted.
shadcn-svelte Tabs Styled Bits/Radix-like Root/List/Trigger/Content. Covered with first-party tokens and compound namespace.
React Aria Tabs Tabs, TabList, Tab, TabPanel; orientation, disabled keys, controlled selection and accessibility relations. Covered with per-trigger disabled and value-based trigger/content registry.

Sources: Radix, Bits UI, Ark UI, shadcn-svelte, React Aria.

Anatomy

<script lang="ts">
	import { Tabs } from '$uix/eidos/components/tabs';

	let value = $state('account');
</script>

<Tabs bind:value variant="line" size="md">
	<Tabs.List aria-label="Account sections">
		<Tabs.Trigger value="account">Account</Tabs.Trigger>
		<Tabs.Trigger value="security">Security</Tabs.Trigger>
		<Tabs.Indicator />
	</Tabs.List>

	<Tabs.Content value="account">Account panel</Tabs.Content>
	<Tabs.Content value="security" keepMounted>Security panel</Tabs.Content>
</Tabs>

Decisions

Gap / Choice Decision
Air mobile collapse was hard-coded to md Eidos uses `collapseAt: 'never'
Ark deselectable Not supported. Tabs are a required one-of-many content selector in UIX; deselection belongs to disclosure/toggle patterns.
Ark lazyMount / unmountOnExit Soma default is lazy/unmounted inactive content. keepMounted aliases Soma forceMount for consumers that need persistent panels.
Ark/animated indicator Implemented as Tabs.Indicator; measurement is visual-only in Eidos, while the part marker remains declared in Morfo/Soma.
Tablist accessible name Tabs.List requires consumer-provided aria-label or aria-labelledby; Soma warns in dev instead of inventing a generic label.

Visual Props

Prop Values Effect
size xs | sm | md | lg Trigger height, padding and content spacing.
variant line | surface | pills Underline, card/surface, or pill-track treatment.
fitted boolean Triggers take equal width.
collapseAt 'never' | breakpoint | px number Vertical tabs collapse responsively below threshold.
scrollable boolean Allows overflow scrolling on the list.
motionPreset none | fade | slide Content transition recipe.

Ownership

  • Morfo declares tab/list/trigger/content/indicator roles, states and ARIA relationships.
  • Soma owns value, keyboard navigation, activation mode, trigger/content ID registries, disabled handling, presence and the indicator's MEASUREMENT (MeasuredIndicator, exposed as --indicator-{x,y,w,h}).
  • Eidos owns size/variant/collapse/scroll/motion presentation, and positions + shapes the indicator from those vars — the "soma positions, eidos shapes" contract. The measurement used to live in the eidos wrapper; it moved to soma so it re-measures on an RTL flip, which a wrapper with no access to the resolved direction could not do.

Talla y tema

79 claves públicas en lib/recipes/base.ts, y la pestaña Tokens de su demo las resuelve en vivo sobre el escenario. El reparto, por dónde pintan:

grupo claves notas
Pila del provider stack-gap, line-stack-gap el hueco lista↔panel; line lo aprieta
Marco surface provider-{radius,border-width,border,bg}, surface-provider-{padding,shadow} sólo bajo variant='surface'
Lista list-{gap,padding,radius,width,bg,border-width,border}, line-list-padding-inline-end, surface-list-bg, pills-list-bg, segmented-list-{bg,radius} list-width es el raíl VERTICAL
Trigger, por talla trigger-height-{xs,sm,md,lg}, trigger-padding-inline-{…}, trigger-gap-{…}, trigger-font-size-{…} cada uno al bundle --size-{k}-*
Trigger, cromo trigger-{radius,border-width,bg,border,fg}, trigger-font-{family,weight}, trigger-line-height, trigger-letter-spacing, hover-trigger-fg, active-trigger-{fg,bg,border}, pills-trigger-radius, segmented-trigger-radius, active-{surface,pills}-trigger-border, active-pills-trigger-shadow, active-segmented-trigger-{bg,fg,shadow} el modificador va DELANTE (D-TH.6)
Foco y estado trigger-focus-ring-{offset,width,color}, disabled-opacity el trío de foco ESPEJA la familia del sistema — exento de la gramática de tinta
Panel content-padding-{xs,sm,md,lg}, content-{radius,bg,border-width,border,fg}, surface-content-{border,bg}, pills-content-padding-block-start
Indicador indicator-transition-{duration,ease}, indicator-line-thickness la FORMA y el deslizamiento
Movimiento trigger-transition-{duration,ease}, scrollable-fade

Lo que el eje dejó fuera el 2026-08-24 (96 % → 97 %), medido y escrito:

  • --indicator-{x,y,w,h} NO se acuñan. Son el canal de VALOR de soma: la capa MeasuredIndicator escribe el rect del trigger activo en cada movimiento. Un público encima sería un knob que un tema podría fijar, y fijarlo rompe el deslizamiento — la misma adjudicación que navigation-menu ya lleva para su propio indicator-w.
  • width: 100% de fitted es identidad, no knob: fitted ES «la lista llena el eje inline». Firmado con su anotación literal:.

Lo que el guard R-5.4 da por silencioso (70/79 mueven; 9 adjudicados en scripts/theming-sentinel-exceptions.ts, todos medidos a mano): los cuatro tokens de transición —el guard CONGELA transition para poder medir todo lo demás—, los tres del anillo de foco —lo apaga con un blur a propósito—, trigger-bg —la demo monta el Indicator, y la regla que sube la etiqueta por encima de la píldora gana (0,2,0)— y scrollable-fade, que además pinta por mask-image, fuera del juego de propiedades que el guard lee.

Baseline

Referencia local: Soma + Morfo + Eidos. La capa visual de Eidos expone size / variant / color sobre el comportamiento que Soma ya implementa; el morfo declara parts, ARIA, keyboard y eventos sema. Las decisiones se alinean con las bibliotecas externas listadas en la Comparativa.

Comparativa

Capacidad Bits UI Ark UI React Aria shadcn-svelte UIX
Surface compound (root + parts) ✓ ✓ ✓ ✓ ✓
ARIA semantics + keyboard nav ✓ ✓ ✓ parcial ✓ via morfo
Variantes visuales (size / variant) parcial parcial n/a tailwind ✓ recipe
Form integration parcial parcial ✓ parcial ✓ via Field
Eventos sema declarativos n/a n/a n/a n/a ✓

Decisiones

  • El wrapper Eidos se mantiene fino: ergonomía visual + tokens. Comportamiento y ARIA viven en Soma + Morfo.
  • Strings públicos usan idlangref bajo components.{kebab}.*, con catálogo en src/uix/langs/components/{kebab}.ts.
  • Eventos sema declarados en el morfo cubren los cambios de estado que cargan peso perceptivo (commit, signal). Las navegaciones internas por teclado son focus moves, no eventos.
  • Cuando la API necesita comportamiento nuevo, va a Soma / Morfo primero; Eidos sólo expone la receta visual del resultado.

Gaps

Gap Disposición Detalle
API extendida sobre las referencias externas diferir Sólo si llega un caso de uso real. Mantener la superficie estable.
Cobertura adicional de variantes visuales diferir El recipe cubre sm/md/lg + solid/outline/ghost. Más variantes requieren caso concreto.
Documentación per-prop exhaustiva implementar Cuando se cierre el ciclo de remediación de cada componente.
Tests browser-level del flujo completo (Playwright) implementar Cobertura visual + interacciones. Se hace en una pasada conjunta de tests.

Powered by TurnKey Linux.