jixoai-ui
the terminal design language
loading the style sheet…
Skip to content
docs · print medium: screen

registry:ui · Display

code-card — the readonly code surface, on Shiki

A figure + pre/code base with a filename-tab head and a compact copy control, highlighted by Shiki through lib/shiki: grammars and themes are separate lazy chunks fetched exactly when a card first needs them (shiki/core + the JavaScript regex engine — no WASM), and the default jixoai theme is Shiki's own css-variables recipe bound to the --tok-* palette, so token paint rides the design tokens in both themes. Code is always a runtime prop — Shiki escapes it, so samples containing literal script-closing tags are inert data; the pre is the scrollport: horizontal always, vertical when maxHeight caps it.

install — code-card

$npx jixoai-ui add code-card

https://ui.jixoai.com/r/code-card.json

based on Shiki engine matrix · six installable backends lang="auto" · optional detection item on-demand grammars · themes zero-download jixoai theme scrollport pre · thin scrollbars

overview

Overview

A readonly code surface that owns its highlight pipeline: six installable backends, on-demand grammars, and a token palette that rides the design tokens.

CodeCard renders one figure — filename tab, header snippet, the scrollport pre, footer snippet, copy control — around a runtime code string. Highlighting is the ENGINE SEAM: a backend prop outranks the HIGHLIGHT_KEY context, which outranks the stock shiki default — six installable backends (shiki, prismjs, highlightJs, sugarHigh, treeSitter, microLighter) over the same contract. Grammars and themes are lazy chunks fetched the first time a card needs them; a page pays only for the engines it actually paints.

Unlike the inline-code chip's zero-markup range engine, shiki backends emit REAL spans into the pre — the trade is markup for print survival and grammar depth. Kinship, named precisely: inline-code shares the context KEY and the structural types (the same HIGHLIGHT_KEY seam) but ships the microlighter range engine as its stock — the two families never mount each other; the engine matrix is the shared surface.

