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

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.

install — blockquote

$npx jixoai-ui add blockquote

https://ui.jixoai.com/r/blockquote.json

native <blockquote> outline · tonal (frozen) rule shadow|border × 1|4|8 label / icon / cite GitHub alerts land here

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.

Blockquote usage
<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.
EWD 648, 1978
blockquote-usage.svelte svelte
<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).

outline — shadow (own) × border, 1 | 4 | 8
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.
the resolved default — 4 won the browser review; 1 stays the xs2-scale hairline
shadow-1: the hairline — fits xs2-scale contexts only.
shadow-4: the default manuscript bar every quote now ships.
tonal — the box border stays; the shadow rule rides beside it
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.
blockquote-rule-usage.svelte svelte
<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.
blockquote-icon-usage.svelte svelte
<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

PropertyTypeDefaultDescription
variant 'outline' | 'tonal''outline' · ambient zoneLadder 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 ambientThe 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 | 84 · Own default, not ambientThe 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

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)

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).

PropertyTypeDefaultDescription
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).
blockquote-axes-usage.svelte svelte
<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

KeyAction
—Not focusable — static reading content, not a control

ARIA

AttributeValueDescription
blockquotenative elementQuoted prose semantics from the platform; no extra ARIA.
footer > citenative elementsThe MDN attribution posture — the cite marks the source title, announced with the quote.
data-jx-blockquotevariantHook 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.

jixoai-ui ui.jixoai.com the jixoai design language

Theme

Brand hue

0°

Auto cycle · 24h