ComponentsData display

Truncated text

One line that ends in an ellipsis when it runs out of room. The full text shows in a tooltip, and only while the line is clipped.

Playground

Change the controls to try each prop. The preview is a 220px table cell. The code under it updates as you go and lists only the props you changed; copy it into your page.

Northbridge Talent Partners International
States
import { TruncatedText } from '@/ui/truncated-text';<TruncatedText text="Northbridge Talent Partners International" />

Clipped

Hover or Tab to the name. The ellipsis says there is more; the tooltip opens after 300ms with the whole name. A clipped line joins the tab order, so keyboard focus opens the same tooltip.

Northbridge Talent Partners International
import { TruncatedText } from '@/ui/truncated-text';

export default function TruncatedTextClipped() {
  return (
    <div className="w-[220px] rounded-medium bg-surface px-100 py-050 text-body leading-body text-text shadow-control">
      <TruncatedText text="Northbridge Talent Partners International" />
    </div>
  );
}

Fits

Nothing is hidden, so there is no tooltip and no tab stop. A tooltip that repeats what's on screen is noise.

Halcyon Bank
import { TruncatedText } from '@/ui/truncated-text';

export default function TruncatedTextFits() {
  return (
    <div className="w-[220px] rounded-medium bg-surface px-100 py-050 text-body leading-body text-text shadow-control">
      <TruncatedText text="Halcyon Bank" />
    </div>
  );
}

Always

With always, the tooltip adds detail on every hover and focus: the exact time behind a relative date. children is what the line shows; text is the tooltip. Screen readers hear both.

Yesterday, Sent 14 Oct 2026, 09:42
import { TruncatedText } from '@/ui/truncated-text';

export default function TruncatedTextAlways() {
  return (
    <div className="flex text-body leading-body text-text">
      <TruncatedText text="Sent 14 Oct 2026, 09:42" always tone="subtle">
        Yesterday
      </TruncatedText>
    </div>
  );
}

Subtle tone

tone="subtle" takes the subtle text colour, for a secondary value under a name.

Maya ChenHalcyon Bank, Treasury Operations
import { TruncatedText } from '@/ui/truncated-text';

export default function TruncatedTextSubtle() {
  return (
    <div className="flex w-[220px] flex-col rounded-medium bg-surface px-100 py-050 text-body leading-body shadow-control">
      <TruncatedText text="Maya Chen" className="font-medium text-text" />
      <TruncatedText text="Halcyon Bank, Treasury Operations" tone="subtle" />
    </div>
  );
}

Where it truncates

Row list

The name gives way first; the avatar and the status keep their width.

Maya Chen-AbernathyInterview
import { TruncatedText } from '@/ui/truncated-text';

export default function TruncatedTextRowList() {
  return (
    <div className="flex w-[260px] items-center gap-100 rounded-medium bg-surface px-100 py-075 text-body leading-body text-text shadow-control">
      <span aria-hidden className="flex size-6 shrink-0 items-center justify-center rounded-full bg-tile text-body-small leading-body-small font-medium text-text-subtle">
        MC
      </span>
      <TruncatedText text="Maya Chen-Abernathy" className="flex-1 font-medium" />
      <span className="shrink-0 rounded-medium bg-background-current px-075 text-body-small leading-body-small font-medium text-text-subtle">
        Interview
      </span>
    </div>
  );
}

Details rail

The value clips at the rail edge; the label never does.

Job
Senior Data Engineer, Payments Platform
import { TruncatedText } from '@/ui/truncated-text';

export default function TruncatedTextDetailsRail() {
  return (
    <dl className="flex w-[240px] items-baseline gap-150 rounded-medium bg-surface px-150 py-100 text-body leading-body shadow-control">
      <dt className="shrink-0 text-body-small leading-body-small font-medium text-text-subtle">Job</dt>
      <dd className="min-w-0 flex-1 text-text">
        <TruncatedText text="Senior Data Engineer, Payments Platform" />
      </dd>
    </dl>
  );
}

On this page