The eight-axis surface is SEVEN lanes by law: the shiki theme literal owns the theme name (the terminal bezel twins' §13 precedent), and the universal theme lane is dropped at the source (never stamped, never broadcast) — the card's own dark adaptation answers to tree ancestry instead, through the family's declared .dark/.jx-light token re-declarations. Density is inert on this fixed-voice surface; the carriers stamp and broadcast to nothing. Per-axis below.

code-card

The complete card: filename tab (head left), header snippet (head right, replacing the default lang label), footer snippet (foot left), and the copy control (foot right). The Playground swaps the backend engine, the language and the theme — each first paint fetches exactly that engine's grammar/theme chunks (nothing of an engine joins the page until its card paints).

spawn.ts shiki · ts
import { UniPty } from '@unipty/core';
import { createNodePtyBackend } from '@unipty/backend-node-pty';

// readiness happens before Core construction
const backend = await createNodePtyBackend({ runtime: 'node' });
const unipty = new UniPty({ backend });

const pty = unipty.spawn(['bash'], {
  terminal: { cols: 80, rows: 24 },
});

pty.resize(120, 36); // Character-Cell Size
powered by Shiki · theme: jixoai
code-card-usage.svelte svelte
<script lang="ts">
  import CodeCard from '@ui/code-card.svelte';
</script>

<!-- the sample is a runtime prop: the engine escapes it, so a literal </script>
     inside it is inert data — nothing to escape at the template level -->
<CodeCard filename="spawn.ts" lang="ts" theme="jixoai" code={sample}>
  {#snippet header()}
    <span class="pill">shiki · ts</span>
  {/snippet}
  {#snippet footer()}
    <span>powered by Shiki</span>
  {/snippet}
</CodeCard>

scroll law

The pre is the single scrollport: long lines scroll horizontally (Tab characters stay tabs, never wrapped), maxHeight caps the body into vertical scrolling, scrollbars are thin currentColor lanes with overscroll containment, and the region is keyboard-focusable.

manifest.ts ts
// one rule: the <pre> is the scrollport — Tab stays Tab, long lines scroll
const manifest = {
  route:    'registry/files/ui/code-card.svelte',
  engine:   'shiki/core + JavaScript regex engine (no WASM)',
  langs:    'typescript tsx javascript jsx svelte html css scss json bash markdown yaml vue',
  themes:   'jixoai (zero-download, --tok-*) + github/vitesse/min families',
  fallback: 'prerendered plain text → upgraded after hydration, zero layout shift',
};
// ── a deliberately wide line to force the horizontal lane ────────────────────────────────────────
console.table(Object.entries(manifest).flatMap(([key, value]) => [{ key, value }]));
scroll-demo.ts ts
// one rule: the <pre> is the scrollport — Tab stays Tab, long lines scroll
const manifest = {
  route:    'registry/files/ui/code-card.svelte',
  engine:   'shiki/core + JavaScript regex engine (no WASM)',
  langs:    'typescript tsx javascript jsx svelte html css scss json bash markdown yaml vue',
  themes:   'jixoai (zero-download, --tok-*) + github/vitesse/min families',
  fallback: 'prerendered plain text → upgraded after hydration, zero layout shift',
};
// ── a deliberately wide line to force the horizontal lane ────────────────────────────────────────
console.table(Object.entries(manifest).flatMap(([key, value]) => [{ key, value }]));

law

Based on Shiki — a facade, not a wrapper

lib/shiki adds loading strategy only: a lazy singleton over shiki/core with the JavaScript regex engine, one dynamic import per grammar and theme, and a zero-download default theme from Shiki's css-variables factory. It never re-interprets Shiki output — getHighlighter() hands back the stock HighlighterCore and highlightCode() forwards Shiki's own codeToHtml options (transformers, dual themes, decorations) untouched, so the whole Shiki ecosystem works here as-is.

what the card owns

  • progressive paint: the prerendered sample is escaped plain text; after hydration Shiki upgrades the SAME <code> element — zero layout shift
  • on-demand loading: shiki/core + engine on first highlight; every grammar/theme its own lazy chunk, fetched only when requested
  • named themes ride along — the theme's editor colors from Shiki's pre output apply verbatim to the card's pre
  • scroll law: horizontal always, vertical under maxHeight, thin scrollbars, keyboard-focusable pre

what the consumer owes

  • a runtime string — never inlined markup between component tags
  • a Shiki language id for lang (aliases like ts/sh/md resolve in lib/shiki)
  • extra grammars/themes in one line: registerLanguage('python', () => import('shiki/langs/python.mjs'))
  • nothing else — npm shiki installs with the registry item

matrix

The engine matrix — one contract, six installable engines

shiki is the pinned default: installing code-card installs shiki and nothing else. Five more engines exist as their own registry items, each a factory returning the same HighlightBackend — markup backends write token spans into the card's code element (the paint survives the print pipeline's freeze clone), microlighter is the range model: zero markup, ranges registered in the CSS Custom Highlight API over the plain text (which is why it prints plain — see the table). Every engine is lazy: importing a factory pulls no engine code; the download happens at a card's first paint.

the six highlight engines compared
engineoutputsize posturelanguagestailoringprintin one line
shiki() default
@jixoai/highlight-shiki
markupshiki/core + the JavaScript regex engine at first paint (no WASM); every grammar and theme its own lazy chunk13 curated — typescript tsx javascript jsx svelte html css scss json bash markdown yaml vue, plus the alias tablelangs subset per instancespans survive the freeze clonethe default — TextMate accuracy, the zero-download jixoai theme
prismjs()
@jixoai/highlight-prismjs
markupcore + one lazy chunk per grammar; themes are global stylesheets — one active per documentthe curated set minus svelte/vue (prismjs 1.30 ships neither): markup css clike js ts jsx tsx json bash markdown yaml scsslangs subset per instancespans survive the freeze clonethe classic class-based workhorse
highlightJs()
@jixoai/highlight-highlightjs
markuplib/core — the zero-language kernel — plus exactly the grammars you register: unselected grammars never import or fetch (the runtime-size flagship; lazy chunks of the curated set still emit)typescript javascript xml css scss json bash markdown yaml; highlight.js 11 ships no tsx/jsx/svelte/vue module — those reject with a shiki hintlangs subset per instancespans survive the freeze clonecore + selective registration
sugarHigh()
@jixoai/highlight-sugar-high
markupone whole bundle — 9.90 KiB min / 4.35 KiB gzip for a TS scene, its README benchmark measured on 2.2.2 (same table: prism 14.63, hljs 29.54)29 canonical languages; no tsx (typescript covers it only as an input alias) — rejects with a shiki hintnone — the whole bundle IS the minimal form (the minimal-engine exemption)spans survive the freeze clonethe featherweight
treeSitter()
@jixoai/highlight-tree-sitter
markupthe wasm core runtime + one wasm per grammar, emitted from npm assets by your bundler (?url) at first paint — the heavyweighttypescript tsx javascript jsx only (jsx is the javascript grammar’s native dialect)langs subset · wasmBase / wasmLoader asset channelsspans survive the freeze clonereal syntax trees, query captures
microLighter()
@jixoai/highlight-microlighter
rangea ~2 kB engine core (its own size budget) + grammars + one theme sheet, all lazy — the code element keeps its plain text nodeits 37 bundled TextMate grammars (typescript tsx javascript vue html css json bash markdown yaml …)none — the range model ships no langs gate (engines without the capability are exempt)ranges do NOT survive the freeze clone — prints plain; pin a markup backend for paperthe range-model proof (CSS Custom Highlight API)

add an engine — one item per engine

registry install
# code-card ships ONE engine by default: shiki (via @jixoai/highlight-shiki)
npx jixoai-ui add @jixoai/highlight-shiki          # already aboard with code-card
npx jixoai-ui add @jixoai/highlight-prismjs        # + prismjs
npx jixoai-ui add @jixoai/highlight-highlightjs    # + highlight.js
npx jixoai-ui add @jixoai/highlight-sugar-high     # + sugar-high
npx jixoai-ui add @jixoai/highlight-tree-sitter    # + web-tree-sitter + grammar wasm
npx jixoai-ui add @jixoai/highlight-microlighter   # + microlighter

Each item lands its factory in $lib/highlight/<engine> and declares only its own npm dependencies — sibling engines never ride along. microlighter + vite: its grammar loading is runtime-templated inside the package and misses fail silently, so hosts owe two lines — dev excludes it from the optimizer, builds emit its dist/grammars/*.js next to the engine chunk (this site's vite.config.ts is the reference implementation). Breaking (2026-09-06): code-card used to bundle prismjs and microlighter as hard npm dependencies — it does not anymore, and nothing is shimmed. If you consumed those factories, add the matching item above; the $lib/highlight/<engine> import path keeps working for every engine you install, and engines you never install simply never download. The full migration table lives in the registry docs.

three configuration tiers

① per instance — the backend prop

Any consumer, any card: pass a factory product. The langs subset is the size lever — one instance's gate never narrows another's.

per-instance
<script lang="ts">
  import CodeCard from '@ui/code-card.svelte';
  import { highlightJs } from '@lib/highlight/highlight-js';
</script>

<!-- one prop, one instance: this card registers ts + bash grammars only -->
<CodeCard lang="ts" code={src} backend={highlightJs({ langs: ['ts', 'bash'] })} />

② subtree default — your ~10-line provider

The seam ships with the items (zero dependencies): HIGHLIGHT_KEY. Cards without a backend prop eat the nearest provider's default — the prop always wins.

subtree default
<script lang="ts">
  // highlight-default.svelte — any subtree root, ~10 lines, yours to own
  import { setContext } from 'svelte';
  import { HIGHLIGHT_KEY } from '$lib/highlight/context-key';
  import { prismjs } from '$lib/highlight/prismjs';

  // every card BELOW this root without a backend prop eats prism
  setContext(HIGHLIGHT_KEY, { backend: prismjs() });
</script>

<slot /> <!-- your subtree -->

③ kernel plugin — the site form

Sites that installed @jixoai/context-plugin can project the default through the plugin kernel — here repairing microlighter's one known limitation: under the print projection, swap the range backend for a markup one so the freeze clone carries real spans. The kernel never rides the registry items; this composition is app-side by law.

print-gated backend swap
// print-markup-backend.ts — the kernel-plugin form (the shape sites
// that installed @jixoai/context-plugin run; the kernel never rides
// the registry items themselves)
import { definePlugin } from '$lib/context-plugin.svelte';
import { isPrintProjection } from '$lib/medium.svelte';
import { HIGHLIGHT_DEF } from '$lib/highlight/context.svelte';
import { shiki } from '$lib/highlight/shiki';

// print survival: under the print projection, swap the range backend
// for a markup one — spans survive the freeze clone, ranges do not
export const printMarkupBackend = definePlugin({
  name: 'print-markup-backend',
  targets: [HIGHLIGHT_DEF],
  filter: (_def, env) => isPrintProjection(env.medium),
  before: (backend) => (backend.id === 'microlighter' ? shiki() : backend),
});

detection

lang="auto" — three detection rings, one optional item

Setting lang to the AUTO_LANG sentinel (strict equality — 'AUTO' and ' auto ' are ordinary language ids) runs detection before highlighting. The chain has exactly three rings: the langDetector prop, the HIGHLIGHT_DETECT_KEY context, and the backend's own detector — highlight.js instances carry one built in (highlightAuto over exactly the instance's languages). A ring resolving null is a no-opinion: the chain falls through (the rings complement, they never fight); a reject is terminal — plain text plus a warn naming the ring. Three no-opinion rings = plain text with the ids listed; zero rings at all = a runtime reject whose text carries the install command and both wiring forms below. Detection bytes load only when a card actually enters auto: a bare code-card install carries ZERO detector code, and the DLD ships as its own framework-free item whose four layers are each lazy modules — a layer that answers loads none of the layers beneath it.

two equivalent wirings — pick one

① the wrapper item — children form

npx jixoai-ui add @jixoai/highlight-detect-default pulls the DLD plus this ~10-line provider — import it from the folder barrel or the direct .svelte path. Svelte context spreads downward only: wrap the subtree, siblings stay untouched.

wrapper item
<script lang="ts">
  import CodeCard from '$lib/ui/code-card';
  import HighlightDetectDefault from '$lib/ui/highlight-detect-default';
</script>

<!-- form ①: the wrapper item — a ~10-line children provider whose body
     IS the one line of form ②. Svelte context only spreads downward:
     cards OUTSIDE this wrapper are untouched; nested wrappers, nearest
     wins; the langDetector prop always outranks whatever is wired here -->
<HighlightDetectDefault>
  <CodeCard filename="main.ts" lang="auto" code={sample} />
</HighlightDetectDefault>

② hand-written — zero components

The lib item is framework-free by law; one setContext line at any subtree root wires the same { detector } adapter shape the wrapper stores — the card's reader cannot tell them apart.

hand-written
<script lang="ts">
  // highlight-detect-root.svelte — any subtree root, zero components
  import { setContext } from 'svelte';
  import { HIGHLIGHT_DETECT_KEY } from '$lib/highlight/context-key';
  import { defaultLangDetector } from '$lib/highlight/default-detector';

  setContext(HIGHLIGHT_DETECT_KEY, { detector: defaultLangDetector() });
</script>

<slot /> <!-- your subtree: every lang="auto" card below eats the DLD -->
registry install
# detection is an OPTIONAL capability — a bare code-card install carries
# ZERO detector bytes; lang="auto" without a ring rejects at runtime
npx jixoai-ui add @jixoai/highlight-lang-detector   # the DLD lib: four-layer waterfall, framework-free
npx jixoai-ui add @jixoai/highlight-detect-default  # + the children wrapper (form ① convenience)

the DLD waterfall — cheap layers first, every layer its own lazy module

the default language detector's four layers
layerreadsanswers fromcost
L1 filenamefilenamethe extension table + the exact-basename table (Dockerfile, Makefile, tsconfig.json…): 'main.ts' → typescript, hit and donepure table parse
L2 shebangfirst linethe interpreter table + first-line modeline: '#!/usr/bin/env python3' → pythonpure table parse
L3 structurebody shapeMarkdown-guarded probes — whole-body JSON.parse, SVG/XML/HTML roots, YAML front-matter, TOML-before-INI sections; never a programming-language fingerprintpure TS probes
L4 statisticalbody statisticsbetlang wasm — 48 calibrated labels mapped through the canonical authority table; confident answers carry a 0..1 probability~98 KiB wasm, fetched on the first L1-L3 miss only

'Four layers' counts the waterfall only — the card's detection rings stay three plus the reject tail. The on-demand law cuts both ways: a filename hit loads L2-L4 zero bytes (pick auto in the playground — its filename answers at L1), and a bare install loads the whole capability zero bytes — the DLD is never a hidden dependency of code-card. A detection whose language the active engine's curated set rejects is terminal by the same matrix law as any lang: the reject names the engines that cover it.

live — the filename-less lanes (structure and statistics)

code-card · auto lanes

no filename, no shebang — the body's shape answers at L3

{
  "lane": "L3",
  "why": "no filename, no shebang — but the whole body parses as JSON",
  "result": { "lang": "json", "source": "structure" }
}

no filename, no shebang, no shape — the wasm answers at L4

set -euo pipefail
# no filename, no shebang, no structural shape — the wasm answers:
# betlang's calibrated top label is Shell, the authority table maps it
# to bash, and the card paints it with whatever engine is selected
npx jixoai-ui add @jixoai/highlight-lang-detector
code-card-auto-demo.svelte svelte
<script lang="ts">
  import CodeCard from '@ui/code-card.svelte';
  import HighlightDetectDefault from '@ui/highlight-detect-default';
  import { AUTO_LANG } from '@lib/highlight/lang-detector';
</script>

<!-- no filename, no shebang — the body's shape answers at L3 -->
<HighlightDetectDefault>
  <CodeCard lang={AUTO_LANG} code={structureSample} copyable={false} />
</HighlightDetectDefault>

<!-- no shape either — the wasm answers at L4 -->
<HighlightDetectDefault>
  <CodeCard lang={AUTO_LANG} code={statisticalSample} copyable={false} />
</HighlightDetectDefault>

Both cards hydrate plain and upgrade after the detector resolves — prerendered output is always plain text (detection never runs server-side). The wasm rides the @jixoai/ui-betlang-wasm npm package (betlang = 0.1.1 pinned at the crate, checksum-gated build): vite emits it as a real asset through the ?url channel, fetched the first time a sample falls through L1-L3.

the detection lab — type anything, watch the waterfall answer

The traced DLD reports one row per executed layer — what it consulted, what it answered, and how long it took; the layers below a hit render as skipped (the short-circuit law made visible). The card at the bottom paints through the real consumer path: lang="auto" inside the wrapper, its own waterfall run, never a pre-computed verdict.

Detection is debounced 250 ms and re-runs the whole waterfall — no cache (design D6); the card below rides the REAL consumer path (lang="auto" inside the wrapper), not a pre-computed verdict.

no opinion anywhere — the card stays plain text (the [detect:all] law)

waterfall log 0 executed
  1. L1 filename — no filename given — the table never consulted
set -euo pipefail
# no filename, no shebang, no structural shape — the wasm answers:
# betlang's calibrated top label is Shell, the authority table maps it
# to bash, and the card paints it with whatever engine is selected
npx jixoai-ui add @jixoai/highlight-lang-detector

types

Code card variants

Head and foot are compositional; fill turns the card into a pinned-chrome panel.

code-card · variants

bare pre

const bare = true;

filename tab + copy

hello.ts ts
export const hello = "world";

header/footer snippets

install.sh registry
npx jixoai-ui add code-card
terminal install
code-card-variants-demo.svelte svelte
<script lang="ts">
  import CodeCard from '@ui/code-card.svelte';
</script>

<CodeCard lang="ts" code={'const bare = true;'} copyable={false} />

<CodeCard filename="hello.ts" lang="ts" code={'export const hello = "world";'} />

<CodeCard filename="install.sh" lang="bash" code={'npx jixoai-ui add code-card'}>
  {#snippet header()}
    <span class="pill">registry</span>
  {/snippet}
  {#snippet footer()}
    <span class="text-[11px] text-muted-foreground">terminal install</span>
  {/snippet}
</CodeCard>

usage

Usage

Code is always a runtime prop — Shiki escapes it, so samples containing literal closing tags are inert data.

CodeCard usage
<script lang="ts">
  import CodeCard from '@ui/code-card.svelte';
</script>

<!-- the sample is a runtime prop: Shiki escapes it, so a literal </script>
     inside it is inert data — nothing to escape at the template level -->
<CodeCard filename="spawn.ts" lang="ts" theme="jixoai" code={source}>
  {#snippet header()}
    <span class="pill">node-pty route</span>
  {/snippet}
  {#snippet footer()}
    <span>powered by Shiki</span>
  {/snippet}
</CodeCard>

<!-- fill mode: the parent owes the height; the pre is the only scroller -->
<CodeCard lang="svelte" code={sample} fill minHeight="12rem" />

a11y

Accessibility

The pre is a labelled, keyboard-focusable scrollport; the copy control is a real button with state feedback.

Keyboard

KeyAction
TabReaches the scrollport (pre) and the copy control
← / → / ↑ / ↓Scroll the focused pre — long lines horizontal, capped bodies vertical
Enter / SpaceActivate the copy button

ARIA

AttributeValueDescription
aria-label"{filename|lang} code sample"On the pre — the scrollport is named whether or not a filename tab exists.
aria-labelcopy {filename|lang} sampleOn the copy button; flips to "copied" for the 1.6s feedback window.

theming

Density and tokens

Token paint end to end — the jixoai theme resolves to the --tok-* palette at paint time; the shell rides the --readonly-code-* tints.

xs
density.ts ts
export const density = "fixed rhythm";
sm
density.ts ts
export const density = "fixed rhythm";
default
density.ts ts
export const density = "fixed rhythm";
lg
density.ts ts
export const density = "fixed rhythm";
TokenDefaultSource
--tok-token-keywordvar(--primary)color
--tok-token-stringvar(--accent)color
--readonly-code-bgmuted 42% / backgroundcolor
--readonly-code-meta-bg / -fgaccent mixescolor
body rhythm13px mono, fixed paddingstructural
--jx-text11 / 12 / 13 / 15pxdensity

axes

Universal props

The eight-axis surface (explicit-props): size · shape · radius · density · color · theme · elevation · motion — each axis takes named steps, auto (inherit the ambient context; stamps nothing), an exact number (px · coefficient · dp · hue per axis), or query() for responsive/container-conditional values. SEVEN lanes — the shiki theme literal owns the theme name (the terminal bezel twins' precedent, §13 rules no rename; W6-dossier-flagged). The flat readonly surface carries no rung of its own.

PropertyTypeDefaultDescription
density 'small' | 'medium' | 'large' | 'auto' | number (+ legacy spellings)'auto'MEASURED INERT — the rung stamps data-density and the carriers broadcast, but this surface hosts no components and its own voices are fixed-scale: the 12.5px pre, the px paddings, the typed --jx-text-label head. A DensityDemo scope moves nothing (probe receipt). No tenant, no consumption — the quietest lane on the page.
size 'small' | 'medium' | 'large' | 'auto' | number'auto'THE §11 ECHO, NOTHING FOLLOWS — the stamp lands verbatim (--jx-size-effective: 18px; font-size: var(--jx-size-effective, 1rem) measured on the root) and the card's paint is px-anchored: the pre stays 12.5px, the head stays the typed label step. The heading-contrast case: a stamp with no em to scale. Number unit: px.
shape 'round' | 'scoop' | 'bevel' | 'notch' | 'square' | 'squircle' | 'auto''auto'SUPPLY-ONLY — stamps --jx-shape-effective/--jx-radius-factor-effective; the bezel corners are the family radius law, not the axis (grep receipt: zero shape reads). Number unit: none.
radius 'small' | 'medium' | 'large' | 'auto' | number'auto'SUPPLY-ONLY — stamps --jx-radius-effective; the shell corner is the family radius law (grep receipt: zero carrier reads). Number unit: px.
color 'primary' | 'secondary' | 'error' | 'warn' | 'success' | 'info' | 'auto' | number | string'auto'SUPPLY-ONLY — stamps --jx-color-effective; no family css reads it (grep receipt). Token hue rides the theme sheet (--primary/--accent/--success…); the copied state retunes through the jx-hue-success injection. Number unit: hue degrees.
theme 'light' | 'dark' | 'system' | 'auto''auto'DROPPED AT THE SOURCE (the §13 keep): stampCarriersForLanes receives theme: undefined and the lane is never broadcast — the shiki `theme` literal owns the theme name. What answers instead is ANCESTRY: the family declares its own .dark / .jx-light token re-declarations (the readonly tints + the tok palette dark formulas), so a dark TREE re-inks the card while the axis prop sits out (measured: a .dark wrapper flips the ground to the dark tint and re-derives the tok dark formulas; the card itself carries no .dark class). light/system/auto ride tree inheritance. No number lane.
elevation 'level-1' | 'level0' | 'level1' | 'level2' | 'level3' | 'level4' | 'level5' | 'auto' | number'auto'SUPPLY-ONLY — the card floats on the readonly tints; no shadow in the family css (grep receipt: zero box-shadow, zero carrier reads). Number unit: dp.
motion 'reduced' | 'subtle' | 'normal' | 'expressive' | 'auto' | number'auto'SUPPLY-ONLY ON THE AXIS — the carrier is unread (grep receipt). The family reads the motion KERNEL directly: the scroll-edge veils fade on var(--motion-150)/var(--motion-ease-out) and prefers-reduced-motion kills both the veils and the copy transition. Animation law: none (the card is static; the veils are scroll-state, not choreography). Number unit: coefficient.

Deviations, cited: the adoption is the census batch D row (explicit-props W3-D1 — openspec/changes/explicit-props/research/migration-census.md); the theme drop is the §13 keep (the shiki theme literal), W6-dossier-flagged. No query() seat: this surface hosts no components, so a responsive lane would re-base nothing — the density row's probe receipt is the demonstration.

CodeCard · universal props

const size = 18
// named steps resolve via the alias ladder
code-card-universal.svelte svelte
<CodeCard size={18} density="small">…</CodeCard>

api

API

Thirteen props; code is the only required one — everything else is composition.

Properties

PropertyTypeDefaultDescription
code * string—The sample (runtime prop; the backend escapes it into inert spans).
backend HighlightBackendcontext → shiki()Highlight backend instance — shiki() | prismjs() | highlightJs() | sugarHigh() | treeSitter() | microLighter(); see the engine matrix.
lang string'ts'Language id; aliases (ts/sh/md/…) resolve in the active backend's table — or 'auto' (the AUTO_LANG sentinel, strict equality) to run the three-ring detection chain first; see lang="auto".
langDetector LanguageDetector—Detection ring ①: an explicit detector outranking context and backend (defaultLangDetector() / betlangDetector() from the highlight-lang-detector item, or any { id, detect } implementation).
filename string''Filename tab on the head's left; head renders when it or header exists. With lang='auto' it feeds the DLD's L1 tables verbatim (paths included — the detector takes the last segment).
header Snippet—Head-right area; replaces the default lang label.
footer Snippet—Footer-left content.
copyable booleantrueCopy control on the footer bar's right.
maxHeight string''CSS length capping the body; turns on vertical scrolling.
fill booleanfalseStretch to the container height; the pre becomes the only scroll area.
minHeight string''Floors the card height; pairs with fill so short samples open readable.
class string''Forwarded to the figure.

Universal props

PropertyTypeDefaultDescription
size'small' | 'medium' | 'large' | 'auto' | number'auto' · ambient scopethe base scale — root font-size; parts size in em
shape'round' | 'scoop' | 'bevel' | 'notch' | 'square' | 'squircle' | 'auto''auto' · ambient scopecorner geometry (CSS corner-shape; §14 degrade table)
radius'small' | 'medium' | 'large' | 'auto' | number'auto' · ambient scopecorner size; auto = the concentric broadcast (§3)
density'small' | 'medium' | 'large' | 'auto' | number'auto' · ambient scopespacing/leading scale over the kernel channels (§4)
color'primary' | 'secondary' | 'error' | 'warn' | 'success' | 'info' | 'auto' | number | string'auto' · ambient scopethe hue axis of the fixed oklch primary system (§5)
theme'light' | 'dark' | 'system' | 'auto''auto' · ambient scopelight/dark profile; system = the JS-mutable global (§6)
elevation'level-1' | 'level0' | 'level1' | 'level2' | 'level3' | 'level4' | 'level5' | 'auto' | number'auto' · ambient scopeofficial M3 levels over the surface ladder (§7)
motion'reduced' | 'subtle' | 'normal' | 'expressive' | 'auto' | number'auto' · ambient scopeintensity across the motion kernels (§8)
jixoai-ui ui.jixoai.com the jixoai design language

Theme

Brand hue

0°

Auto cycle · 24h