Repository navigation
feat(data-grid): add better badge trancation - #1022
Merged
Merged
Conversation
- 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
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
There was a problem hiding this comment.
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
useBadgeTruncationwith width measurement and caching - Updates
MultiSelectCellandFileCellto 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.
- 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
...
})
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.