Improve table design consistency across the dashboard - #6276
Conversation
mirekm
commented
Jan 24, 2026
- Unified styling for ResponsiveTable components
- Better loading states
- Improved scroll behavior for variant navigation
- Many small improvements and fixes met along the way
🦋 Changeset detectedLatest commit: a950d14 The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #6276 +/- ##
==========================================
+ Coverage 42.50% 42.54% +0.03%
==========================================
Files 2494 2494
Lines 43259 43320 +61
Branches 10181 10258 +77
==========================================
+ Hits 18389 18432 +43
+ Misses 24833 23563 -1270
- Partials 37 1325 +1288 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This pull request standardizes table/list UI across the dashboard: it introduces a richer ResponsiveTable wrapper (with built‑in search, empty and footer states), unifies pagination via TablePagination/DatagridPagination, and improves several specific flows (variant navigation, taxes, shipping, permissions, etc.) for better consistency.
Changes:
- Reworked many list and detail views to use the new
ResponsiveTable+Placeholderpattern, with consistent paddings, headers, and empty/loading states. - Introduced
DatagridPaginationand enhancedTablePaginationso datagrid and non-datagrid views share a common pagination UX, while also tweaking theme overrides and global CSS for inputs and selects. - Improved UX in several screens (variant navigation auto-scroll + skeletons, tax/tax-class/country/channel menus, shipping configuration cards, save button tooltips) while cleaning up legacy styles and redundant table paddings.
Reviewed changes
Copilot reviewed 132 out of 132 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| testUtils/setup.ts | Adds a global scrollIntoView mock to support new auto-scroll behavior in tests. |
| src/warehouses/components/WarehouseListPage/WarehouseListPage.tsx | Replaces the standalone search input with WarehouseList’s new search prop and keeps the list inside the card content. |
| src/warehouses/components/WarehouseList/WarehouseList.tsx | Switches to named ResponsiveTable, adds an optional search config and moves pagination into the table footer while simplifying the header “Actions” column. |
| src/translations/components/TranslationsLanguageListPage/TranslationsLanguageListPage.tsx | Wraps the language list in a padded Box for consistent spacing. |
| src/translations/components/TranslationsLanguageList/TranslationsLanguageList.tsx | Uses named ResponsiveTable and removes custom padding overrides, simplifying row classes. |
| src/translations/components/TranslationsEntitiesListPage/TranslationsEntitiesListPage.tsx | Wraps entities list content in DashboardCard.Content and adds bottom padding spacer for layout consistency. |
| src/translations/components/TranslationsEntitiesList/TranslationsEntitiesList.tsx | Uses new ResponsiveTable footer for pagination instead of a TableFooter. |
| src/themeOverrides.ts | Tweaks MuiOutlinedInput border behavior (moves border color to notchedOutline and hover state) for more consistent input styling. |
| src/taxes/pages/TaxCountriesPage/styles.ts | Removes now-unused TaxCountries page-specific styles in favor of new table/menu components. |
| src/taxes/pages/TaxCountriesPage/TaxCountriesPage.tsx | Rebuilds the tax class rates section using DashboardCard + ResponsiveTable with integrated search and column headers, instead of list components. |
| src/taxes/pages/TaxCountriesPage/TaxCountriesMenu/styles.ts | Deletes menu-specific JSS in favor of the new reusable TaxMenu. |
| src/taxes/pages/TaxCountriesPage/TaxCountriesMenu/index.ts | Exports the named TaxCountriesMenu component only. |
| src/taxes/pages/TaxCountriesPage/TaxCountriesMenu/TaxCountriesMenu.tsx | Replaces bespoke card/list menu with TaxMenu and an items array describing each country row and delete action. |
| src/taxes/pages/TaxClassesPage/styles.ts | Trims unused styles (search row padding, divider overrides) that are no longer needed with the new table layout. |
| src/taxes/pages/TaxClassesPage/TaxClassesPage.tsx | Refactors the tax-class detail view to use ResponsiveTable + TablePagination for country rates with integrated search and footer-based pagination. |
| src/taxes/pages/TaxClassesPage/TaxClassesMenu/index.ts | Changes to export named TaxClassesMenu. |
| src/taxes/pages/TaxClassesPage/TaxClassesMenu/TaxClassesMenu.tsx | Switches the tax-class menu to use TaxMenu items and toolbar instead of custom card/list styling. |
| src/taxes/pages/TaxChannelsPage/TaxChannelsPage.tsx | Updates import to named TaxChannelsMenu. |
| src/taxes/pages/TaxChannelsPage/TaxChannelsMenu/styles.ts | Removes old styling now replaced by TaxMenu. |
| src/taxes/pages/TaxChannelsPage/TaxChannelsMenu/index.ts | Exports named TaxChannelsMenu. |
| src/taxes/pages/TaxChannelsPage/TaxChannelsMenu/TaxChannelsMenu.tsx | Reimplements channel menu using TaxMenu items (channel name and selection state). |
| src/taxes/messages.ts | Adjusts channel/tax messages; adds channelNameHeader and updates the tax class rates header copy and IDs. |
| src/taxes/components/TaxPagination/index.ts | Removes the old TaxPagination wrapper in favor of standard TablePagination. |
| src/taxes/components/TaxPagination/TaxPagination.tsx | Deletes the bespoke tax pagination component (superseded by shared pagination). |
| src/taxes/components/TaxMenu/index.ts | Adds index file exporting the new TaxMenu. |
| src/taxes/components/TaxMenu/TaxMenu.tsx | Introduces TaxMenu (common card + list wrapper for channel/country/tax-class menus). |
| src/taxes/components/TaxMenu/TaxMenu.module.css | Defines non-Box styles (fit-content height, selection indicator, ellipsis, hover background) for TaxMenu. |
| src/structures/components/MenuList/MenuList.tsx | Migrates structure menu list to new ResponsiveTable + footer pagination and uses shared tableStyles.colAction for action column. |
| src/staff/components/StaffListDatagrid/StaffListDatagrid.tsx | Switches footer pagination from TablePaginationWithContext to DatagridPagination. |
| src/shipping/components/ShippingZonesListDatagrid/ShippingZonesListDatagrid.tsx | Same datagrid pagination swap for shipping zones list. |
| src/shipping/components/ShippingZoneRatesPage/ShippingZoneRatesPage.tsx | Adds spacing after metadata and wires a tooltip into the save button when prices aren’t valid. |
| src/shipping/components/ShippingZoneRatesCreatePage/ShippingZoneRatesCreatePage.tsx | Similarly adds spacing and disabled-save tooltip for the create shipping rate flow. |
| src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx | Reworks table into a DashboardCard.Content with empty and loading states (Skeleton/Placeholder) and conditional ResponsiveTable rendering. |
| src/shipping/components/ShippingZonePostalCodes/ShippingZonePostalCodes.tsx | Uses Placeholder for no postal codes, updates expand/collapse icon and alignment, and moves table into DashboardCard.Content. |
| src/shipping/components/ShippingZoneCountriesAssignDialog/styles.ts | Adjusts checkbox and wide cell paddings to work with the new table appearance. |
| src/shipping/components/ShippingZoneCountriesAssignDialog/ShippingZoneCountriesAssignDialog.tsx | Switches to named ResponsiveTable and tweaks padding/scroll height behavior for the country list. |
| src/shipping/components/ShippingMethodProductsAddDialog/ShippingMethodProductsAddDialog.tsx | Updates import to named ResponsiveTable. |
| src/shipping/components/ShippingMethodProducts/ShippingMethodProducts.tsx | Wraps content in DashboardCard.Content, adds proper loading/empty (Skeleton/Placeholder) states and uses ResponsiveTable footer pagination. |
| src/shipping/components/PricingCard/styles.ts | Removes custom padding overrides to align with new table spacing. |
| src/shipping/components/PricingCard/PricingCard.tsx | Uses named ResponsiveTable and adds vertical margin to PriceField inputs via sprinkles. |
| src/shipping/components/OrderValue/styles.ts | Simplifies styles (removes theme-based paddings) while keeping column widths and table layout. |
| src/shipping/components/OrderValue/OrderValue.tsx | Moves the checkbox and table into DashboardCard.Content and adds spacing around PriceField instances. |
| src/products/components/ProductVariantPrice/ProductVariantPrice.tsx | Refactors variant price table into DashboardCard.Content + ResponsiveTable and simplifies cell styling. |
| src/products/components/ProductVariantPage/ProductVariantPage.tsx | Enhances the top nav title with product name + variant name breadcrumb and passes loading state into variant navigation. |
| src/products/components/ProductVariantNavigation/components/ProductVariantItem.tsx | Adds scrollIntoView behavior for the active variant via a ref callback so it’s visible in long lists. |
| src/products/components/ProductVariantNavigation/ProductVariantNavigation.tsx | Redesigns variant navigation: toolbar button moved to header, scrollable column with skeleton loading state, and adjusts how new-variant placeholder is shown. |
| src/products/components/ProductStocks/components/ProductStocksAssignWarehouses.tsx | Converts this component into a pure modal controlled by an open prop, adds Placeholder when no warehouses are available, and removes the internal “Assign warehouses” button. |
| src/products/components/ProductStocks/ProductStocks.tsx | Moves the “Assign Warehouses” button into the stocks card header, uses the new modal API, and moves stock table into ResponsiveTable. |
| src/products/components/ProductListTiles/ProductListTiles.tsx | Replaces TablePaginationWithContext wrapper with DatagridPagination in the tiles view. |
| src/products/components/ProductListDatagrid/ProductListDatagrid.tsx | Switches datagrid footer pagination to DatagridPagination. |
| src/productTypes/components/ProductTypeVariantAttributes/ProductTypeVariantAttributes.tsx | Uses ResponsiveTable + Placeholder for empty state and shared tableStyles.colAction instead of local action column styles. |
| src/productTypes/components/ProductTypeListPage/ProductTypeListPage.tsx | Wraps ProductTypeList in DashboardCard.Content instead of placing it directly in the card. |
| src/productTypes/components/ProductTypeList/ProductTypeList.tsx | Moves pagination into ResponsiveTable’s footer and uses named ResponsiveTable. |
| src/productTypes/components/ProductTypeAttributes/ProductTypeAttributes.tsx | Aligns with variant attributes: ResponsiveTable + Placeholder and shared action column styling. |
| src/permissionGroups/components/PermissionGroupMemberList/PermissionGroupMemberList.tsx | Introduces loading and empty (Placeholder) states for members and moves the table into DashboardCard.Content. |
| src/permissionGroups/components/PermissionGroupListDatagrid/PermissionGroupListDatagrid.tsx | Replaces table-based pagination footer with DatagridPagination. |
| src/permissionGroups/components/AssignMembersDialog/AssignMembersDialog.tsx | Switches to named ResponsiveTable. |
| src/orders/components/OrderTransactionRefundPage/components/OrderTransactionRefundSummary/OrderTransactionSummary.tsx | Adds a border around the refund summary “amount” box for better visual separation. |
| src/orders/components/OrderTransactionRefundPage/OrderTransactionRefundPage.tsx | Tweaks helper text sizes and colors in refund reason settings links for consistency. |
| src/orders/components/OrderProductAddDialog/styles.ts | Removes left padding overrides to align with new global table cell padding. |
| src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx | Updates import to named ResponsiveTable. |
| src/orders/components/OrderListDatagrid/OrderListDatagrid.tsx | Uses DatagridPagination for orders list footer. |
| src/orders/components/OrderInvoiceList/OrderInvoiceList.tsx | Switches to named ResponsiveTable. |
| src/orders/components/OrderFulfillStockExceededDialog/OrderFulfillStockExceededDialog.tsx | Updates import to named ResponsiveTable. |
| src/orders/components/OrderFulfillPage/OrderFulfillPage.tsx | Wraps fulfill lines table in DashboardCard.Content and uses named ResponsiveTable. |
| src/orders/components/OrderDraftListDatagrid/OrderDraftListDatagrid.tsx | Uses DatagridPagination for drafts list pagination. |
| src/modeling/components/PageListDatagrid/PageListDatagrid.tsx | Replaces TablePaginationWithContext with DatagridPagination in the modeling pages list. |
| src/modelTypes/components/PageTypeListPage/PageTypeListPage.tsx | Moves search into PageTypeList’s search prop and removes the outer DashboardCard. |
| src/modelTypes/components/PageTypeList/PageTypeList.tsx | Adds optional search config, moves pagination into ResponsiveTable’s footer, and keeps table body logic unchanged. |
| src/modelTypes/components/PageTypeAttributes/PageTypeAttributes.tsx | Adds loading and empty states with Skeleton/Placeholder and uses ResponsiveTable + tableStyles.colAction. |
| src/index.css | Adds global overrides for legacy MuiSelect row-number select styling used by pagination. |
| src/icons/Translations.tsx | Adjusts translations icon size and sets an explicit viewBox to match other icons. |
| src/graphql/types.generated.ts | Adds totalCount to the PageTypeListQuery type. |
| src/graphql/hooks.generated.ts | Updates the PageTypeList query to request totalCount. |
| src/giftCards/GiftCardsList/GiftCardsListDatagrid/GiftCardsListDatagrid.tsx | Wraps TablePagination in DatagridPagination for consistent padding in the gift cards list. |
| src/extensions/views/EditCustomExtension/components/WebhooksList/styles.ts | Drops left padding override for the name column to align with new table defaults. |
| src/extensions/views/EditCustomExtension/components/WebhooksList/WebhooksList.tsx | Uses named ResponsiveTable and puts the table inside DashboardCard.Content. |
| src/extensions/views/EditCustomExtension/components/CustomExtensionTokens/CustomExtensionTokens.tsx | Same ResponsiveTable/content adjustments for custom extension tokens, plus removal of “Actions” header label. |
| src/discounts/components/VoucherValue/styles.ts | Simplifies voucher value styles and removes left padding and container margin hacks. |
| src/discounts/components/VoucherValue/VoucherValue.tsx | Uses Placeholder for “no channels” and ResponsiveTable for per-channel values. |
| src/discounts/components/VoucherRequirements/styles.ts | Similar style simplifications for voucher requirements (no left padding, adjusted price cell padding). |
| src/discounts/components/VoucherRequirements/VoucherRequirements.tsx | Adds Placeholder for missing channels and uses ResponsiveTable for requirement per channel. |
| src/discounts/components/VoucherListDatagrid/VoucherListDatagrid.tsx | Switches to DatagridPagination in the vouchers list. |
| src/discounts/components/VoucherCodesDatagrid/VoucherCodesDatagrid.tsx | Same DatagridPagination usage for voucher codes list. |
| src/discounts/components/DiscountVariants/styles.ts | Removes redundant padding-right adjustments for the actions column. |
| src/discounts/components/DiscountVariants/DiscountVariants.tsx | Wraps in DashboardCard.Content, adds loading/empty states and uses ResponsiveTable footer pagination. |
| src/discounts/components/DiscountProducts/styles.ts | Removes left padding override for product name in discount products. |
| src/discounts/components/DiscountProducts/DiscountProducts.tsx | Similar pattern to variants: adds DashboardCard.Content, loading/empty states and integrates ResponsiveTable footer pagination. |
| src/discounts/components/DiscountListDatagrid/DiscountListDatagrid.tsx | Converts discount list pagination to DatagridPagination. |
| src/discounts/components/DiscountCountrySelectDialog/styles.ts | Removes checkbox cell left padding override. |
| src/discounts/components/DiscountCountrySelectDialog/DiscountCountrySelectDialog.tsx | Switches to named ResponsiveTable. |
| src/discounts/components/DiscountCollections/DiscountCollections.tsx | Wraps in DashboardCard.Content, adds Placeholder for empty and uses ResponsiveTable with footer pagination. |
| src/discounts/components/DiscountCategories/DiscountCategories.tsx | Same refactor for discount categories table. |
| src/customers/components/CustomerOrders/CustomerOrders.tsx | Moves orders table into DashboardCard.Content, adds loading/empty placeholder handling and uses named ResponsiveTable. |
| src/customers/components/CustomerListDatagrid/CustomerListDatagrid.tsx | Switches customer list pagination to DatagridPagination. |
| src/components/TablePagination/index.ts | Re-exports DatagridPagination from the pagination barrel. |
| src/components/TablePagination/TablePagination.tsx | Extends pagination API to support both settings-based and direct row-number pagination, and to render either wrapped or inline (for table footers). |
| src/components/TablePagination/DatagridPagination.tsx | Introduces a DatagridPagination wrapper that adds consistent horizontal padding around pagination content (see note below for a bug). |
| src/components/TableHead/TableHead.tsx | Simplifies header cell padding/styling and toolbar layout for selected-row toolbars. |
| src/components/SortableTable/SortableHandle.tsx | Tightens drag handle padding and width to better fit new table layouts. |
| src/components/Savebar/SavebarActionButtons.tsx | Enhances Savebar.ConfirmButton to support optional tooltips on disabled state, wrapping the button in a Tooltip when appropriate. |
| src/components/ResponsiveTable/index.ts | Changes exports to named ResponsiveTable and tableStyles. |
| src/components/ResponsiveTable/ResponsiveTable.tsx | Reimplements ResponsiveTable as a styled wrapper with optional search bar, a “no results” state, and a footer slot, plus shared action column styles. |
| src/components/ResponsiveTable/ResponsiveTable.module.css | Provides layout, header, padding, and column styles for ResponsiveTable. |
| src/components/ResponsiveTable/AGENTS.md | Documents usage guidelines for ResponsiveTable, including loading/empty handling patterns. |
| src/components/Placeholder/index.ts | Adds barrel export for the new Placeholder component. |
| src/components/Placeholder/Placeholder.tsx | Simple bordered placeholder block for empty states. |
| src/components/Grid/Grid.tsx | Makes the left column in variant="inverted" grids sticky at the top of the viewport for better side-by-side navigation ergonomics. |
| src/components/CountryList/CountryList.tsx | Refactors the country list into DashboardCard.Content + ResponsiveTable and uses Placeholder when there are no countries. |
| src/components/AssignVariantDialog/styles.ts | Drops table padding overrides in favor of global table styling. |
| src/components/AssignVariantDialog/AssignVariantDialogSingle.tsx | Uses named ResponsiveTable. |
| src/components/AssignVariantDialog/AssignVariantDialogMulti.tsx | Uses named ResponsiveTable. |
| src/components/AssignProductDialog/styles.ts | Removes left padding overrides for avatars and name columns. |
| src/components/AssignProductDialog/AssignProductDialogSingle.tsx | Uses named ResponsiveTable. |
| src/components/AssignProductDialog/AssignProductDialogMulti.tsx | Uses named ResponsiveTable. |
| src/components/AssignContainerDialog/styles.ts | Simplifies avatar and checkbox-cell styles to align with shared table padding. |
| src/components/AssignContainerDialog/AssignContainerDialogSingle.tsx | Uses named ResponsiveTable. |
| src/components/AssignContainerDialog/AssignContainerDialogMulti.tsx | Uses named ResponsiveTable. |
| src/components/AssignAttributeDialog/AssignAttributeDialog.tsx | Uses named ResponsiveTable. |
| src/components/AppLayout/TopNav/Root.tsx | Adds spacing between title and right-side controls and keeps flex behavior for the channel picker. |
| src/components/AppLayout/AppChannelSelect.tsx | Adjusts channel selector width/height and alignment for better fit in the top nav. |
| src/collections/components/CollectionListDatagrid/CollectionListDatagrid.tsx | Uses DatagridPagination for collection list. |
| src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx | Adds a CardSpacer after the title field for nicer spacing. |
| src/channels/pages/ChannelsListPage/styles.ts | Drops extra padding-left on channel name column to align with shared table styles. |
| src/channels/pages/ChannelsListPage/ChannelsListPage.tsx | Moves channel table into DashboardCard.Content with ResponsiveTable and simplifies the header actions column. |
| src/categories/components/CategoryProductListDatagrid/CategoryProductListDatagrid.tsx | Uses DatagridPagination for category product lists. |
| src/categories/components/CategoryListDatagrid/CategoryListDatagrid.tsx | Same pagination update for category lists. |
| src/attributes/components/AttributeValues/AttributeValues.tsx | Refactors attribute values list to use DashboardCard.Content, ResponsiveTable, and Placeholder for empty values, and switches pagination to a footer TablePagination. |
| src/attributes/components/AttributeListDatagrid/AttributeListDatagrid.tsx | Uses DatagridPagination for attribute list. |
| locale/defaultMessages.json | Adds new message strings for save-button tooltip and “no warehouses available to add.” |
| AGENTS.md | Extends repo-level docs with UI design guidelines for long lists and empty/loading states. |
| .changeset/bumpy-jobs-clean.md | Updates the changeset summary to reflect the dashboard table design unification work. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 130 out of 130 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <FormattedMessage | ||
| id="j/vV0n" | ||
| defaultMessage="Channel Name" | ||
| description="channel name" |
There was a problem hiding this comment.
suggestion: This is pretty self explanatory, we don't need duplication in the description :)
if we already have such string already in dashboard we might re-use it
| description="channel name" |
| ### UI Design Guidelines | ||
|
|
||
| **Before redesigning any component that displays a list, ask: "What happens with 50+ items?"** | ||
|
|
||
| If the list could be long: | ||
|
|
||
| - Add scrollable container with `max-height` | ||
| - Keep headers outside the scroll area | ||
| - Auto-scroll to active item on load | ||
|
|
||
| Other considerations: | ||
|
|
||
| - Loading states: Show skeletons | ||
| - Empty states: Handle zero items gracefully |
There was a problem hiding this comment.
question: maybe in general we should migrate to skills for specific tasks like this one (writing / refactoring components that display list) - I think it works better in general: agents.md tends to get ignored + we pollute our context less.
There was a problem hiding this comment.
Yes - 100%. I internally use both rules and skills. Just had no time to pull it together yet as I initially did for our storefront on the Paper PR/branch.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 131 out of 132 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 132 out of 132 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 133 out of 133 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 133 out of 133 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 132 out of 132 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const [searchValue, setSearchValue] = useState(search?.initialValue ?? ""); | ||
|
|
||
| const isSearchActive = searchValue.length > 0; | ||
| const showFilteredEmptyState = isSearchActive && filteredItemsCount === 0; | ||
|
|
||
| const debouncedOnSearchChange = useDebounce((value: string) => { | ||
| search?.onSearchChange?.(value); | ||
| }, 300); | ||
|
|
||
| const handleSearchChange = (e: ChangeEvent<HTMLInputElement>) => { | ||
| const value = e.target.value; | ||
|
|
||
| setSearchValue(value); | ||
|
|
There was a problem hiding this comment.
The ResponsiveTable search state currently uses initialValue only for the initial useState value and never reacts to later prop changes, so if the parent updates search.initialValue (for example when switching filter presets or syncing with URL query params), the input will continue showing the old query. To keep behavior consistent with the previous SearchInput component (which synced its internal state when initialSearch changed), the searchValue state here should be updated in a useEffect when search?.initialValue changes.