Quote
Testimonials, pull quotes, blockquotes and epigraphs, composed as a figure with a blockquote and a figcaption.
import {
Quote,
QuoteAttribution,
QuoteName,
QuoteRole,
QuoteText,
} from '@fairgarden-private/design/components/Quote'
Quotes set in type-quote, the display italic, and attributions in caps sans: the name over the role, never joined by a pipe. Every part is the scope's one ink. Use curly quotes, keep testimonials to 40 words, and never fabricate or anonymize an attribution. A quote is never a heading, and quotes never go in a carousel.
Kinds
Kinds
kind is required. band centers a testimonial that sits alone on its ground. framed draws a 2 px outline with a heavy open-quote glyph and takes an optional 40 px QuotePortrait. pull closes with a short rule and has no attribution; add duplicate when it repeats the article's text, which renders an aside hidden from assistive technology and drops it from print. block indents a quoted passage behind a 3 px rule; a linked QuoteSource holds a Link. epigraph is one or two lines of display bold italic with no marks.
“I came for the owls and stayed for the people who count them.”
The crew days are the best three hours of my month.
“A meadow is a slow argument with the forest.”
Burning in late winter keeps woody shrubs back and lets the prairie grasses take the light first.
Every trail is a promise to come back.
import { AvatarFallback } from '@fairgarden-private/design/components/Avatar'
import { Link } from '@fairgarden-private/design/components/Link'
import {
Quote,
QuoteAttribution,
QuoteName,
QuotePortrait,
QuoteRole,
QuoteSource,
QuoteText,
} from '@fairgarden-private/design/components/Quote'
import styles from './kinds.module.css'
/** Band and framed testimonials, a pull quote, a blockquote and an epigraph. */
export function QuoteKinds() {
return (
<div className={styles.stack}>
<Quote kind="band">
<QuoteText>
<p>“I came for the owls and stayed for the people who count them.”</p>
</QuoteText>
<QuoteAttribution>
<QuoteName>Ana Díaz</QuoteName>
<QuoteRole>Volunteer since 2019</QuoteRole>
</QuoteAttribution>
</Quote>
<Quote kind="framed">
<QuoteText>
<p>The crew days are the best three hours of my month.</p>
</QuoteText>
<QuoteAttribution>
<QuotePortrait>
<AvatarFallback>BO</AvatarFallback>
</QuotePortrait>
<QuoteName>Ben Okafor</QuoteName>
<QuoteRole>Trail crew lead</QuoteRole>
</QuoteAttribution>
</Quote>
<Quote kind="pull">
<QuoteText>
<p>“A meadow is a slow argument with the forest.”</p>
</QuoteText>
</Quote>
<Quote kind="block">
<QuoteText>
<p>
Burning in late winter keeps woody shrubs back and lets the prairie grasses take the
light first.
</p>
</QuoteText>
<QuoteAttribution>
<QuoteSource>
<Link href="#kinds">Prairie Management Handbook</Link>
</QuoteSource>
</QuoteAttribution>
</Quote>
<Quote kind="epigraph">
<QuoteText>
<p>Every trail is a promise to come back.</p>
</QuoteText>
</Quote>
</div>
)
}
On paper, forest and clay
On paper, forest and clay
Inside a deep field such as forest the frame and text turn light on their own. Saturated fields such as clay hold the band only, in their one ink.
paper
Worth every early start.
forest field
Worth every early start.
clay field
“Worth every early start.”
import { Ground } from '@fairgarden-private/design/components/Ground'
import {
Quote,
QuoteAttribution,
QuoteName,
QuoteRole,
QuoteText,
} from '@fairgarden-private/design/components/Quote'
import styles from './grounds.module.css'
/** Framed on a page ground and a deep field; saturated fields hold the band only, in one ink. */
export function QuoteGrounds() {
return (
<div className={styles.row}>
<Ground kind="face" preset="paper" className={styles.face}>
<p className={styles.name}>paper</p>
<FramedQuote />
</Ground>
<Ground kind="field" preset="forest" className={styles.face}>
<p className={styles.name}>forest field</p>
<FramedQuote />
</Ground>
<Ground kind="field" preset="clay" className={styles.face}>
<p className={styles.name}>clay field</p>
<Quote kind="band">
<QuoteText>
<p>“Worth every early start.”</p>
</QuoteText>
<QuoteAttribution>
<QuoteName>Mei Lin</QuoteName>
</QuoteAttribution>
</Quote>
</Ground>
</div>
)
}
function FramedQuote() {
return (
<Quote kind="framed">
<QuoteText>
<p>Worth every early start.</p>
</QuoteText>
<QuoteAttribution>
<QuoteName>Mei Lin</QuoteName>
<QuoteRole>Member</QuoteRole>
</QuoteAttribution>
</Quote>
)
}
Placement and print
The hanging pull quote and 2-up framed testimonials are page-grid placements from 1024 px of viewport, set by the page template; the component has no container. In print the frame prints at 1.5 pt and the portrait in grayscale.
API Reference
Quote
The quote: a figure holding QuoteText (the blockquote) and, for
testimonials, a QuoteAttribution (figcaption) with QuoteName,
QuoteRole, an optional QuotePortrait and an optional QuoteSource.
Keep band and framed testimonials to 40 words; never put quotes in a
carousel.
| Prop | Type | Description |
|---|---|---|
duplicate | | The pull quote repeats text from the article: it renders as an
|
kind | | A pull quote: |
primary | | Primary Radix scale: text, mark, rules, frame and attribution. Never defaulted; omitted, it inherits the scope [D133]. |
secondary | | Secondary Radix scale: only a linked source’s underline
( |
QuoteText
The quoted words, a blockquote (pass cite for a source URL):
type-quote for band, framed and pull; type-body behind the left rule
for block; display bold italic for epigraph. Curly quotes only; pull
quotes hang their punctuation. A pull quote closes with its short rule.
QuoteAttribution, QuoteName and QuoteRole
Who said it, --size-px-5 below the quote: QuotePortrait, then
QuoteName over QuoteRole (a line break, never a pipe), then an
optional QuoteSource.
The person’s name: type-label caps in --primary12, on its own line.
Role or affiliation under the name: type-caption in --primary12.
QuotePortrait and QuoteSource
The portrait: an Avatar at 40 px (md) with its --role-rule ring,
taking the quote’s primary and secondary unless given its own. Compose
AvatarImage (empty alt, since the name is adjacent) and
AvatarFallback inside. Prints grayscale, at most 20 mm.
| Prop | Type | Description |
|---|---|---|
primary | | Primary Radix scale: the ring. Never defaulted; omitted, it inherits the scope [D133]. |
secondary | | Secondary Radix scale, accepted for the shared contract; no part uses it. |
size | |
|
The source title in a cite (type-caption, upright). Link it with a
Link inside, which owns the --role-accent underline and its states.
Additional types
QuoteAttributionProps
Props for QuoteAttribution: figcaption props and render.
type QuoteAttributionProps = useRender.ComponentProps<'figcaption'>QuoteKind
The five quote builds (§12.8).
type QuoteKind = 'band' | 'framed' | 'pull' | 'block' | 'epigraph'QuoteNameProps
Props for QuoteName: span props and render.
type QuoteNameProps = useRender.ComponentProps<'span'>QuotePortraitProps
Props for QuotePortrait: Avatar props; size defaults to md.
type QuotePortraitProps = AvatarPropsQuoteProps
Props for Quote: figure props, render, the kind (and duplicate) and the color axes.
type QuoteProps =
| (React.ClassAttributes<HTMLElement> &
React.HTMLAttributes<HTMLElement> &
__type & { kind: 'pull'; duplicate?: boolean } & {
primary?:
| 'ruby'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'crimson'
| 'tomato'
| 'pink'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| null;
secondary?:
| 'ruby'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'crimson'
| 'tomato'
| 'pink'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| 'amber'
| 'blue'
| 'cyan'
| 'grass'
| 'green'
| 'jade'
| 'lime'
| 'mint'
| 'orange'
| 'sky'
| 'teal'
| 'yellow'
| null;
})
| (React.ClassAttributes<HTMLElement> &
React.HTMLAttributes<HTMLElement> &
__type & { kind: 'band' | 'framed' | 'block' | 'epigraph'; duplicate?: undefined } & {
primary?:
| 'ruby'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'crimson'
| 'tomato'
| 'pink'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| null;
secondary?:
| 'ruby'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'crimson'
| 'tomato'
| 'pink'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| 'amber'
| 'blue'
| 'cyan'
| 'grass'
| 'green'
| 'jade'
| 'lime'
| 'mint'
| 'orange'
| 'sky'
| 'teal'
| 'yellow'
| null;
})QuoteRoleProps
Props for QuoteRole: span props and render.
type QuoteRoleProps = useRender.ComponentProps<'span'>QuoteSourceProps
Props for QuoteSource: cite props and render.
type QuoteSourceProps = useRender.ComponentProps<'cite'>QuoteTextProps
Props for QuoteText: blockquote props and render.
type QuoteTextProps = useRender.ComponentProps<'blockquote'>Specification: DESIGN-SYSTEM.md §12.8 (testimonial and quote).