All componentsEelco, Saas UI Eelco, Saas UI subtleEelco, Saas UI solidEelco, Saas UI plain
Blockquote
Quotations with subtle and solid accents and an attribution caption.
Ship pages, not stylesheets.
123456789101112import { Blockquote } from "#components/ui/base-ui/blockquote.tsx";
export function Example() { return ( // variant/justify resolve once on Root; parts inherit them via context // and Root exposes data-variant / data-justify attributes <Blockquote.Root variant="subtle"> <blockquote>Ship pages, not stylesheets.</blockquote> <Blockquote.Caption>Eelco, Saas UI</Blockquote.Caption> </Blockquote.Root> );}Variants
Ship pages, not stylesheets.
Ship pages, not stylesheets.
Ship pages, not stylesheets.
Install
1npx stylexblocks add blockquoteSource
components/ui/base-ui/blockquote.tsx
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113import * as stylex from "@stylexjs/stylex";import { createSlotRecipeContext } from "#lib/base-ui/create-slot-recipe-context.tsx";import { defineSlotRecipe } from "#lib/recipe-props.ts";import { colorPalette } from '@stylexblocks/ui/color-palette.stylex.ts'import { fontSizes } from '@stylexblocks/ui/tokens/font-sizes.stylex.ts'import { lineHeights } from '@stylexblocks/ui/tokens/line-heights.stylex.ts'import { semanticColors } from '@stylexblocks/ui/semantic-tokens/colors.stylex.ts'import { sizes } from '@stylexblocks/ui/tokens/sizes.stylex.ts'import { spacing } from '@stylexblocks/ui/tokens/spacing.stylex.ts'
const blockquoteRoot = stylex.create({ base: { position: 'relative', display: 'flex', flexDirection: 'column', gap: spacing._2, },})
const blockquoteRootVariants = stylex.create({ subtle: { paddingInline: spacing._5, borderStartWidth: '4px', borderStartColor: colorPalette.muted, }, solid: { paddingInline: spacing._5, borderStartWidth: '4px', borderStartColor: colorPalette.solid, }, plain: { paddingInline: spacing._5, },})
const blockquoteRootJustifys = stylex.create({ start: { alignItems: 'flex-start', textAlign: 'start', }, center: { alignItems: 'center', textAlign: 'center', }, end: { alignItems: 'flex-end', textAlign: 'end', },})
const blockquoteCaption = stylex.create({ base: { fontSize: fontSizes.sm, lineHeight: lineHeights.sm, color: semanticColors.fgMuted, },})
const blockquoteIcon = stylex.create({ base: { width: sizes._5, height: sizes._5, },})
const blockquoteIconVariants = stylex.create({ subtle: { color: colorPalette.fg, }, solid: { color: colorPalette.solid, }, plain: { color: colorPalette.solid, },})
export type BlockquoteJustify = keyof typeof blockquoteRootJustifys
export type BlockquoteVariant = keyof typeof blockquoteRootVariants
// defineSlotRecipe validates the shape at compile time: default values must// exist in the axis maps, and slot keys must be `styles` or a declared axis// (axis maps are looked up by pluralized axis name: `justify` → `justifys`)const blockquoteSlotRecipe = defineSlotRecipe({ slots: { root: { styles: blockquoteRoot, variants: blockquoteRootVariants, justifys: blockquoteRootJustifys, }, caption: { styles: blockquoteCaption }, icon: { styles: blockquoteIcon, variants: blockquoteIconVariants }, }, defaultVariants: { variant: "subtle", justify: "start" },});
/** * Blockquote — recipe and component colocated in one file. `<Blockquote.Root * variant justify>` resolves the recipe once and every part inherits it * through context; each part composes via `render`. */const { withProvider, withContext } = createSlotRecipeContext( blockquoteSlotRecipe,);
export const Blockquote = { // slot names resolve mechanically from the recipe maps above Root: withProvider("figure", "root", "BlockquoteRoot"), Caption: withContext("figcaption", "caption", "BlockquoteCaption"), Icon: withContext("span", "icon", "BlockquoteIcon"),};