registry:ui · Data Display
blockquote — the quote, on the banner's ladder
The reading-content quote and admonition surface: the native <blockquote> on the alert-shaped two-rung ladder — outline, the classic left-rule quote; tonal, the alert recipe verbatim — with label, icon and cite composing over either rung.
$npx jixoai-ui add blockquote
https://ui.jixoai.com/r/blockquote.json
overview
Overview
One native element, two frozen postures, one rule channel — composed over by label, icon and cite.
Blockquote is the reading-content quote and admonition surface. The root is the native <blockquote> element — quoted-prose semantics come from the platform,
and cite renders the MDN attribution posture (footer > cite after the body), never an element swap.
One surface, two postures, on the alert-shaped two-rung ladder: outline (the default) is
the classic left-rule quote — transparent ground, an inset rule, a 0.875em muted body;
tonal is the alert recipe verbatim (12% tinted ground, 45% border, rounded box), the
callout posture. Availability is frozen at these two rungs: fill buries long-form copy,
and ghost is interactive-chrome vocabulary a static quote misuses. Hue rides the jx-hue-* class injection — never a variant name; the markdown map's GitHub
alerts land here as tonal + label + hue.
The left rule is its own channel: rule (shadow | border) × ruleSize (1 | 4 | 8 px) — the inset standard made a prop, paddings fixed
across sizes (paint never moves geometry). label renders the alert
title-row form, icon composes inline-start of it, and the body rides
0.875em of the ambient scale. The eight universal axes resolve on the same root — the
grammar (named steps, auto, numbers, query()) is documented once on the universal props page.
usage
Usage
Import the component, choose the posture by prominence — outline for the plain quote, tonal for the admonition — and compose label, icon and cite over either rung.
<script lang="ts">
import Blockquote from '@ui/blockquote';
</script>
<div class={cx(rt.col16, rt.wFull, rt.maxWXl)}>
<div class={cx(rt.bqGrid640a)}>
<Blockquote>
outline (own) — transparent ground, a soft 4px left rule at a lightened mix, 0.875em muted body: the classic quote.
</Blockquote>
<Blockquote variant="tonal">
tonal — the alert recipe verbatim: 12% tinted ground, 45% border, rounded box.
</Blockquote>
</div>
<div class={cx(rt.bqGrid640a)}>
<Blockquote variant="tonal" class="jx-hue-info" label="Note">
The streaming prefix never remounts while chunks arrive.
</Blockquote>
<Blockquote variant="tonal" class="jx-hue-warning" label="Warning">
The migration rewrites column names in place.
</Blockquote>
</div>
<Blockquote label="Edsger W. Dijkstra" cite="EWD 648, 1978">
The purpose of abstracting is not to be vague, but to create a new semantic level in
which one can be absolutely precise.
</Blockquote>
</div>blockquote
The two frozen rungs side by side, the hue injections the admonition posture rides, and the label + cite composition. outline keeps the muted body (the manuscript posture); tonal tints both label and body like the alert rows.
outline (own) — transparent ground, a soft 4px left rule at a lightened mix, 0.875em muted body: the classic quote.
tonal — the alert recipe verbatim: 12% tinted ground, 45% border, rounded box.
Note
The streaming prefix never remounts while chunks arrive.
Warning
The migration rewrites column names in place.
Edsger W. Dijkstra
The purpose of abstracting is not to be vague, but to create a new semantic level in which one can be absolutely precise.
<script lang="ts">
import Blockquote from '@ui/blockquote';
</script>
<div class={cx(rt.col16, rt.wFull, rt.maxWXl)}>
<div class={cx(rt.bqGrid640a)}>
<Blockquote>
outline (own) — transparent ground, a soft 4px left rule at a lightened mix, 0.875em muted body: the classic quote.
</Blockquote>
<Blockquote variant="tonal">
tonal — the alert recipe verbatim: 12% tinted ground, 45% border, rounded box.
</Blockquote>
</div>
<div class={cx(rt.bqGrid640a)}>
<Blockquote variant="tonal" class="jx-hue-info" label="Note">
The streaming prefix never remounts while chunks arrive.
</Blockquote>
<Blockquote variant="tonal" class="jx-hue-warning" label="Warning">
The migration rewrites column names in place.
</Blockquote>
</div>
<Blockquote label="Edsger W. Dijkstra" cite="EWD 648, 1978">
The purpose of abstracting is not to be vague, but to create a new semantic level in
which one can be absolutely precise.
</Blockquote>
</div>blockquote
The rule channel — shadow (own) × border, each at the literal 1|4|8 px ladder. The rule's color rides the rung's OWN border-color declaration (one hue source: a jx-hue-* retune moves ground, box and rule together); ONE shadow utility per root; outline in shadow mode emits no border at all; the paddings stay FIXED across channels and sizes — border consumes geometry, shadow doesn't (paint never moves geometry).
shadow-1 — the hairline: a 1px inset rule painted over geometry.
shadow-4 — the emphasis quote, pad fixed at 14px (calc(var(--jx-unit) * 3.5)).
shadow-8 — the pull quote; ps stays fixed, the paint widens.
border-1 — the classic geometry-consuming rule.
border-4 — consumes 3px more of the box.
border-8 — the widest structural edge.
shadow-1: the hairline — fits xs2-scale contexts only.
shadow-4: the default manuscript bar every quote now ships.
tonal + shadow-1: a deliberate near-no-op — axis uniformity over special-casing.
tonal + shadow-4: the rule starts to read through the tint.
tonal + shadow-8: two edges, one hue source.
<script lang="ts">
import Blockquote from '@ui/blockquote';
</script>
<div class={cx(rt.col24, rt.wFull, rt.maxW3xl)}>
<div class={cx(rt.col12)}>
<span class={cx(rt.note11)}>outline — shadow (own) × border, 1 | 4 | 8</span>
<div class={cx(rt.bqGrid640b)}>
<Blockquote rule="shadow" ruleSize={1}>shadow-1 — the hairline: a 1px inset rule painted over geometry.</Blockquote>
<Blockquote rule="shadow" ruleSize={4}>shadow-4 — the emphasis quote, pad fixed at 14px (calc(var(--jx-unit) * 3.5)).</Blockquote>
<Blockquote rule="shadow" ruleSize={8}>shadow-8 — the pull quote; ps stays fixed, the paint widens.</Blockquote>
<Blockquote rule="border" ruleSize={1}>border-1 — the classic geometry-consuming rule.</Blockquote>
<Blockquote rule="border" ruleSize={4}>border-4 — consumes 3px more of the box.</Blockquote>
<Blockquote rule="border" ruleSize={8}>border-8 — the widest structural edge.</Blockquote>
</div>
</div>
<div class={cx(rt.col12)}>
<span class={cx(rt.note11)}>the resolved default — 4 won the browser review; 1 stays the xs2-scale hairline</span>
<div class={cx(rt.bqGrid640a)}>
<Blockquote rule="shadow" ruleSize={1}>shadow-1: the hairline — fits xs2-scale contexts only.</Blockquote>
<Blockquote rule="shadow" ruleSize={4}>shadow-4: the default manuscript bar every quote now ships.</Blockquote>
</div>
</div>
<div class={cx(rt.col12)}>
<span class={cx(rt.note11)}>tonal — the box border stays; the shadow rule rides beside it</span>
<div class={cx(rt.bqGrid640b)}>
<Blockquote variant="tonal" rule="shadow" ruleSize={1}>tonal + shadow-1: a deliberate near-no-op — axis uniformity over special-casing.</Blockquote>
<Blockquote variant="tonal" rule="shadow" ruleSize={4}>tonal + shadow-4: the rule starts to read through the tint.</Blockquote>
<Blockquote variant="tonal" rule="shadow" ruleSize={8}>tonal + shadow-8: two edges, one hue source.</Blockquote>
</div>
</div>
</div>demo
The icon lane — bring your own glyph
icon is a snippet rendered inline-start of the label, exactly the alert precedent: the component ships no glyph vocabulary, so lucide marks, inline svgs and plain text all land the same way. The label row is the surface's one fixed chrome size (0.8125rem nav caps); the body inherits the ambient scale. The drawer carries the runnable source.
blockquote · icon lane
Warning
The migration rewrites column names in place — snapshot before upgrading.
<script lang="ts">
import Blockquote from '@ui/blockquote';
</script>
<div class={cx(rt.maxWXl)}>
{#snippet warningGlyph()}<span class={cx(rt.fontMono)} aria-hidden="true">▲</span>{/snippet}
<Blockquote variant="tonal" class="jx-hue-warning" label="Warning" icon={warningGlyph}>
The migration rewrites column names in place — snapshot before upgrading.
</Blockquote>
</div>api
API
The table renders from the GENERATED meta; the eight universal axis rows split into the shared section beneath the family rows. ruleSize stays outside the eight — migration-census.md's §13 keep row (no collision with the universal size axis).
Properties
| Property | Type | Default | Description |
|---|---|---|---|
| variant | 'outline' | 'tonal' | 'outline' · ambient zone | Ladder prominence: outline paints the transparent ground with the left rule and the muted 0.875em body; tonal paints the alert recipe verbatim (12% tinted ground, 45% border, rounded box). Hue rides the jx-hue-* class injection, never the variant name. Omitted → the ambient paint zone, else the frozen own outline. Availability is frozen at these two rungs — fill buries long-form copy and ghost is interactive-chrome vocabulary a static quote misuses. |
| rule | 'shadow' | 'border' | 'shadow' · Own default, not ambient | The left rule's ink channel: shadow paints over geometry (the inset standard — command-item's inset primary, the elevation grammar's WELL tier, kbd's engrave lineage); border consumes it. Outline in shadow mode emits no border at all; tonal keeps its box border plus the shadow rule. A literal slot the ambient zone never moves. |
| ruleSize | 1 | 4 | 8 | 4 · Own default, not ambient | The rule's literal px ladder — the Owner's explicit enumeration, recorded as the ruling over a derived scale. Paddings stay fixed across sizes: paint never moves geometry. Kept outside the eight axes per migration-census.md's §13 row (no collision with the universal size axis). |
| label | string | — | One-line uppercase heading in the alert title-row form — the surface's one fixed chrome size (0.8125rem). Omitted renders a bare body block. |
| icon | Snippet | — | Snippet rendered inline-start of the label — bring your own glyph (lucide, svg, text); the component ships no glyph vocabulary. |
| cite | string | — | Attribution rendered as <footer><cite> after the body — the MDN posture. Not the native cite attribute, and never an element swap: the root stays <blockquote>. |
| children | Snippet | — | Body copy, rendered as direct children of the native blockquote (no wrapper). At auto the body rides 0.875em of the ambient scale; an explicit size REPLACES that em voice — the root renders the stamped size verbatim and the body copy follows it. |
| class | string | '' | Forwarded to the root blockquote. The jx-hue-* intent utilities land here — the tonal rung consumes their --jx-tonal / --jx-outline seams, and the rule channel rides the same single hue source. |
Universal props
| Property | Type | Default | Description |
|---|---|---|---|
| size | 'small' | 'medium' | 'large' | 'auto' | number | 'auto' · ambient scope | the base scale — root font-size; parts size in em |
| shape | 'round' | 'scoop' | 'bevel' | 'notch' | 'square' | 'squircle' | 'auto' | 'auto' · ambient scope | corner geometry (CSS corner-shape; §14 degrade table) |
| radius | 'small' | 'medium' | 'large' | 'auto' | number | 'auto' · ambient scope | corner size; auto = the concentric broadcast (§3) |
| density | 'small' | 'medium' | 'large' | 'auto' | number | 'auto' · ambient scope | spacing/leading scale over the kernel channels (§4) |
| color | 'primary' | 'secondary' | 'error' | 'warn' | 'success' | 'info' | 'auto' | number | string | 'auto' · ambient scope | the hue axis of the fixed oklch primary system (§5) |
| theme | 'light' | 'dark' | 'system' | 'auto' | 'auto' · ambient scope | light/dark profile; system = the JS-mutable global (§6) |
| elevation | 'level-1' | 'level0' | 'level1' | 'level2' | 'level3' | 'level4' | 'level5' | 'auto' | number | 'auto' · ambient scope | official M3 levels over the surface ladder (§7) |
| motion | 'reduced' | 'subtle' | 'normal' | 'expressive' | 'auto' | number | 'auto' · ambient scope | intensity across the motion kernels (§8) |
axes
The eight axes on this component
What each axis drives HERE — the carrier names are the family's real vars (blockquote.stylex.ts, blockquote.css), steps and units per universal-props.schema.ts, every axis defaulting auto. Two axes are consumed on the quote itself (size, theme); density is scope-only — its rung re-bases the kernel channels for content composed into the body while the quote's own paint stays fixed; five are supply-only — they stamp their carriers for descendants and no blockquote css reads them, recorded per axis instead of silently omitted. ruleSize is the family's own literal axis and stays outside the eight (the census keep row).
| Property | Type | Default | Description |
|---|---|---|---|
| size | 'small' | 'medium' | 'large' | 'auto' | number | 'auto' | CONSUMED — an explicit size REPLACES the em voice: the kernel stamps --jx-size-effective and font-size on the root inline, and the quote renders the stamped size verbatim (14 → 14px; large → var(--jx-size-large) = 18px). The 0.875em body voice (blockquote.css) is the auto-only ambient rescale — it never rides on top of an explicit size. The label/cite chrome rows stay fixed at var(--jx-text-base) (rem-anchored). Number unit: px. |
| density | 'small' | 'medium' | 'large' | 'xs' | '2xs' | 'sm' | 'default' | 'lg' | 'auto' | number | 'auto' | SCOPE — stamps --jx-density-coefficient and the data-density rung attribute on the root; the kernel's [data-density] scope blocks then re-declare the density channels (--jx-text, --jx-gap, --jx-stack, --jx-hit …) at the quote root, so kernel-bearing content composed into the body follows the rung. A bare number stamps the coefficient only — no rung attribute, no scope block matches, nothing recomposes (the declaring-element law). No blockquote css reads any channel: the quote's own paint is fixed — paddings ride --jx-unit and --jx-space-12, the label row's gap --jx-space-8. small/medium/large alias sm/default/lg; the five legacy spellings stay addressable. Number unit: coefficient. |
| theme | 'light' | 'dark' | 'system' | 'auto' | 'auto' | CONSUMED — dark stamps the .dark class bridge on the root and the island's vars re-resolve the dark profile; light and system ride tree inheritance. No number lane. |
| radius | 'small' | 'medium' | 'large' | 'auto' | number | 'auto' | SUPPLY ONLY — stamps --jx-radius-effective for descendants. The quote's one corner surface, the tonal box, keeps the theme radius var(--radius) (blockquote.stylex.ts tonalGround); a per-instance corner size does not repaint it. Documented absence. Number unit: px. |
| shape | 'round' | 'scoop' | 'bevel' | 'notch' | 'square' | 'squircle' | 'auto' | 'auto' | SUPPLY ONLY — stamps --jx-shape-effective and --jx-radius-factor-effective; no blockquote css reads them — a quote paints no corner-shape (the degrade table lives on the universal props page). Documented absence. No number lane. |
| color | 'primary' | 'secondary' | 'error' | 'warn' | 'success' | 'info' | 'auto' | number | string | 'auto' | SUPPLY ONLY — stamps --jx-color-effective; nothing in the family reads it. Hue here rides the jx-hue-* scope classes, which inject --jx-tonal and --jx-outline — the single hue source the tonal ground, the inks and the rule channel consume. Number unit: hue degrees; raw strings pass through (closed at build). |
| elevation | 'level-1' | 'level0' | 'level1' | 'level2' | 'level3' | 'level4' | 'level5' | 'auto' | number | 'auto' | SUPPLY ONLY — stamps --jx-elevation-effective (level-1 = −1dp … level5 = 12dp); a static quote paints no shadow ladder — the only shadow is the rule channel's inset. Documented absence. Number unit: dp. |
| motion | 'reduced' | 'subtle' | 'normal' | 'expressive' | 'auto' | number | 'auto' | SUPPLY ONLY — stamps --jx-motion-effective; reading content carries no motion kernels. Documented absence. Number unit: coefficient. |
Blockquote · the consumed lanes, live
The lanes the quote itself paints: a px number and a named step on the size axis (the root renders the stamped size verbatim — an explicit size REPLACES the 0.875em em voice, which applies only at auto), the theme dark island, and one real query() case — the base 14px below the 48rem viewport, 16px at md and wider (resize the window). The supply-only axes stamp nothing visible on the quote; the table above records each absence.
size 14
A px number sets the root font-size verbatim — the body renders 14px, not 0.875 × 14; the em voice is auto-only.
size large
The named step resolves var(--jx-size-large) and the root renders it verbatim — 18px, no em rescale on top.
theme dark
The .dark class bridge re-resolves the island's vars — ground, border and rule inks follow the dark profile.
responsive
Base 14px below the 48rem viewport, 16px at md and wider — the stamped size lands verbatim at each rung (resize the window).
<script lang="ts">
import Blockquote from '@ui/blockquote';
import { query } from '$lib/universal-props-query.svelte';
</script>
<div class={cx(rt.col16, rt.wFull, rt.maxWXl)}>
<div class={cx(rt.gridSm2)}>
<div class={cx(rt.panel)}>
<Blockquote label="size 14" size={14}>A px number sets the root font-size verbatim — the body renders 14px, not 0.875 × 14; the em voice is auto-only.</Blockquote>
</div>
<div class={cx(rt.panel)}>
<Blockquote label="size large" size="large">The named step resolves var(--jx-size-large) and the root renders it verbatim — 18px, no em rescale on top.</Blockquote>
</div>
<div class={cx(rt.panel)}>
<Blockquote label="theme dark" theme="dark">The .dark class bridge re-resolves the island's vars — ground, border and rule inks follow the dark profile.</Blockquote>
</div>
<div class={cx(rt.panel)}>
<Blockquote label="responsive" size={query({ md: 16 }, 14)}>Base 14px below the 48rem viewport, 16px at md and wider — the stamped size lands verbatim at each rung (resize the window).</Blockquote>
</div>
</div>
</div>a11y
Accessibility
The native blockquote element announces quoted prose for free; the cite footer is real attribution markup, not decoration. Reading content, not a control — nothing to focus, nothing to operate.
Keyboard
| Key | Action |
|---|---|
| — | Not focusable — static reading content, not a control |
ARIA
| Attribute | Value | Description |
|---|---|---|
| blockquote | native element | Quoted prose semantics from the platform; no extra ARIA. |
| footer > cite | native elements | The MDN attribution posture — the cite marks the source title, announced with the quote. |
| data-jx-blockquote | variant | Hook attribute carrying the ladder variant (outline | tonal) for styling. |
| data-jx-blockquote-rule | {rule}-{size} | The rule channel hook (e.g. shadow-1, border-4) — tests and tooling read the channel without reverse-engineering utility soup. |
Under forced colors the color-mix tints do not drop on their own: tonal degrades to Canvas ground with CanvasText ink, and the shadow rule re-materializes as an Npx CanvasText border — the edge survives as structure.