Fade text
One line of text that never ends in dots: it says itself in fewer characters, then fades its end edge.
import { FadeText } from "@arcadia/ui"One line of text that never ends in dots. Text that fits shows whole, with no mask at all. Text that doesn't fit fades out over its last 24px (16px at caption sizes) at its end edge, the right in a left-to-right line and the left in a right-to-left one. The fade is a mask, so it works on any surface in either theme, and it is on only while the text is cut: no script watches each row, so a sidebar of thousands stays cheap.
Reach for it last. First say the thing in fewer characters (a path's last folder, a branch without its namespace); in a row of chips, let the least important go icon-only (see PriorityRow). Fade only what truly can't fit: a long chat title, a path in a long list.
Examples
Shorter forms
forms lists shorter ways to say the same thing, longest first.
The longest that fits shows; when none fits, the shortest fades. A { cut } form is a sentence's leading whole words: it fades at its own end, its last word dimmed but whole, so a line never ends mid-word. Text given no forms takes textForms: whole sentences, clauses and words, or a path's or a single token's name boundaries (/, -, _, ., a camelCase hump). A part that may go entirely ends its forms with an empty one; one with more text after it on its row takes last={false}, so its last word stays undimmed: only a row's last word fades. Narrow the row to see the namespace go, then the name's parts.
Inside a control
A control that sets its text on its capitals (a Button label, a menu row's description) takes a FadeText as that text.
It trims its own line to the same capitals and keeps the room above and below them inside its clip, so the control keeps its height, no letter is cut, and its forms give way before it fades. A ListRow fits its label and description itself: hand it the text.
Several lines
lines keeps a box of that many lines: the lines above the last stay whole and the last one fades at its end, where a line clamp would have drawn dots.
rootStyle takes where the text sits (margins, flex and grid placement, size bounds) and the fade's length.
--fade-size- Ref<Space> | Derived
- The fade's length: 24px at body sizes, 16px at caption sizes.
--fade-wrap- "normal" | "nowrap"
normal: it wraps, where a narrow layout stacks.
The full text is always in the page, so it is what a screen reader reads and what a copy takes, whatever the eye sees. When a shorter form shows, the full text stays in the DOM out of sight and the shown form is hidden from assistive technology, so nothing is read twice: a button whose label shows "Continue" is still named by its whole label.
On hover, a tooltip shows the full text, but only while the text is cut or shortened; its content is hidden from assistive technology, since the text already says it. Pass full={false} where the row opens a hover card of its own. The mask sits on the text, never on a control, so a focus ring around it stays whole.
FadeText
forms- readonly (ReactNode | { cut: ReactNode })[]Default textForms
- Shorter forms, longest first: the first that fits shows; a
{ cut }one fades at its end. last- booleanDefault true
false: text follows on its row, so a{ cut }form ends undimmed.lines- number
- This many lines; the last fades at its end.
full- "tooltip" | falseDefault "tooltip"
tooltip: the full text on hover while cut or shortened.falsebeside a hover card.onForm- (form: number) => void
- Told the form it shows (0: the whole text).
rootStyle- FadeTextStyle
childrenrequired- ReactNode
- The full text, always the accessible name.
Rest props go to <span> props.