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 <rajuvala80@gmail.com>
This commit is contained in:
samarthsinh2660
2026-01-20 11:54:51 +05:30
parent bd8ed8badd
commit 8b1a847da9
5 changed files with 31 additions and 5 deletions
@@ -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.
+2 -2
View File
@@ -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';
+1 -1
View File
@@ -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;
@@ -209,6 +209,23 @@ describe('<Table />', () => {
expect(rendered.getByText('subtitle')).toBeInTheDocument();
});
it('renders with both title and filters without layout issues', async () => {
const rendered = await renderInTestApp(
<Table
title="My Table"
filters={[
{
column: column1.title,
type: 'select',
},
]}
{...minProps}
/>,
);
expect(rendered.getByText('My Table')).toBeInTheDocument();
expect(rendered.getByText('Filters (0)')).toBeInTheDocument();
});
it('renders custom empty component if empty', async () => {
const rendered = await renderInTestApp(
<Table
@@ -178,7 +178,7 @@ const StyledMTableToolbar = withStyles(
)(MTableToolbar);
/** @public */
export type FiltersContainerClassKey = 'root' | 'title';
export type FiltersContainerClassKey = 'root' | 'filterControls' | 'title';
const useFilterStyles = makeStyles(
theme => ({
@@ -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 (
<Box className={filtersClasses.root}>
<Box className={filtersClasses.root}>
<Box className={filtersClasses.filterControls}>
<IconButton onClick={toggleFilters} aria-label="filter list">
<FilterList />
</IconButton>