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/label
dev ffa45726fd
feat(color)!: una palabra, un significado - primary/secondary son SIEMPRE jerarquia
2 months ago
..
README.md feat(color)!: una palabra, un significado - primary/secondary son SIEMPRE jerarquia 2 months ago
index.ts feat(label): standalone Label primitive (ported from terra/label) 3 months ago
label.css feat(color)!: una palabra, un significado - primary/secondary son SIEMPRE jerarquia 2 months ago
label.svelte feat(color)!: una palabra, un significado - primary/secondary son SIEMPRE jerarquia 2 months ago
types.ts feat(color)!: una palabra, un significado - primary/secondary son SIEMPRE jerarquia 2 months ago

README.md

Label

Standalone accessible label primitive — a native <label> you can associate with any control by id. Ported from the legacy terra/label (which mirrored Radix Label) into the current eidos-native leaf shape.

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

<Label for="email">Email address</Label>
<Label size="lg" weight="semibold" for="title">Title</Label>
<input id="email" type="email" />

Carries the foundation label typography style (--style-label-*: UI family, sm size, medium weight, content-primary), overridable per-axis via size / weight / color. Its only behaviour is a mousedown guard that stops a double / triple click from selecting the label text (the Radix convention); a single click still labels + focuses the control.

Baseline

No Air baseline. Ported from morfo-runtime:src/uix/terra/label — a LabelProviderState that rendered <label>, passed for through, stamped data-label, and carried the multi-click select guard. The port drops terra's provider-state layer: in the current architecture a <label> is an eidos-native leaf (native element, no ARIA widget, no composition, no complex behaviour), and the visual axes follow the Text typography primitive (--style-{name}-* base + per-instance --_{comp}-* overrides). The select-guard is DOM hygiene, so it lives inline in the eidos wrapper.

Comparativa

Feature Radix Bits UI React Aria Ark UI / MUI UIX
Standalone label primitive ✅ Label.Root ✅ Label.Root ✅ <Label> ❌ field-scoped only ✅ <Label>
size / weight / color axes ❌ unstyled ❌ ❌ ⚠️ ✅ Text mechanism
Multi-click text-select guard ✅ onMouseDown ✅ (from Radix) ❌ ❌ ✅ inline handler
Field-scoped auto-wired label ⚠️ separate ⚠️ ✅ context ✅ ✅ Field.Label
Floating label ⚠️ CSS ⚠️ ✅ ✅ variant ⏳ Field concern (deferred)

Radix and Bits ship a standalone Label; Ark UI / MUI only expose a Field-scoped label. UIX ships both and they are complementary: <Label for="…"> for a control outside a Field, <Field.Label> inside one (it auto-wires for=inputId and reflects the field's invalid / disabled state).

Decisiones

  • Eidos-native leaf (scope: ['eidos'], no soma, no sema). A <label> is native HTML with no ARIA widget pattern, no part composition and no complex behaviour — it fails all three soma membership criteria. The morfo is the contract (one Provider part → data-label); the eidos wrapper stamps it and renders the <label> directly.
  • Follows the Text typography mechanism, not Link. Visual props (size/weight/color) resolve through ActiveEidos.resolve() into inline --_label-* variables over the foundation --style-label-* base — identical to how <Text style="label"> works. No per-size recipe tokens (Text/Label register no base.ts recipe). This is why the standalone Label exposes real, selectable visual axes rather than being a prop-less shell.
  • The select guard stays inline in the eidos wrapper. It is stateless, non-semantic DOM hygiene — mounting a soma provider for one handler would violate Simplicity First. The wrapper composes the consumer's onmousedown (if any) after its own guard, so nothing is clobbered.
  • Label vs Field.Label. Kept as two components (as terra did): Label is context-free with a manual for; Field.Label auto-wires through the field context. Neither replaces the other. Note the weights differ by design — standalone Label uses the foundation label weight (medium); Field.Label overrides to regular for form-field density. Pass weight="regular" to match.

Talla y tema

Guard R-5.4 (npm run theming:sentinel -- label <url>): 1/2 en vivo; el otro está adjudicado con su medición en scripts/theming-sentinel-exceptions.ts. Corrido 2026-08-22.

Contrato en lib/recipes/base.ts > label (2 claves, fusionadas con el forward de paleta). Alcance del censo: 100 % (era 0 %).

Seis de sus ocho knobs son SISTEMA y no se acuñan. label es uno de los seis primitivos tipográficos: sus seis ejes consumen --style-label-* a través de la escotilla por instancia (var(--_label-{eje}, var(--style-label-{eje}))), que es la forma que D-TH.2-b fijó y la que hace que un <Label> y un <Text style="label"> se lean idénticos. La capa los posee.

Quedan dos knobs propios, los que el primitivo añade por su cuenta: el gap al icono o indicador que puede acompañar al texto, y disabled-fg, la tinta cuando el consumidor marca la etiqueta como deshabilitada junto a su control. --_label-color sigue privado: es el conmutador de dos fuentes (eje de tinta en línea / forward de paleta cuando llega data-color), el mismo patrón que en code, textarea, spinner y skeleton.

Gaps

Capability Disposition Notes
Floating label (float) diferir A floating label needs the control's focused / filled state, which a context-free <Label> cannot observe. It belongs to Field as a labelPlacement="floating" mode (CSS :focus-within + :placeholder-shown), reusing Field.Label. Deferred to that work — not a prop on standalone Label.
align / truncate / italic-underline diferir The Text primitive already covers rich typography; add to Label only on a real request. Implementar if a label needs them.
invalid state token diferir Field.Label reflects field-invalid via context; a standalone label has no field, so data-disabled is enough for now.
Soma provider for the select guard descartar Over-engineering for one stateless handler (see Decisiones).

Passive justification

Label declares 0 semantic events — it is a passive display primitive. A label neither commits, emerges, nor transitions; the perceptual events belong to the control it labels (which carries its own sema), not to the label. Same justification as separator.ts / link.ts. scope therefore excludes sema.

Anatomy

Part Element Notes
Label (Provider) <label data-label> Native label; for associates it with a control by id.

Props: size (xs–xl), weight (regular/medium/semibold), color (subtle/muted/disabled/on-solid — the content-ink axis — plus any role / intent / donor scale / raw CSS colour) — all ResponsiveProp — plus every HTMLLabelAttribute (for, id, class, aria-*, event handlers). Set data-disabled when the associated control is disabled for the muted treatment.

Accessibility

  • Native <label> — full built-in label semantics, no ARIA needed.
  • for="{id}" ties the label to a control; clicking it focuses / toggles the control.
  • The multi-click mousedown guard prevents accidental text selection while keeping single-click activation.
  • Inside a Field, prefer Field.Label — it wires for automatically and reflects invalid / disabled field state.

Powered by TurnKey Linux.