feat: add composable DataTable component#18
Conversation
📦 Alpha published
pnpm add @datum-cloud/datum-ui@0.3.0-alpha.4702cdb
# or use the alpha tag for the latest alpha:
pnpm add @datum-cloud/datum-ui@alpha |
|
@gaghan430 The data-table component can now be reviewed and tested. You can use the alpha version |
I'll try it out... thanks! |
Monosnap.screencast.2026-03-10.20-25-49.mp4@yahyafakhroji I have a few things for now and will continue testing further:
I’ll continue testing and will share more feedback if I find anything else. |
…cture - Reactive store (useSyncExternalStore) with selector hooks for re-render isolation - Pre-filtering engine with built-in strategies (checkbox, select, date-gte, date-lte) - Self-registering filter components (register strategy on mount) - Client-side mode: filtering, sorting, pagination, search with useTransition - Server-side mode: cursor-based pagination, fetch lifecycle management - nuqs adapter for URL state sync with simple sort format (-column for desc) - Selection column auto-injection with bulk actions - Inline content registration system - React.memo on all leaf components for performance - 320 tests across 48 test files - Storybook stories and docs page - CI: alpha publish workflow for PR previews
9d90881 to
ffa8392
Compare
…se components - Add DataTable.ActiveFilters compound component with grouped filter badges, customizable label, clear-all variants (icon/button/text), and className/data-slot support for styling - Migrate all data-table components from @repo/shadcn imports to datum-ui base components (Button, Input, Badge, Select, etc.) for Alpha theme consistency - Fix Badge variant prop in checkbox-filter (variant -> type/theme) - Update storybook stories with ActiveFilters demos and customization - Update fumadocs docs with ActiveFilters section, tri-state sorting, server fetchFn/transform pattern, and new data-slot entries
…race condition - Add aria-labels to pagination prev/next and page number buttons - Add aria-current="page" to active page button - Wrap pagination buttons in nav landmark - Add aria-label to search input - Add descriptive aria-label with sort state to column header button - Add setPagination batch method to avoid double state updates - Add input validation on setPageIndex/setPageSize (NaN/negative guard) - Use immutable Map reassignment in registerFilter/unregisterFilter - Merge cursor-reset effect into fetch effect to fix server hook race condition - Replace separate useState(hasNextPage) with ref to avoid extra render cycle
Addressing review feedback
Here's a summary of what was done to address each point from the review: 1. "The table feels a bit laggy compared to the existing staff portal table, especially when sorting"
2. "There doesn't seem to be a way to return to the unsorted state (asc → desc → remove sort)"
3. "Pagination doesn't seem to be working properly / use detailed pagination instead of cursor-based"
4. "Would it be possible to have an active filter component similar to the staff portal?"
5. "The style doesn't seem to follow the Alpha theme (e.g., search field)"
Full changelogCommit 1:
|
|
@yahyafakhroji Im getting this error using latest package, could be related with data-table |
Add getServerSnapshot to all useSyncExternalStore calls for React 18+ SSR compatibility. Refactor providers to accept hook options directly as props, creating store/table internally with a two-layer SSR gate (useIsClient → conditional render). Breaking changes: - useDataTableClient and useDataTableServer removed from public exports - useDataTableContext deprecated facade removed - Providers no longer accept store/table props; pass data/columns/etc. directly Changes: - Add useIsClient hook for SSR/hydration detection - Rewrite ClientProvider and ServerProvider with inner/outer pattern - Add ssrFallback prop for custom loading state during SSR - Remove useDataTableContext deprecated facade from use-selectors - Delete hooks/use-data-table-context.ts re-export file - Update all tests and storybook stories to inline API
…race condition - Replace use() with useContext() for DataTableRenderKeyContext to fix SSR context subscription bug where use() fails to register subscriptions after React Router SSR hydration, causing sort/pagination/page-size changes to not re-render components - Add _version monotonic counter to store state, incremented on every setState, powering DataTableRenderKeyContext for table-dependent hooks - Wrap providers (client + server) with DataTableRenderKeyContext - Rewrite useDataTableSelection, useDataTablePagination, useDataTableRows to use useRenderKey() + direct table reads instead of useSliceSelector - Fix pagination active button using disabled styling instead of full opacity (aria-disabled + pointer-events-none instead of disabled prop)
1a6419a to
bdce331
Compare
|
@gaghan430 Just pushed a fix — can you try again with the latest from this branch - @datum-cloud/datum-ui (0.3.0-alpha.bdce331) ? If you're still seeing issues, could you share which version you're on and how you're importing the data-table? |
- Add "source" condition to all datum-ui package exports pointing to TypeScript source files (CSS-only exports ./grid and ./nprogress intentionally omitted to avoid PostCSS resolving TS files as CSS) - Configure storybook rsbuild to prefer "source" conditionNames so @datum-cloud/datum-ui resolves to src/ directly, bypassing tsdown - Replace unconditional predev in storybook and docs with a guard that only builds datum-ui when dist is missing, preventing race conditions when running via turbo while still supporting direct pnpm dev runs
- Update docs to use inline props pattern (no more useDataTableClient/ useDataTableServer hook-and-spread) matching the actual SSR-safe API - Deduplicate types: hooks now import from types.ts instead of defining local copies that diverged (ServerTransformResult.nextCursor vs cursor) - Fix runtime to read result.cursor matching the public type - Add missing filterFns, className, ssrFallback props to docs and types
…perf - Add disabled prop to Search, SelectFilter, CheckboxFilter, DatePickerFilter - Add native disabled prop to CalendarDatePicker (replaces CSS workaround) - Extract FilterOption type and DataTableBaseProps to reduce duplication - Extract shared test-helpers.tsx (mockTable, createTestStore, renderWithStore) - Convert excludeFilters to Set for O(1) lookups in ActiveFilters - Add dot-path resolution for nested filter column access - SSR fallback defaults to skeleton table instead of blank - Rewrite Loading skeleton to use shadcn Table components - Add excludeFilters support with reserved 'search' key - Update docs with disabled state, filterFns, and dot-notation sections
SelectFilter and CheckboxFilter triggers defaulted to h-9 via datum-ui Button, causing a 4px mismatch with the Search input (h-10). Added explicit h-10 to both filter trigger buttons for consistent height within DataTable context. Consumer className overrides still work.
Radix UI and cmdk packages are now regular dependencies instead of peerDependencies, so consumers no longer need to install them manually. Added tw-animate-css to root styles for component animations. Updated all 27 component docs to remove radix/cmdk from install instructions.
Move sidebar.tsx to base/sidebar/ so consumers can use the base sidebar layout without installing motion. Rename AppSidebar to AppNavigation and NavMain to NavMenu in new app-navigation export. Update storybook stories and docs accordingly.
- Make lucide-react a required (non-optional) peer dependency since base sidebar primitives import it directly - Export sidebar from base barrel (base/index.ts) - Add h-10 height to DatePickerFilter trigger for consistent filter alignment - Pass className through to DataTableLoading SSR fallback - Extract skeleton to dedicated file with datum-ui customization
…Value API Remove the SSR hydration gate (useIsClient) and make the store always available during SSR. Table instance is deferred to after hydration via a tableReady state gate, with null-safe selector hooks throughout. - Remove useIsClient hook and SSR fallback rendering - Add useTableInstanceOrNull for null-safe table access during SSR - Refactor ClientProvider into outer (store) + inner (table) components - Extract useClientTable and useServerTable hooks from providers - Add loading prop to DataTable.Client for consumer-controlled skeleton state - Add columnCount to store so Content derives skeleton columns from columns.length - Fix loading effect ordering to prevent empty-message flash - Refactor formatFilterValue from function to Record<string, (value) => string> with dot-notation support - Remove dead setTable from store interface - Deprecate useTableInstance with accurate hydration error message - Update docs, storybook, and tests for all changes
Today's Changes (Mar 13)SSR Fallback Removal, Loading Prop & formatFilterValue API (
|


Summary
DataTablecompound component with a reactive store architecture (useSyncExternalStore) featuring selector-based hooks for minimal re-rendersuseTransitionfor non-blocking UIfetchFn/transformpatterncheckbox,select,date-gte,date-lte)ActiveFilterscomponent with grouped filter badges, customizable labels, clear-all variants, anddata-slotsupport-columnfor desc)aria-current="page", nav landmarksSidebar Refactor
sidebar.tsxintobase/sidebar/(layout primitives, nomotiondependency) andfeatures/app-navigation/(renamed fromAppSidebar→AppNavigation,NavMain→NavMenu)Dependency & DX Changes
lucide-reacta required peer dep (used by base sidebar primitives)tw-animate-cssto root styles for component animations"source"export condition to all package exports for instant Storybook HMR (resolves TS source directly, bypasses tsdown)predevguard — only buildsdatum-uiwhendist/is missing, preventing turbo race conditions