ui · Primitive
TruncatedText
@devalok/shilp-sutra/ui/truncated-textView in Storybook Preview
This is a long project title that will not fit on a single line and gets clipped with an ellipsis.
Variants
mode="end" (default)
A single-line label that trails off at the end when it overflows.
mode="middle" (filenames)
quarterly-financial-report-2026-final-v2.pdf
mode="clamp" lines={2}
A longer description that wraps across multiple lines and is clamped to two lines before it is cut off with an ellipsis at the end.
Reference
- Import: @devalok/shilp-sutra/ui/truncated-text
- Server-safe: No
- Category: ui
Props
children: string (REQUIRED — the full text; always the accessible name, even when shortened)
mode: "end" | "clamp" | "middle" (end [default] = single-line ellipsis; clamp = multi-line; middle = keep both ends)
lines: number (lines to show in mode="clamp"; default 2)
as: "span" | "p" | "div" (element to render; default "span")
tooltip: boolean (show the full text in a tooltip when — and only when — actually clipped; default true)
title: string (override the full-text accessible name / tooltip; defaults to children)
className: string
Defaults
mode="end", lines=2, as="span", tooltip=true
Example
<TruncatedText>{user.name}</TruncatedText>
// Filenames / emails — keep the extension / domain:
<TruncatedText mode="middle">{fileName}</TruncatedText> // report…v7.pdf
// Multi-line description with a 2-line clamp:
<TruncatedText as="p" mode="clamp" lines={2}>{description}</TruncatedText>
// In a flex row, the shrinking item still needs min-w-0:
<div className="flex items-center gap-ds-03">
<Avatar … />
<TruncatedText className="min-w-0 flex-1">{user.name}</TruncatedText>
</div>Composability
- Truncates AND recovers in one place:
end/clampare pure CSS (full text stays in the DOM → screen-reader safe).middlemeasures the element and JS-shortens the visible string but keeps the full string as the accessible name. A tooltip appears only whenscrollWidth/scrollHeightactually exceeds the box (measured via ResizeObserver) — no tooltip noise on text that fits. mode="middle"for identifiers: filenames (extension), emails (domain), paths, hashes — end-ellipsis destroys the meaningful tail; middle keeps both ends. Middle is not native CSS, so it's measured + recomputed on resize.- The flexbox gotcha:
truncate(andmiddle) do nothing on a flex/grid child unless that item hasmin-w-0(or an explicit width). TruncatedText can't set that on its parent — addmin-w-0at the call site. - Don't truncate everything: page titles/H1, toast bodies, validation messages, and numbers must show fully (a truncated number is a wrong number). Use this for bounded list/nav/metadata text.
Gotchas
childrenmust be a string (it's measured + used as the accessible name) — not arbitrary ReactNode.- In a flex row, add
min-w-0to the TruncatedText (or its column) or nothing truncates. mode="middle"clips to the largest middle-truncated string that fits; the last glyph may be sub-pixel-clipped by overflow-hidden — the tooltip + aria-label always carry the full string.
Changes
v0.44.0
- Added Initial release — end/clamp/middle truncation with overflow-aware tooltip recovery.