Jixoai UI v0.3: richer document expression, better press texture
Figures, tables, equations, and listings number themselves and can be cited anywhere in the text; reorder sections and the numbers and anchors keep working. @jixoai/vite-plugin 0.2.0 ships alongside, wiring terminal components and the icon system into Vite builds. The registry carries 113 items. One breaking change.
이 글은 영어로 작성되었습니다. 중국어 버전 읽기 →
$ git log v0.2.0..v0.3.0 --oneline | wc -l
787
jixoai-ui 0.3.0 is out (2026-09-05). From this release on, figures, tables, equations, and listings in a document number themselves, and the running text can cite them anywhere; reorder sections and the numbers renumber while link anchors keep working. Press texture, scrolling, and density each got a unification round. The registry carries 113 items, and @jixoai/vite-plugin 0.2.0 ships alongside. The window contains one breaking change; see the migration section.
Figures, tables, and equations number themselves
Numbered citation was the unfinished business the legacy numbering mechanisms left behind; reference-book and textbook pages could not be written. This release closes that gap.
Section numbering domains: a
numberingdeclaration makes a section the root of a numbering subtree, with decimal numbers generated level by level (3 → 3.2 → 3.2.1); it is also the counting domain for floats. Sections outside any domain stay byte-identical.The Figure family: counts inside its domain by
kind(figure, table, equation, listing). The wrapper component carries the number, anchor, and caption, with the code block nesting in the content slot; acitedInslot marks manual back-references.The Reference family: how a citation renders is decided by its target. A numbered float renders as
Eq (4.5), a numbered section as§ 3.2.1, an unnumbered target as its own title. A missing id falls back to a visible marker plus a console.warn and never blocks rendering.
Real usage from the 0.3.0 docs page (number and caption are automatic):
<NumberingProvider>
<Section numbering="decimal" title="Results">
<Figure kind="equation" id="eq-1" caption="the momentum balance">
<CodeCard lang="ts">p = m·v</CodeCard>
</Figure>
<p>see <Reference to="eq-1" /></p>
</Section>
</NumberingProvider>
Numbering and reference data also enter the harvest contract, the agreement that collects structural data from the rendered DOM into the static corpus. A two-pass pre-scan on the harvest side first indexes every referenceable target in the document, then maps data-ref-to into the corpus; forward references keep their pointing relation in the SSR fallback state. The figure's number, the citing block's refids[], and the section's number are all contract members, so search, llms.txt, and print tables of contents get more accurate as structure lands.
Design background: the document structure ontology
The design track started from one question (the Owner's words): "If you were a creator, what structured expression would you need?" A lexicographer wants headword, part of speech, and citation; a composer wants movement, bar, and rehearsal mark; web documents used to hand them headings and code blocks and nothing else. The answer is a three-layer ontology: CodeBlock as the atom of expression, SectionCard carrying seven structural primitives (section / entry / sequence / float / note / reference / break), and PrintDoc as the genre preset for a whole document. The numbering and reference work in this release belong to the float and reference primitives. The proposals are linked in the design archive row at the end.
Reorder sections and the numbers follow
Numbers follow DOM order; they are display currency. Reorder and they renumber, while the id never moves: sections that trade places update their numbers on their own, link anchors keep working, the print pipeline captures the numbers already in the DOM without special handling, and page numbers stay layout facts, never pre-harvested. CSS counters and PagedRef, the two legacy numbering mechanisms, retire; the replacement is the numbering declaration and the Reference component from the previous section.
Vite builds plug straight in
Vite projects can now wire jixoai-ui's terminal components and icon system into their build. @jixoai/vite-plugin 0.2.0 ships with this release: the pinned ghostty-vt wasm runs the resolve → serve → emit pipeline and hands the asset URL to the page via the virtual:jixoai-ghostty module; the icon system carries svg, lucide, and font providers; jixoai-ghostty-probe is the ABI sentinel bin. Its earlier install problems are healed by the ghostty pin resolver and the lucide lock sync (release commit 125e31f1).
Other changes
Press texture becomes a library-wide rule: buttons gain raised / flat texture zones; flat rests shadowless and shows the engrave inner shadow on press. icon-button joins the axis, and the foot zones of Card and Dialog hand their buttons flat by default.
Scrolling unified under one law set: the new registry item
@jixoai/scroll-rungives every scrollable region the same law set, with tabs and button-group as its consumers; the five effects slide, blur, blurSlide, progressBlur, and shadow come from the same source, and RTL is normalized across three engines (aeb747f2).The 2xs density rung: the fifth density, for pro-tool operation surfaces. Text lands at 10px (9px stays unshipped as the absolute floor), the 24px minimum row height sits at the WCAG 2.5.8 AA floor, and the hit floor is redeclared inside the rung per the non-touch-pointer stance (c8749f86).
Print determinism: print output no longer depends on the viewport.
The three defaults-economy changes and the single paint key landed; control-chrome lets in-row control shells choose between dissolving and self-sustaining.
CI repairs for the ghostty version pin and the lock chain.
Repo-wide test suite at 2185/2185 (604f9e01).
Commit type stats (strict conventional prefixes, grep -cE '^(type)(\(|!|:)'): feat 270 / fix 262 / docs 146 / test 16 / chore 46 / refactor 28 / style 3; the remaining 16 are tune, spec, merge, and unprefixed commits, totaling 787.
Migration (breaking: hook classes become attributes)
Breaking changes, counted: zero commits in the window carry the ! marker; the single breaking change is the hook migration of 2026-08-25, recorded in the README as a breaking markup-contract change. What changed: the css-less .jx-* hook classes are fully retired, semantic anchors become data-jx-* attributes, and no compatibility classes are kept. Query migration:
document.querySelector('[data-jx-kbd]')
'[data-jx-badge="tonal"]'
el.setAttribute('data-jx-foo', '')
el.hasAttribute('data-jx-foo')
Variant families collapse into one valued attribute: data-jx-badge={variant}, where the ladder fill | tonal | outline carries structural values only and no semantic hue names; error status = variant="tonal" + jx-hue-error injection. The lowest-friction path is re-adding the item, then migrating queries per the table above.
npx shadcn add @jixoai/<item>
Acknowledgements
The README's own words: everything here graduated from production work on unipty and openspecui.
Links
Changelog: GitHub Release v0.3.0 · compare v0.2.0...v0.3.0
Docs & registry: ui.jixoai.com · README (v0.3.0)
Upgrade: see the Migration section above
Discussion: GitHub Issues
Design archive: document-ontology design track · float + reference R2
Chinese version: /zh/blog/2026-09-06-ui-0-3-0/
