Skip to content

feat(data-grid): add better badge trancation - #1022

Merged
sadmann7 merged 11 commits into
mainfrom
improve-badge-truncation
Nov 18, 2025
Merged

sadmann7 merged 11 commits into
mainfrom
improve-badge-truncation

Conversation

@sadmann7

Copy link
Copy Markdown
Owner

No description provided.

- Replace predictive truncation (lineCount * 3) with actual width measurements
- Add shared cache for badge width measurements across all cells
- Use single ResizeObserver per container (not per badge)
- Implement smart layout algorithm that calculates optimal badge visibility
- Apply to both MultiSelectCell and FileCell
- Add documentation in .ai/ folder

Performance:
- Only ~20-30 ResizeObservers (virtualized rows)
- O(1) measurement per unique label (cached)
- Automatically adjusts to column width changes

Follows Airtable's 'View Projection' pattern for efficient rendering.
- Create useBadgeTruncation hook for shared truncation logic
- Move measurement and caching functions into hook
- Support both text-only and icon+text badges via measureOptions
- Update MultiSelectCell and FileCell to use the new hook
- Reduce code duplication and improve maintainability

Benefits:
- Reusable across different cell types and components
- Centralized cache management
- Consistent truncation behavior
- Easier to test and maintain
- Type-safe with full TypeScript support
- Remove .ai/ documentation files
- Add use-badge-truncation hook to data-grid registry
- Apply formatting fixes to hook
- Replace boolean withIcon with number iconSize for more flexibility
- Allows specifying exact icon size in pixels
- Update FileCell to use iconSize: 12
- Change maxWidth from string to number (pixels) for consistency
- Both options now use the same unit (pixels)
- Update FileCell to use maxWidth: 100 instead of "100px"
- More intuitive API with consistent types
Copilot AI review requested due to automatic review settings November 18, 2025 13:31
@vercel

vercel Bot commented Nov 18, 2025 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
shadcn-table Ready Ready Preview Comment Nov 18, 2025 1:46pm
tablecn Ready Ready Preview Comment Nov 18, 2025 1:46pm

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

This PR improves badge truncation in data grid cells by replacing a simple count-based approach with a more sophisticated width-aware truncation system. The new useBadgeTruncation hook measures actual badge widths to determine which badges can fit within a container, accounting for icon sizes, text content, and configurable line counts.

Key changes:

  • Introduces a new custom hook useBadgeTruncation with width measurement and caching
  • Updates MultiSelectCell and FileCell to use dynamic truncation instead of fixed badge counts
  • Adds the new hook to the component registry

Reviewed Changes

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

File Description
src/hooks/use-badge-truncation.ts New hook implementing width-based badge truncation with DOM measurement and caching
src/components/data-grid/data-grid-cell-variants.tsx Replaces fixed lineCount * 3 badge limits with dynamic width-based truncation in MultiSelectCell and FileCell
registry.json Registers the new hook in the component registry

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/hooks/use-badge-overflow.ts Outdated
Comment thread src/hooks/use-badge-overflow.ts Outdated
Comment thread src/hooks/use-badge-overflow.ts Outdated
Comment thread src/hooks/use-badge-overflow.ts Outdated
- Rename hook from use-badge-truncation to use-badge-overflow
- Update interface names: BadgeOverflowOpts, UseBadgeOverflowOptions, UseBadgeOverflowResult
- Update all imports and usages in data-grid-cell-variants
- Update registry.json

Better naming: 'overflow' describes the problem being solved,
while 'truncation' described the implementation technique.
- Remove nested measureOpts object
- Pass iconSize, maxWidth, className directly as top-level props
- Fixes memoization issue: primitives in deps instead of object reference
- Simpler, cleaner API: useBadgeOverflow({ iconSize: 12 })

Before:
  useBadgeOverflow({ measureOpts: { iconSize: 12, maxWidth: 100 } })

After:
  useBadgeOverflow({ iconSize: 12, maxWidth: 100 })

This fixes the Copilot warning about measureOpts breaking memoization.
- Add containerPadding, badgeGap, overflowBadgeWidth as optional params
- Use DEFAULT_* constants as default values
- Update dependency arrays to include new params
- Allows users to customize spacing for different design systems

Example usage:
  useBadgeOverflow({
    items,
    containerPadding: 20,  // Custom padding
    badgeGap: 8,          // Custom gap
    overflowBadgeWidth: 50, // Custom +N badge width
    ...
  })
@sadmann7
sadmann7 merged commit 59850f7 into main Nov 18, 2025
4 checks passed
@sadmann7
sadmann7 deleted the improve-badge-truncation branch November 18, 2025 13:46
noodleman1991 pushed a commit to noodleman1991/tablecn that referenced this pull request Mar 12, 2026
* feat: improve badge truncation with measurement-based approach

- Replace predictive truncation (lineCount * 3) with actual width measurements
- Add shared cache for badge width measurements across all cells
- Use single ResizeObserver per container (not per badge)
- Implement smart layout algorithm that calculates optimal badge visibility
- Apply to both MultiSelectCell and FileCell
- Add documentation in .ai/ folder

Performance:
- Only ~20-30 ResizeObservers (virtualized rows)
- O(1) measurement per unique label (cached)
- Automatically adjusts to column width changes

Follows Airtable's 'View Projection' pattern for efficient rendering.

* refactor: extract badge truncation logic into reusable hook

- Create useBadgeTruncation hook for shared truncation logic
- Move measurement and caching functions into hook
- Support both text-only and icon+text badges via measureOptions
- Update MultiSelectCell and FileCell to use the new hook
- Reduce code duplication and improve maintainability

Benefits:
- Reusable across different cell types and components
- Centralized cache management
- Consistent truncation behavior
- Easier to test and maintain
- Type-safe with full TypeScript support

