Compare commits

...
Author SHA1 Message Date
sadpandajoeandClaude Sonnet 5 65a7dc8478 fix(dashboard): address review feedback on metadata-bar overlap tests
Drop the storybook-driven Playwright layout spec and its dedicated
config: it never ran in CI (playwright:storybook wasn't referenced from
any .github/ workflow), and there's no other storybook-driven Playwright
pattern in this repo to justify the added maintenance surface for a
1-line CSS change. The jsdom regression test in PageHeaderWithActions
already guards the CSS property directly.

Render the certified badge and stand-ins for the header's other real
title-panel siblings (refresh/auto-refresh/published-status) in the
DashboardHeader story so it matches production's title-panel composition
more closely; the real components live in src/dashboard and can't be
imported into this core-level story without inverting the package
dependency direction.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 22:21:35 +00:00
sadpandajoeandClaude Sonnet 5 cafb9b6eb3 fix(dashboard): clip header metadata bar instead of overlapping actions menu
On the dashboard page header, narrowing the browser window shrinks the
editable title down to nothing, but the certification/fave-star badges and
metadata bar (last modified / owner info) had no way to shrink or clip. Once
the title fully collapsed, that cluster rendered outside its allotted flex
space and visually overlapped the kebab-menu/action buttons instead of
collapsing.

Add overflow: hidden to the title panel's badges/metadata-bar wrapper so it
clips along with the title as space runs out.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 01:15:40 +00:00
3 changed files with 125 additions and 2 deletions
@@ -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: {},
};
@@ -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/);
});
@@ -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 {