facebook / facebook/astryx

feat(lab): LineClamp — clamp arbitrary content to N lines (port from XDSLineClamp)

Open
#4,180 0 comments 0 reactions 1 assignee View on GitHub

@cixzhang is already working on this.

Since Sep 2, 2026.

component enhancement
Dominant language
TypeScript
Stars
13.2k
Forks
1.1k
Avg merge
1d 14h
Merged PRs (30d)
669

Description

Summary

Add a LineClamp component that truncates arbitrary content to a fixed number of lines with an ellipsis, ported from the internal XDSLineClamp component. Port the value and behavior, not the internal structure.

Why a dedicated component

Astryx already clamps text via Text's maxLines prop (backed by useTruncation). LineClamp is a different primitive: a standalone wrapper that clamps whatever you put inside it to N lines — not just a Text node.

Text maxLines LineClamp
Scope Truncates the Text component's own string content Clamps any children to N lines
Use "This label is one Text, cap it at 2 lines" "Cap this block of mixed/inline content at N lines"
Composition Built into Text Composable around arbitrary content

So this is not a duplicate of Text — it's the reusable clamp primitive that other components and consumers can wrap around content that isn't a single Text.

Proposed behavior (to confirm against the internal source during the port)

  • lines (or maxLines) — number of lines to clamp to.
  • Clamps via -webkit-line-clamp (the same mechanism Text/useTruncation already rely on), with a block/overflow setup that works cross-browser.
  • Truncation detection should reuse the existing useTruncation hook rather than reinventing overflow measurement — it already handles the multi-line Range.getBoundingClientRect() case and shares a single ResizeObserver.
  • Optional tooltip / "show more" affordance on overflow (mirror what the internal component does; decide during the port).
  • Extends BaseProps, xstyle/className/style escape hatches, displayName, 'use client'.

Scope

  • Land in @astryxdesign/lab first (canary-only), following the standard lab → core graduation path.
  • Full component surface: LineClamp.tsx, colocated LineClamp.test.tsx, LineClamp.doc.mjs, index.ts export, Storybook story, showcase block.
  • Reuse useTruncation and semantic tokens; StyleX only.

Open questions for the port

  • Prop name: lines vs maxLines (align with Text's existing maxLines for consistency?).
  • Does the internal component own the overflow-detection/tooltip behavior, or is that left to the consumer? Decide what to port vs. drop.
  • Any semantic-name/API differences from the internal version get resolved to Astryx conventions (port the value, not the internal API shape).

Acceptance criteria

  • LineClamp clamps arbitrary children to N lines with an ellipsis.
  • Reuses useTruncation for overflow detection (no reinvented measurement).
  • StyleX only, tokens, BaseProps escape hatches, displayName, 'use client'.
  • Colocated test, .doc.mjs, Storybook story, showcase block, index.ts export.
  • Lands in @astryxdesign/lab; documented as lab/canary.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.