Skip to content

feat(ClampedText): N-line clamp with fade and Show more toggle - #398

Open
ebellamy-bh wants to merge 3 commits into
mainfrom
feat/clamped-text
Open

feat(ClampedText): N-line clamp with fade and Show more toggle#398
ebellamy-bh wants to merge 3 commits into
mainfrom
feat/clamped-text

Conversation

@ebellamy-bh

Copy link
Copy Markdown

Ports waggleline's free-text clamp into the design system — long messages, notes, and descriptions collapse to N lines instead of pushing a detail panel's scroll a mile down.

What it does

  • Clamps to 2–8 lines with a fade-out gradient at the clamp edge and a Show more / Show less toggle (aria-expanded)
  • Short text stays flat: under the threshold character count (default 280) it renders inline with no toggle
  • fadeClassName matches the fade to the surface behind the text (from-card default, from-background for page surfaces)
  • Toggle labels overridable for i18n; toggle clicks stop propagation for use inside clickable containers

Screenshots

A long call note clamped to four lines inside a card:

Light Dark
ClampedText light ClampedText dark

Provenance

Port of waggleline/app/imports/ui/components/ClampedText.tsx (used by its form-details renderer for 2,000-character free-text fields); hardcoded gray/cyan → semantic tokens, static line-clamp-* map kept literal for Tailwind scanning.

Testing

  • 5 unit tests (short-text passthrough, clamp + toggle round-trip, custom threshold, i18n labels, fade class lifecycle)
  • 3 stories (card usage, short text, page-background fade)
  • typecheck / lint / format / rtl:scan clean; combined batch suite 651/651

Ported from waggleline's free-text field renderer: clamps to 2-8 lines
with a surface-matched fade gradient, skips the toggle under a
character threshold so short values stay flat, and exposes toggle
labels for i18n. Hardcoded grays/cyan become semantic tokens.
Copilot AI lite review requested due to automatic review settings August 23, 2026 04:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new ClampedText component to the design system to collapse long free-text fields to a configurable number of lines with a fade edge and a “Show more / Show less” disclosure.

Changes:

  • Introduces ClampedText component implementation, Storybook stories, and unit tests.
  • Exports ClampedText from the package public API (src/index.ts) and adds a tsup entrypoint for component build output.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tsup.config.ts Adds ClampedText to tsup entrypoints so it’s built/published.
src/index.ts Re-exports ClampedText from the package root.
src/components/ClampedText/index.ts Barrel export for ClampedText and its props.
src/components/ClampedText/ClampedText.tsx Implements the N-line clamp UI with fade + toggle.
src/components/ClampedText/ClampedText.test.tsx Adds unit tests covering clamp/toggle behavior and props like threshold/labels/fade.
src/components/ClampedText/ClampedText.stories.tsx Adds Storybook stories demonstrating card/page usage and short-text behavior.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/components/ClampedText/ClampedText.tsx
Comment thread src/components/ClampedText/ClampedText.tsx Outdated
Comment thread src/components/ClampedText/ClampedText.tsx
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 23, 2026

Copy link
Copy Markdown

Deploying ui with  Cloudflare Pages  Cloudflare Pages

Latest commit: 28f471d
Status: ✅  Deploy successful!
Preview URL: https://61fe54be.ui-6d0.pages.dev
Branch Preview URL: https://feat-clamped-text.ui-6d0.pages.dev

View logs

… lines 7, TW3 clamp support

- The short-text branch now spreads ...props and attaches the forwarded
  ref (component retyped to HTMLElement since it renders span or div)
- lines union gains 7 so the documented 2–8 range is real
- Preset twins extend theme.lineClamp with 7/8 and safelist all clamp +
  fade classes so Tailwind 3 consumers generate them (TW4 accepts any
  integer bare value)
Copilot AI review requested due to automatic review settings August 23, 2026 04:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

src/components/ClampedText/ClampedText.tsx:70

  • This component renders a <span> when text.length <= threshold but a <div> when clamped. That means the DOM structure and default display semantics change at runtime based on text length (and can produce invalid HTML if used inside phrasing-only contexts like <p>). Consider rendering a consistent root element (e.g., always a span with block class when clamped, or an as prop).
    if (text.length <= threshold) {
      return (
        <span
          ref={ref as React.ForwardedRef<HTMLSpanElement>}
          className={cn('break-words whitespace-pre-wrap', className)}
          {...props}

src/components/ClampedText/ClampedText.tsx:103

  • The toggle sets aria-expanded, but it doesn’t identify what region it controls (no aria-controls). Several disclosure-style components in this codebase wire aria-controls to the controlled region id (e.g., CollapsibleTrigger), which improves screen reader context. Consider adding a stable id to the clamped text region and referencing it from the button.
        <button
          type="button"
          aria-expanded={open}
          onClick={(e) => {

Comment thread src/tailwind-preset.ts
Comment thread src/tailwind-preset.cjs
Comment thread src/components/ClampedText/ClampedText.stories.tsx
Copilot AI review requested due to automatic review settings August 23, 2026 04:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

src/components/ClampedText/ClampedText.tsx:6

  • ClampedTextProps inherits children from React.HTMLAttributes<HTMLElement>, but the component ignores children and always renders text. Allowing children here makes the API misleading and can silently drop user-provided content; it also makes it easier to accidentally pass props that conflict with rendered children.

Consider omitting children from the inherited attributes, consistent with other data-driven components (e.g. AddressProps uses Omit<...,'children'>).

export interface ClampedTextProps extends React.HTMLAttributes<HTMLElement> {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants