This is an automated email from the ASF dual-hosted git repository.
sadpandajoe pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new 7382ee0bfec fix(dashboard): prevent header metadata bar from
overlapping action buttons at narrow widths (#43845)
7382ee0bfec is described below
commit 7382ee0bfecbf31da1e13d459066335fd425f017
Author: Joe Li <[email protected]>
AuthorDate: Tue Sep 8 09:34:09 2026 -0700
fix(dashboard): prevent header metadata bar from overlapping action buttons
at narrow widths (#43845)
Co-authored-by: Claude Sonnet 5 <[email protected]>
---
.../PageHeaderWithActions.stories.tsx | 102 +++++++++++++++++++++
.../PageHeaderWithActions.test.tsx | 19 +++-
.../src/components/PageHeaderWithActions/index.tsx | 6 +-
3 files changed, 125 insertions(+), 2 deletions(-)
diff --git
a/superset-frontend/packages/superset-ui-core/src/components/PageHeaderWithActions/PageHeaderWithActions.stories.tsx
b/superset-frontend/packages/superset-ui-core/src/components/PageHeaderWithActions/PageHeaderWithActions.stories.tsx
new file mode 100644
index 00000000000..50d84268257
--- /dev/null
+++
b/superset-frontend/packages/superset-ui-core/src/components/PageHeaderWithActions/PageHeaderWithActions.stories.tsx
@@ -0,0 +1,102 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { Icons } from '../Icons';
+import { Button } from '../Button';
+import MetadataBar, { MetadataType } from '../MetadataBar';
+import { Menu } from '../Menu';
+import { PageHeaderWithActions, PageHeaderWithActionsProps } from '.';
+
+export default {
+ title: 'Design System/Components/PageHeaderWithActions',
+ component: PageHeaderWithActions,
+ parameters: {
+ layout: 'fullscreen',
+ docs: {
+ description: {
+ component:
+ 'Header used on entity pages (e.g. the dashboard page) combining an
editable title with badges, a metadata bar, and page-level actions.',
+ },
+ },
+ },
+};
+
+// Mirrors src/dashboard/components/Header's real composition: an editable
+// title, the certified badge, and a titlePanelAdditionalItems cluster of a
+// refresh button, an auto-refresh indicator, a published-status toggle, and
+// a MetadataBar (Last Modified + Editor) -- the same items the real
+// dashboard header packs into that space -- so this story reproduces the
+// header's real narrow-viewport layout behavior, not just the isolated
+// MetadataBar. The real RefreshButton/AutoRefreshIndicator/PublishedStatus
+// components live in src/dashboard and depend on this package, so they
+// can't be imported here without inverting that dependency; these are
+// same-sized stand-ins built from core components instead.
+export const DashboardHeader = (args: PageHeaderWithActionsProps) => (
+ <PageHeaderWithActions {...args} />
+);
+
+DashboardHeader.args = {
+ editableTitleProps: {
+ title: 'Q3 Executive Revenue and Growth Overview Dashboard',
+ placeholder: 'Add the name of the dashboard',
+ onSave: () => {},
+ canEdit: true,
+ label: 'Dashboard title',
+ },
+ showTitlePanelItems: true,
+ certificatiedBadgeProps: {
+ certifiedBy: 'Jane Doe',
+ details: 'Certified by the BI team',
+ },
+ showFaveStar: true,
+ faveStarProps: { itemId: 1, saveFaveStar: () => {}, isStarred: false },
+ titlePanelAdditionalItems: [
+ <Button key="refresh-button" buttonStyle="link" tooltip="Refresh
dashboard">
+ <Icons.ReloadOutlined iconSize="l" />
+ </Button>,
+ <Icons.SyncOutlined key="auto-refresh-indicator" iconSize="l" />,
+ <Button key="published-status" buttonStyle="link">
+ Published
+ </Button>,
+ <MetadataBar
+ key="metadata-bar"
+ tooltipPlacement="bottom"
+ items={[
+ {
+ type: MetadataType.LastModified,
+ value: '2 hours ago',
+ modifiedBy: 'Jane Doe',
+ },
+ {
+ type: MetadataType.Editor,
+ createdBy: 'Jane Doe',
+ editors: ['Jane Doe', 'John Smith'],
+ createdOn: 'a week ago',
+ },
+ ]}
+ />,
+ ],
+ rightPanelAdditionalItems: <button type="button">Edit dashboard</button>,
+ additionalActionsMenu: (
+ <Menu
+ items={[{ label: 'Edit properties', key: '1' }]}
+ data-test="additional-actions-menu"
+ />
+ ),
+ menuDropdownProps: {},
+};
diff --git
a/superset-frontend/packages/superset-ui-core/src/components/PageHeaderWithActions/PageHeaderWithActions.test.tsx
b/superset-frontend/packages/superset-ui-core/src/components/PageHeaderWithActions/PageHeaderWithActions.test.tsx
index 2a3d17c9a55..0f90c99a675 100644
---
a/superset-frontend/packages/superset-ui-core/src/components/PageHeaderWithActions/PageHeaderWithActions.test.tsx
+++
b/superset-frontend/packages/superset-ui-core/src/components/PageHeaderWithActions/PageHeaderWithActions.test.tsx
@@ -18,7 +18,12 @@
*/
import { render, screen, userEvent } from '@superset-ui/core/spec';
-import { PageHeaderWithActions, PageHeaderWithActionsProps } from './index';
+import { supersetTheme } from '@apache-superset/core/theme';
+import {
+ buttonsStyles,
+ PageHeaderWithActions,
+ PageHeaderWithActionsProps,
+} from './index';
import { Menu } from '../Menu';
const defaultProps: PageHeaderWithActionsProps = {
@@ -54,3 +59,15 @@ test('Renders', async () => {
await userEvent.click(screen.getByLabelText('Menu actions trigger'));
expect(defaultProps.menuDropdownProps.onOpenChange).toHaveBeenCalled();
});
+
+test('clips the title panel buttons/metadata cluster instead of letting it
overflow into the actions menu', () => {
+ // jsdom doesn't compute real flexbox layout, so it can't verify the
+ // overlap itself is fixed; this guards the underlying CSS from
+ // regressing instead. Without `overflow: hidden`, this wrapper's
+ // automatic flex minimum size is based on its content rather than 0, so
+ // it refuses to shrink -- forcing the title to absorb all the space
+ // pressure until the cluster's content renders outside its box and
+ // overlaps the actions menu once the title has fully collapsed.
+ const { styles } = buttonsStyles(supersetTheme);
+ expect(styles).toMatch(/overflow:\s*hidden/);
+});
diff --git
a/superset-frontend/packages/superset-ui-core/src/components/PageHeaderWithActions/index.tsx
b/superset-frontend/packages/superset-ui-core/src/components/PageHeaderWithActions/index.tsx
index cd1ef78f834..7b25c8c858d 100644
---
a/superset-frontend/packages/superset-ui-core/src/components/PageHeaderWithActions/index.tsx
+++
b/superset-frontend/packages/superset-ui-core/src/components/PageHeaderWithActions/index.tsx
@@ -99,9 +99,13 @@ const headerStyles = (theme: SupersetTheme) => css`
}
`;
-const buttonsStyles = (theme: SupersetTheme) => css`
+// Exported only so PageHeaderWithActions.test.tsx can assert on the
+// `overflow: hidden` declaration directly; not part of the component's
+// public API.
+export const buttonsStyles = (theme: SupersetTheme) => css`
display: flex;
align-items: center;
+ overflow: hidden;
padding-left: ${theme.sizeUnit * 2}px;
& .anticon-star {