Text and display

Contents

  • Use typography primitives for styled text
  • Text.Sans vs Text.Heading vs Text.Mono
  • InlineCode vs CopyableCode vs CodeBlock
  • Markdown and DescriptionList
  • Avatar
  • FilePreview vs file-list parts
  • Kbd
  • Icons

Use typography primitives for styled text

Use the Text namespace when standalone copy needs raft-ui typography. Keep native text elements when their semantics and inherited styles are intentional.

Incorrect:

tsx
<p className="text-sm text-gray-500">Last synced 2 minutes ago</p>

Correct:

tsx
<Text.Sans size="small">Last synced 2 minutes ago</Text.Sans>

Text.Sans vs Text.Heading vs Text.Mono

ComponentFor
Text.Sansbody copy, labels, and descriptions
Text.Headingsection and page headings; level is 1 through 6
Text.Monocode-like values, metadata, and tabular numbers

Prefer the namespace used by the canonical compositions.

Text.Sans sizes — large body small caption.

Text.Mono sizes — code meta eyebrow tabular.

Use Text.Mono size="tabular" for numbers that update in place — counts, timers, file sizes, and percentages. Proportional digits can change width and make the surrounding layout jitter.

tsx
<Text.Mono size="tabular">{unreadCount}</Text.Mono>

Use size="meta" for timestamps and IDs, size="eyebrow" for the small label above a section.

Text.Heading level selects both the heading element and its recipe size. Pick it from document structure. Use render only when the surrounding document requires a different element.


InlineCode vs CopyableCode vs CodeBlock

Use
InlineCodea token inside a sentence — a prop name, a flag, a key
CopyableCodea single-line command the user is meant to run or paste
CodeBlockmulti-line code on display

If the user's next move is to select the text, it should have been CopyableCode or CodeBlock.

tsx
<CopyableCodeRoot>
  <CopyableCode truncate>{command}</CopyableCode>
  <CopyableCodeAction aria-label="Copy install command" />
</CopyableCodeRoot>

CopyableCodeRoot sizes are sm and md. Use truncate on CopyableCode for long single-line commands, and give CopyableCodeAction an aria-label that says what is being copied. When you omit it, the label swaps between Copy code and Copied code.

Compose a titled block with CodeBlockHeader, CodeBlockTitle, CodeBlockActions, and CodeBlockAction above CodeBlockBody. In a block without a header, place CodeBlockActions inside CodeBlockBody. Render the complete <pre><code>…</code></pre> as body content.


Markdown and DescriptionList

Rendered markdown is styled by the Markdown* part set. Map paragraphs, headings, lists, links, blockquotes, inline code (MarkdownInlineCode; fenced code is CodeBlock), tables, images, task checkboxes, rules, and marks to the matching exported parts. Wrap wide tables in MarkdownTableScroll, and compose MarkdownTable, MarkdownTableRow, MarkdownHeaderCell, and MarkdownCell.

DescriptionList renders term/value pairs. Wrap DescriptionTerm and DescriptionDetails in DescriptionItem, and set direction="horizontal" or direction="vertical".


Avatar

tsx
<Avatar type="human" size="sm">
  <AvatarImage src={user.avatarUrl} />
  <AvatarFallback>{initials}</AvatarFallback>
</Avatar>
  • Pass the required type and size props. type is agent or human; it picks the placeholder fill.
  • Sizes are 3xs 2xs xs sm md lg xl.
  • Include AvatarFallback whenever you include AvatarImage. When Avatar has no children, it renders its built-in fallback automatically.
  • Use AvatarGroup and AvatarGroupCount for stacks. Pass the required avatar size to AvatarGroupCount.
  • AvatarBadge for a presence dot attached to the avatar. For a standalone state dot elsewhere, use Status.

FilePreview vs file-list parts

FilePreview renders one file as a tile. It has dedicated shapes rather than a type prop:

ShapeFor
FilePreviewMediaimages and video
FilePreviewDocumentPDFs and documents
FilePreviewCodesource files
FilePreviewFileanything else

Pick the shape by what the file is. FilePreviewBadge labels the format.

The file-list parts render a list surface: FilesPanel, FilesViewport, FilesList, and per-row FileRow, FileThumbnail, FileContent, FileName, FileMeta, FileMetaItem, FileActions, FileAction, FileRowOpen, FileImage. There is no Files root component.

Use FilePreview for attachments inside a composer or message; compose the file-list parts for a browsable list.


Kbd

tsx
<KbdGroup aria-label="Command K">
  <Kbd>⌘</Kbd>
  <Kbd>K</Kbd>
</KbdGroup>

Render one key per Kbd. Use KbdGroup to apply spacing to a key combination. Add any visible separator as explicit content when the shortcut notation requires one.


Icons

Raft-ui's internal recipes and canonical compositions are tuned to Lucide SVGs, but raft-ui does not re-export Lucide; it exports only the conversation icons MessageIcon, ChatIcon, DirectMessageIcon, and ThreadIcon. When application code imports Lucide icons, declare lucide-react as a direct application dependency rather than relying on raft-ui's transitive dependency. A consumer may provide another SVG icon set when it preserves the component's expected sizing and stroke treatment.

Let raft-ui components own their icons' default treatment. Buttons, menu items, sidebar items, toasts, and tabs apply recipe-specific sizing and sometimes stroke widths. Override those values only when the component's API or a deliberate one-off treatment requires it.

Incorrect:

tsx
<Button size="icon-sm">
  <SearchIcon className="size-4 stroke-2" />
</Button>

Correct:

tsx
<Button size="icon-sm">
  <SearchIcon />
</Button>

In your own markup — outside any icon-owning component — size icons explicitly (className="size-4").