From 8b1a847da94297eb3c3269836368e73bfb86082c Mon Sep 17 00:00:00 2001 From: samarthsinh2660 Date: Tue, 20 Jan 2026 11:54:51 +0530 Subject: [PATCH] fix(core-components): fix Table layout when filters and title are used together The TableToolbar component was using the same CSS class for both the root container and the nested filter controls container, causing layout conflicts when both filters and title props were present. Changes: - Added dedicated filterControls CSS class for the filter icon/text - Added flex-wrap: wrap to root container for better responsiveness - Fixed nested Box using the same class issue Fixes #32120 Signed-off-by: samarthsinh2660 --- .changeset/fix-table-filters-title-layout.md | 5 +++++ packages/core-components/report-alpha.api.md | 4 ++-- packages/core-components/report.api.md | 2 +- .../src/components/Table/Table.test.tsx | 17 +++++++++++++++++ .../src/components/Table/Table.tsx | 8 ++++++-- 5 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 .changeset/fix-table-filters-title-layout.md diff --git a/.changeset/fix-table-filters-title-layout.md b/.changeset/fix-table-filters-title-layout.md new file mode 100644 index 0000000000..cfbd72fa90 --- /dev/null +++ b/.changeset/fix-table-filters-title-layout.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Fixed Table component layout when both `filters` and `title` props are used together. The filter controls now use a dedicated CSS class (`filterControls`) instead of incorrectly reusing the root container class. diff --git a/packages/core-components/report-alpha.api.md b/packages/core-components/report-alpha.api.md index e6a54e32a4..97b3043283 100644 --- a/packages/core-components/report-alpha.api.md +++ b/packages/core-components/report-alpha.api.md @@ -15,8 +15,8 @@ export const coreComponentsTranslationRef: TranslationRef< readonly 'table.body.emptyDataSourceMessage': 'No records to display'; readonly 'table.header.actions': 'Actions'; readonly 'table.toolbar.search': 'Filter'; - readonly 'table.pagination.labelDisplayedRows': '{from}-{to} of {count}'; readonly 'table.pagination.firstTooltip': 'First Page'; + readonly 'table.pagination.labelDisplayedRows': '{from}-{to} of {count}'; readonly 'table.pagination.labelRowsSelect': 'rows'; readonly 'table.pagination.lastTooltip': 'Last Page'; readonly 'table.pagination.nextTooltip': 'Next Page'; @@ -24,10 +24,10 @@ export const coreComponentsTranslationRef: TranslationRef< readonly 'signIn.title': 'Sign In'; readonly 'signIn.loginFailed': 'Login failed'; readonly 'signIn.customProvider.title': 'Custom User'; + readonly 'signIn.customProvider.continue': 'Continue'; readonly 'signIn.customProvider.subtitle': 'Enter your own User ID and credentials.\n This selection will not be stored.'; readonly 'signIn.customProvider.userId': 'User ID'; readonly 'signIn.customProvider.tokenInvalid': 'Token is not a valid OpenID Connect JWT Token'; - readonly 'signIn.customProvider.continue': 'Continue'; readonly 'signIn.customProvider.idToken': 'ID Token (optional)'; readonly 'signIn.guestProvider.title': 'Guest'; readonly 'signIn.guestProvider.enter': 'Enter'; diff --git a/packages/core-components/report.api.md b/packages/core-components/report.api.md index 0cd8a7d866..946fd13c74 100644 --- a/packages/core-components/report.api.md +++ b/packages/core-components/report.api.md @@ -512,7 +512,7 @@ export function FeatureCalloutCircular( ): JSX_2.Element; // @public (undocumented) -export type FiltersContainerClassKey = 'root' | 'title'; +export type FiltersContainerClassKey = 'root' | 'filterControls' | 'title'; // @public export function Gauge(props: GaugeProps): JSX_2.Element; diff --git a/packages/core-components/src/components/Table/Table.test.tsx b/packages/core-components/src/components/Table/Table.test.tsx index dab5a462c2..075dbcc0cd 100644 --- a/packages/core-components/src/components/Table/Table.test.tsx +++ b/packages/core-components/src/components/Table/Table.test.tsx @@ -209,6 +209,23 @@ describe('', () => { expect(rendered.getByText('subtitle')).toBeInTheDocument(); }); + it('renders with both title and filters without layout issues', async () => { + const rendered = await renderInTestApp( +
, + ); + expect(rendered.getByText('My Table')).toBeInTheDocument(); + expect(rendered.getByText('Filters (0)')).toBeInTheDocument(); + }); + it('renders custom empty component if empty', async () => { const rendered = await renderInTestApp(
({ @@ -188,6 +188,10 @@ const useFilterStyles = makeStyles( justifyContent: 'space-between', flexWrap: 'wrap', }, + filterControls: { + display: 'flex', + alignItems: 'center', + }, title: { fontWeight: theme.typography.fontWeightBold, fontSize: 18, @@ -316,7 +320,7 @@ export function TableToolbar(toolbarProps: { if (hasFilters) { return ( - +