uiatom
Prose
Styles for an article body: headings, paragraphs, lists, links, code, quotes and tables on the Facade type scale. Wrap rendered markdown or hand-written HTML in it.
Preview
Installation
pnpm dlx shadcn@latest add @facade/proseThis component needs utils. The CLI installs them for you.
Usage
This is the code for the preview above. To install it as a file, run npx shadcn@latest add @facade/prose-demo.
import { Prose } from "@registry/ui/prose"
export function Demo() {
return (
<Prose className="max-w-2xl">
<h2>Install the tokens</h2>
<p>
Every section reads the same design tokens. Add them once, then import the file in
your global stylesheet. See <a href="#theming">theming</a> for the presets.
</p>
{/* Focusable, because it scrolls sideways on a narrow screen. */}
<pre tabIndex={0} role="region" aria-label="Install command">
<code>npx shadcn@latest add @facade/tokens</code>
</pre>
<h3>What you get</h3>
<ul>
<li>
shadcn colour names, so <code>bg-primary</code> means what it always did
</li>
<li>Display sizes, section spacing and motion timings</li>
</ul>
<blockquote>
<p>A token that fails contrast fails the build, not the visitor.</p>
</blockquote>
<table>
<thead>
<tr>
<th>Token</th>
<th>Used for</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>--input</code>
</td>
<td>Field borders, at 3:1 or better</td>
</tr>
<tr>
<td>
<code>--ring</code>
</td>
<td>The focus ring</td>
</tr>
</tbody>
</table>
</Prose>
)
}Source
These are the files the CLI copies into your project.
/**
* Prose — styles for an article body: headings, paragraphs, lists, links,
* code, quotes and tables, on the Facade type scale.
*
* Wrap rendered markdown or hand-written HTML in it. It styles descendants by
* element, so the content needs no classes of its own. Not
* `@tailwindcss/typography`, which would bring a second type scale.
*
* a11y:
*
* - Links are underlined, not only coloured, so they are found without
* colour vision (WCAG 1.4.1).
* - Text uses `--foreground` and `--muted-foreground`, both checked by
* `pnpm contrast`; `--primary` is never text.
* - A `<pre>` scrolls sideways when a line is too long. A block that does
* needs `tabIndex={0}`, `role="region"` and an `aria-label`, so keyboard
* users can scroll it too.
*
* Dependencies: react, @/lib/utils.
*/
import type { ComponentPropsWithoutRef } from "react"
import { cn } from "@/lib/utils"
export interface ProseProps extends ComponentPropsWithoutRef<"div"> {
/** The element to render. Use `article` when it is the whole article. */
as?: "div" | "article" | "section"
}
export function Prose({ as: Tag = "div", className, children, ...props }: ProseProps) {
return (
<Tag
className={cn(
"flex flex-col gap-6",
"[&_h2]:mt-6 [&_h2]:scroll-mt-24 [&_h2]:text-2xl [&_h2]:font-semibold [&_h2]:tracking-tight",
"[&_h3]:mt-2 [&_h3]:scroll-mt-24 [&_h3]:text-lg [&_h3]:font-semibold",
"[&_h4]:scroll-mt-24 [&_h4]:font-semibold",
"[&_p]:text-muted-foreground [&_p]:text-pretty",
"[&_ul]:text-muted-foreground [&_ul]:flex [&_ul]:list-disc [&_ul]:flex-col [&_ul]:gap-2 [&_ul]:pl-6",
"[&_ol]:text-muted-foreground [&_ol]:flex [&_ol]:list-decimal [&_ol]:flex-col [&_ol]:gap-2 [&_ol]:pl-6",
"[&_code]:bg-muted [&_code]:rounded [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-[0.85em]",
"[&_pre]:bg-muted [&_pre]:overflow-x-auto [&_pre]:rounded-lg [&_pre]:p-4 [&_pre]:font-mono [&_pre]:text-sm [&_pre]:leading-6",
"[&_pre_code]:bg-transparent [&_pre_code]:p-0 [&_pre_code]:text-[1em]",
"[&_figure_code]:bg-transparent [&_figure_code]:p-0",
"[&_a]:text-foreground [&_a]:underline [&_a]:underline-offset-4",
"[&_blockquote]:border-border [&_blockquote]:text-muted-foreground [&_blockquote]:border-l-2 [&_blockquote]:pl-4",
"[&_table]:w-full [&_table]:border-collapse [&_table]:text-left [&_table]:text-sm",
"[&_th]:border-border [&_th]:border-b [&_th]:py-2 [&_th]:pr-4 [&_th]:font-semibold",
"[&_td]:border-border [&_td]:text-muted-foreground [&_td]:border-b [&_td]:py-2 [&_td]:pr-4",
"[&_img]:rounded-lg",
"[&_hr]:border-border",
className,
)}
{...props}
>
{children}
</Tag>
)
}Props
ProseProps
Extends ComponentPropsWithoutRef<"div">.
| Prop | Type | Default |
|---|---|---|
asThe element to render. Use `article` when it is the whole article. | "div" | "article" | "section" | "div" |