Skip to content

Commit b0135cb

Browse files
Replace Add New Tile button with unified Add dropdown (#1956)
## Summary - Replace the "Add New Tile" button and overflow "Add Section" menu item with a unified "Add" dropdown at the bottom of the dashboard - Dropdown contains "New Tile" and "New Section" — creative actions only - "Import Dashboard" stays in the overflow menu alongside Export, Delete, and other management actions - Follows the Grafana/Datadog pattern of a single entry point for adding content, which scales to future container types (tabs, groups) ## Test plan - [x] Click "Add" button at bottom of dashboard → dropdown opens upward with "New Tile" and "New Section" - [x] Click "New Tile" → tile editor opens (same as before) - [x] Click "New Section" → new section appears on dashboard - [x] Overflow menu still contains "Import Dashboard" with contextual label - [x] E2E tests pass (updated page object for two-click dropdown flow) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: peter-leonov-ch <209667683+peter-leonov-ch@users.noreply.github.com>
1 parent 89a08e9 commit b0135cb

3 files changed

Lines changed: 62 additions & 27 deletions

File tree

packages/app/src/DBDashboardPage.tsx

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import { notifications } from '@mantine/notifications';
6060
import {
6161
IconArrowsMaximize,
6262
IconBell,
63+
IconChartBar,
6364
IconCopy,
6465
IconDeviceFloppy,
6566
IconDotsVertical,
@@ -68,6 +69,7 @@ import {
6869
IconLayoutList,
6970
IconPencil,
7071
IconPlayerPlay,
72+
IconPlus,
7173
IconRefresh,
7274
IconTags,
7375
IconTrash,
@@ -1589,13 +1591,6 @@ function DBDashboardPage({ presetConfig }: { presetConfig?: Dashboard }) {
15891591
>
15901592
{hasTiles ? 'Import New Dashboard' : 'Import Dashboard'}
15911593
</Menu.Item>
1592-
<Menu.Item
1593-
data-testid="add-new-section-button"
1594-
leftSection={<IconLayoutList size={16} />}
1595-
onClick={handleAddSection}
1596-
>
1597-
Add Section
1598-
</Menu.Item>
15991594
<Menu.Divider />
16001595
<Menu.Item
16011596
data-testid="save-default-query-filters-menu-item"
@@ -1795,16 +1790,36 @@ function DBDashboardPage({ presetConfig }: { presetConfig?: Dashboard }) {
17951790
</ErrorBoundary>
17961791
) : null}
17971792
</Box>
1798-
<Button
1799-
data-testid="add-new-tile-button"
1800-
variant={dashboard?.tiles.length === 0 ? 'primary' : 'secondary'}
1801-
mt="sm"
1802-
fw={400}
1803-
onClick={() => onAddTile()}
1804-
w="100%"
1805-
>
1806-
+ Add New Tile
1807-
</Button>
1793+
<Menu position="top" width={200}>
1794+
<Menu.Target>
1795+
<Button
1796+
data-testid="add-dropdown-button"
1797+
variant={dashboard?.tiles.length === 0 ? 'primary' : 'secondary'}
1798+
mt="sm"
1799+
fw={400}
1800+
w="100%"
1801+
leftSection={<IconPlus size={16} />}
1802+
>
1803+
Add
1804+
</Button>
1805+
</Menu.Target>
1806+
<Menu.Dropdown>
1807+
<Menu.Item
1808+
data-testid="add-new-tile-menu-item"
1809+
leftSection={<IconChartBar size={16} />}
1810+
onClick={() => onAddTile()}
1811+
>
1812+
New Tile
1813+
</Menu.Item>
1814+
<Menu.Item
1815+
data-testid="add-new-section-menu-item"
1816+
leftSection={<IconLayoutList size={16} />}
1817+
onClick={handleAddSection}
1818+
>
1819+
New Section
1820+
</Menu.Item>
1821+
</Menu.Dropdown>
1822+
</Menu>
18081823
<DashboardFiltersModal
18091824
opened={showFiltersModal}
18101825
onClose={() => setShowFiltersModal(false)}

packages/app/tests/e2e/features/dashboard.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ test.describe('Dashboard', { tag: ['@dashboard'] }, () => {
5050

5151
await test.step('Add a tile to the dashboard', async () => {
5252
// Open add tile modal
53-
await expect(dashboardPage.addNewTileButton).toBeVisible();
53+
await expect(dashboardPage.addButton).toBeVisible();
5454
await dashboardPage.addTile();
5555

5656
// Create chart using chart editor component
@@ -124,7 +124,7 @@ test.describe('Dashboard', { tag: ['@dashboard'] }, () => {
124124
});
125125

126126
await test.step('Add first tile to dashboard', async () => {
127-
await expect(dashboardPage.addNewTileButton).toBeVisible();
127+
await expect(dashboardPage.addButton).toBeVisible();
128128
await dashboardPage.addTile();
129129

130130
// Create basic chart
@@ -137,7 +137,7 @@ test.describe('Dashboard', { tag: ['@dashboard'] }, () => {
137137
});
138138

139139
await test.step('Add second tile with Demo Metrics', async () => {
140-
await expect(dashboardPage.addNewTileButton).toBeVisible();
140+
await expect(dashboardPage.addButton).toBeVisible();
141141
await dashboardPage.addTile();
142142

143143
// Select source and create chart with specific metric
@@ -297,7 +297,7 @@ test.describe('Dashboard', { tag: ['@dashboard'] }, () => {
297297
});
298298

299299
await test.step('create a Number type chart with alert', async () => {
300-
await expect(dashboardPage.addNewTileButton).toBeVisible();
300+
await expect(dashboardPage.addButton).toBeVisible();
301301
await dashboardPage.addTile();
302302

303303
await expect(dashboardPage.chartEditor.source).toBeVisible();

packages/app/tests/e2e/page-objects/DashboardPage.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ export class DashboardPage {
6262
readonly searchInput: Locator;
6363

6464
private readonly createDashboardButton: Locator;
65-
private readonly addTileButton: Locator;
65+
private readonly addDropdownButton: Locator;
66+
private readonly addTileMenuItem: Locator;
67+
private readonly addSectionMenuItem: Locator;
6668
private readonly dashboardNameHeading: Locator;
6769
private readonly searchSubmitButton: Locator;
6870
private readonly liveButton: Locator;
@@ -93,7 +95,15 @@ export class DashboardPage {
9395
this.createDashboardButton = page.locator(
9496
'[data-testid="create-dashboard-button"]',
9597
);
96-
this.addTileButton = page.locator('[data-testid="add-new-tile-button"]');
98+
this.addDropdownButton = page.locator(
99+
'[data-testid="add-dropdown-button"]',
100+
);
101+
this.addTileMenuItem = page.locator(
102+
'[data-testid="add-new-tile-menu-item"]',
103+
);
104+
this.addSectionMenuItem = page.locator(
105+
'[data-testid="add-new-section-menu-item"]',
106+
);
97107
this.searchInput = page.locator('[data-testid="search-input"]');
98108
this.searchSubmitButton = page.locator(
99109
'[data-testid="search-submit-button"]',
@@ -193,7 +203,16 @@ export class DashboardPage {
193203
* Add a new tile to the dashboard
194204
*/
195205
async addTile() {
196-
await this.addTileButton.click();
206+
await this.addDropdownButton.click();
207+
await this.addTileMenuItem.click();
208+
}
209+
210+
/**
211+
* Add a new section to the dashboard
212+
*/
213+
async addSection() {
214+
await this.addDropdownButton.click();
215+
await this.addSectionMenuItem.click();
197216
}
198217

199218
/**
@@ -210,7 +229,8 @@ export class DashboardPage {
210229
async openNewTileEditor() {
211230
await this.createDashboardButton.click();
212231
await this.page.waitForURL('**/dashboards**');
213-
await this.addTileButton.click();
232+
await this.addDropdownButton.click();
233+
await this.addTileMenuItem.click();
214234
await expect(this.chartEditor.nameInput).toBeVisible();
215235
await this.chartEditor.waitForDataToLoad();
216236
}
@@ -577,8 +597,8 @@ export class DashboardPage {
577597
return this.createDashboardButton;
578598
}
579599

580-
get addNewTileButton() {
581-
return this.addTileButton;
600+
get addButton() {
601+
return this.addDropdownButton;
582602
}
583603

584604
get dashboardName() {

0 commit comments

Comments
 (0)