5.9 KiB
Eidos Text
Universal inline-flow typography primitive. Aplica uno de los named
styles del foundation (body / prose / label / caption) y
permite sobrescribir per-axis (size / family / weight / color / align)
sin tocar el resto. Render por defecto <span> — composable dentro de
cualquier contenedor.
Superficie
<Text>Body copy.</Text>
<Text style="prose" size="lg">Longer reading passage.</Text>
<Text style="caption" italic>Image credit.</Text>
<Text truncate>Single-line label that may overflow…</Text>
<Text clamp={3}>Three-line clamped paragraph.</Text>
<Text as="p" align="center">Centered block paragraph.</Text>
Baseline
Origen: air/components/typography/text (rama morfo-runtime).
Adaptaciones para eidos:
- Sizes: air
1..12→ eidosxxs/xs/sm/md/lg/xl/xxl/xxxl. Sin escala separada — usamos el contrato existente--font-size-{key}/--font-line-height-{key}/--font-letter-spacing-{key}del foundation. - Families: air
'ui'|'prose'|'code'→ eidosprimary/secondary/mono/display. El foundation ya emite los aliases--font-ui/--font-prose/--font-codepero preferimos referencias directas a--font-family-{key}para claridad de origen. - Named styles: nuevo respecto a air. Cuando se pasa
style="body"(default),"prose","label"o"caption", el recipe consume los tokens--style-{name}-*que el foundation emite (familia + size + weight + line-height + letter-spacing + color, con overrides responsive cuando aplica). Los per-prop overrides ganan vía local--_text-{axis}declaradas inline por el componente. - Canvas measurement del air (clamp con conteo exacto de líneas vía
canvas) se simplifica a CSS
-webkit-line-clampen este port — ver Gaps.
Comparativa
| Capacidad | UIX Text | Radix Themes Text | Chakra Text | Mantine Text |
|---|---|---|---|---|
| Named style prop (body/prose/label/caption) | Sí (style) |
Sí (as + size) |
Sí (textStyle) |
Sí (size) |
| Size scale | xxs..xxxl (8 steps) | 1..9 | xs..6xl | xs..xxl |
| Family override | Sí (family) |
Sí | Sí (fontFamily) |
Sí (ff) |
| Weight override | Sí (weight) |
Sí | Sí (fontWeight) |
Sí (fw) |
| Color override | Sí (color → content-role slot) |
Sí (intent) | Sí (free) | Sí (free) |
| Align | Sí | Sí | Sí (textAlign) |
Sí (ta) |
| Italic shorthand | Sí (italic) |
No (style) | Sí (fontStyle) |
Sí (fs) |
| Underline shorthand | Sí (underline) |
Sí (underline) |
Sí (textDecoration) |
Sí (td) |
| Truncate (single-line ellipsis) | Sí (truncate) |
Sí (truncate) |
Sí (isTruncated) |
Sí (truncate) |
| Line-clamp (multi-line) | Sí (clamp={N}, CSS only) |
Sí (truncate + weight) |
Sí (noOfLines) |
Sí (lineClamp) |
| Canvas line-count measurement | No — gap | No | No | No |
Bindable lineCount output |
No — gap | No | No | No |
as prop polymorphism |
Sí | Sí | Sí | Sí |
| Responsive props | Sí (ResponsiveProp) |
Sí | Sí | Sí |
Decisiones
styleprop apunta a named foundation tokens — no recreamos los combos family+size+weight. Cuando cambias el design system, los Text constyle="body"actualizan sin tocar componentes.- Per-prop overrides vía local CSS vars
--_text-*— escritas inline en el span. El recipe usavar(--_text-x, var(--style-{name}-x))para cascade limpio. - Default
<span>, no<p>— Text es inline-flow primitive. Composable dentro de un<h1>,<button>,<label>, etc. Cuando necesitas block-level,as="p". Difiere de Mantine/Chakra que default a<p>; alinea con el principio "the dumbest element by default". colorsiempre desde el content-role slot —primary↔--color-content-primary. No aceptamos colores libres en este primitive para mantener el contrato de contraste y la coherencia con el theme.- Canvas measurement diferido — air tenía un sistema canvas para
contar líneas exactas + bindable output. Pesa y complica el SSR.
CSS
-webkit-line-clampcubre el 95% de los casos (clamp visual, no necesitas el conteo exacto si solo quieres truncar). tagStylesepara delstyleprop — elstyleHTML prop entra en conflicto semántico con nuestra propstyle(named style). El escape hatch inline está expuesto víatagStyle.
Eventos Sema
Text declara 0 eventos. Como Box/Flex/etc., es una primitiva pasiva. Componentes que animan/cambian estado en aparición componen Text dentro de un primitive interactivo (collapsible, dialog, toast) que posee los verbos sema relevantes.
Gaps
| Gap | Disposición | Detalle |
|---|---|---|
Canvas line-count measurement (text string prop + bindable lineCount) |
diferir | Pesa, complica SSR, y el 95% de casos se cubre con CSS line-clamp. Si llega un caso de uso (e.g. show "+N more lines" badge), añadir como mixin opt-in. |
| Hint visual cuando clamp recorta ("+N líneas más") | diferir | Requiere el canvas measurement. Sin él, no podemos saber si hay overflow real. |
Color libre (hex / CSS custom) en color prop |
descartar | Rompe contrato de contraste con theme. Usar tagStyle como escape hatch. |
| Variants tipográficas (small-caps, oldstyle figures, etc.) | diferir | Si emerge demanda, añadir feature flags. Bajo prioridad. |
| Text gradient | diferir | Composable con tagStyle o un componente <GradientText> dedicado. |
Referencias
- Radix Themes Text: https://www.radix-ui.com/themes/docs/components/text
- Chakra UI Text: https://chakra-ui.com/docs/components/text
- Mantine Text: https://mantine.dev/core/text/
- MUI Typography: https://mui.com/material-ui/react-typography/
Passive justification
Visual-only (scope: ['eidos']). Una sola part Provider, marker
[data-text]. Sin estados, sin keyboard, sin ARIA, sin eventos.
La recipe consume --style-{name}-* tokens del foundation +
--_text-{axis} overrides escritas inline.