* docs: add comprehensive hook documentation

* chore: remove internal docs and update registry

- Remove .ai/ documentation files
- Add use-badge-truncation hook to data-grid registry
- Apply formatting fixes to hook

* refactor: use iconSize instead of withIcon prop

- Replace boolean withIcon with number iconSize for more flexibility
- Allows specifying exact icon size in pixels
- Update FileCell to use iconSize: 12

* refactor: use number for both iconSize and maxWidth

- Change maxWidth from string to number (pixels) for consistency
- Both options now use the same unit (pixels)
- Update FileCell to use maxWidth: 100 instead of "100px"
- More intuitive API with consistent types

* chore: clenaup stuffs

* refactor: rename useBadgeTruncation to useBadgeOverflow

- Rename hook from use-badge-truncation to use-badge-overflow
- Update interface names: BadgeOverflowOpts, UseBadgeOverflowOptions, UseBadgeOverflowResult
- Update all imports and usages in data-grid-cell-variants
- Update registry.json

Better naming: 'overflow' describes the problem being solved,
while 'truncation' described the implementation technique.

* refactor: flatten useBadgeOverflow API

- Remove nested measureOpts object
- Pass iconSize, maxWidth, className directly as top-level props
- Fixes memoization issue: primitives in deps instead of object reference
- Simpler, cleaner API: useBadgeOverflow({ iconSize: 12 })

Before:
  useBadgeOverflow({ measureOpts: { iconSize: 12, maxWidth: 100 } })

After:
  useBadgeOverflow({ iconSize: 12, maxWidth: 100 })

This fixes the Copilot warning about measureOpts breaking memoization.

* refactor: make spacing values configurable via hook params

- Add containerPadding, badgeGap, overflowBadgeWidth as optional params
- Use DEFAULT_* constants as default values
- Update dependency arrays to include new params
- Allows users to customize spacing for different design systems

Example usage:
  useBadgeOverflow({
    items,
    containerPadding: 20,  // Custom padding
    badgeGap: 8,          // Custom gap
    overflowBadgeWidth: 50, // Custom +N badge width
    ...
  })

* feat: update badge-overflow
anhdd-kuro pushed a commit to anhdd-kuro/tablecn that referenced this pull request Apr 8, 2026
* feat: improve badge truncation with measurement-based approach

- Replace predictive truncation (lineCount * 3) with actual width measurements
- Add shared cache for badge width measurements across all cells
- Use single ResizeObserver per container (not per badge)
- Implement smart layout algorithm that calculates optimal badge visibility
- Apply to both MultiSelectCell and FileCell
- Add documentation in .ai/ folder

Performance:
- Only ~20-30 ResizeObservers (virtualized rows)
- O(1) measurement per unique label (cached)
- Automatically adjusts to column width changes

Follows Airtable's 'View Projection' pattern for efficient rendering.

* refactor: extract badge truncation logic into reusable hook

- Create useBadgeTruncation hook for shared truncation logic
- Move measurement and caching functions into hook
- Support both text-only and icon+text badges via measureOptions
- Update MultiSelectCell and FileCell to use the new hook
- Reduce code duplication and improve maintainability

Benefits:
- Reusable across different cell types and components
- Centralized cache management
- Consistent truncation behavior
- Easier to test and maintain
- Type-safe with full TypeScript support

* docs: add comprehensive hook documentation

* chore: remove internal docs and update registry

- Remove .ai/ documentation files
- Add use-badge-truncation hook to data-grid registry
- Apply formatting fixes to hook

* refactor: use iconSize instead of withIcon prop

- Replace boolean withIcon with number iconSize for more flexibility
- Allows specifying exact icon size in pixels
- Update FileCell to use iconSize: 12

* refactor: use number for both iconSize and maxWidth

- Change maxWidth from string to number (pixels) for consistency
- Both options now use the same unit (pixels)
- Update FileCell to use maxWidth: 100 instead of "100px"
- More intuitive API with consistent types

* chore: clenaup stuffs

* refactor: rename useBadgeTruncation to useBadgeOverflow

- Rename hook from use-badge-truncation to use-badge-overflow
- Update interface names: BadgeOverflowOpts, UseBadgeOverflowOptions, UseBadgeOverflowResult
- Update all imports and usages in data-grid-cell-variants
- Update registry.json

Better naming: 'overflow' describes the problem being solved,
while 'truncation' described the implementation technique.

* refactor: flatten useBadgeOverflow API

- Remove nested measureOpts object
- Pass iconSize, maxWidth, className directly as top-level props
- Fixes memoization issue: primitives in deps instead of object reference
- Simpler, cleaner API: useBadgeOverflow({ iconSize: 12 })

Before:
  useBadgeOverflow({ measureOpts: { iconSize: 12, maxWidth: 100 } })

After:
  useBadgeOverflow({ iconSize: 12, maxWidth: 100 })

This fixes the Copilot warning about measureOpts breaking memoization.

* refactor: make spacing values configurable via hook params

- Add containerPadding, badgeGap, overflowBadgeWidth as optional params
- Use DEFAULT_* constants as default values
- Update dependency arrays to include new params
- Allows users to customize spacing for different design systems

Example usage:
  useBadgeOverflow({
    items,
    containerPadding: 20,  // Custom padding
    badgeGap: 8,          // Custom gap
    overflowBadgeWidth: 50, // Custom +N badge width
    ...
  })

* feat: update badge-overflow

This branch was successfully deployed

2 active deployments
Preview – tablecn — 66fbd459 Deployed Nov 18, 2025 by vercel[bot]
Preview – shadcn-table — 66fbd459 Deployed Nov 18, 2025 by vercel[bot]
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