Finishes the spin-field family. The 4 triggers + 2 scrubbers (number-field +
css-field) now spread renderProps() and add only soma-specific extras.
- Scrubbers: role + aria-hidden + data-spin-field-scrubber now morfo-sourced;
soma keeps data-scrubbing/disabled, cursor style, pointer handlers.
- Triggers: type + aria-label + data-spin-field + aria-disabled now morfo-
sourced. The trigger morfos' aria-disabled moves from literal-'true'+condition
to propRef('disabled') + ariaBoolean (the de-facto always-emit shape); each
trigger registers its own `disabled` source (includes atMax/atMin) so
renderProps resolves it. aria-label resolves from the morfo's
commonRef('buttons.increment/decrement') — the SAME idlangref the provider
used, so the string is unchanged ("Aumentar"/"Disminuir" in es).
- Dropped the now-orphaned NUMBER_FIELD_LANGS + boolToStr imports.
Verified in browser for all parts (type/aria-label/aria-disabled/role/aria-hidden
identical) + soma/morfo tests 95/95 (2 pre-existing palabras contract failures
only). The entire spin-field family is now morfo-sourced — zero re-declared attrs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mirrors the NumberField Input reference. CssField morfo's aria-required/disabled/
readonly/invalid gain `ariaBoolean`; the Input provider drops the hardcoded role +
data-spin-field-input + those four aria booleans — all now from renderProps().
Soma keeps the CSS-value-specific bits it genuinely owns: the parsed aria-valuenow,
soma-only aria-valuemin/max, aria-valuetext, native form attrs, handlers.
Verified in browser (role/aria/data from morfo, parsed aria-valuenow="16") +
soma/morfo tests 71/71. Both spin-field inputs are now fully morfo-sourced; the
triggers/scrubber + the other families remain on the backlog.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
NumberField and CssField are the same visual (a bordered field + input +
increment/decrement triggers + scrubber, split/stacked layouts, sizes/
variants/colors, themeable glyphs); only their value model differs. They
were two cloned recipes + CSS that drifted — a refinement to one (square
flush buttons, divider, contrast) didn't reach the other.
Unify into ONE shared source (the toggle-group structural-identity pattern):
- New eidos/components/spin-field: recipe key `spin-field` (`--spin-field-*`)
+ spin-field.css with all the stepper-field rules, selecting `[data-spin-
field*]`. Loaded via the foundation @import in index.css.
- number-field + css-field morfos declare structural identity (`data-spin-
field*` presence attrs on each part). The Provider emits them via syncAttrs;
the sub-parts emit them in their soma `props` getter (number-field's soma
hardcodes sub-part attrs rather than syncing the morfo).
- Removed the `number-field` / `css-field` recipe keys; their CSS files are
now stubs. A theme tints one component by scoping `[data-number-field] {
--spin-field-… }`.
- css-field thereby adopts number-field's refined steppers (square, flush,
divider) — the drift fix the user asked for, now structural (no clone).
Verified bit-for-bit in browser: number-field identical to baseline (split
flush, stacked symmetric xs..xl, RTL, glyph token/children override);
css-field now square/flush/divider. eidos-lint invalid 0; recipe contract
passes (no orphans, loads-once); check + morfo:check clean for these.
Docs: THEMING sections 33 (glyph tokens now `--spin-field-*`) + 34 (the
shared layer); number-field / css-field READMEs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>