Polish dashboard tile styling and header layout#2592
Conversation
Give dashboard tiles white surface backgrounds with a border on a subtly muted page background, a modern dotted resize handle, and a compact, consistent header. Tile actions are consolidated into a right-aligned kebab menu (alongside the alert bell) that renders after each chart's own controls, and a full-bleed separator gives every tile a consistent header strip. Table tiles now use the default (non-muted) table variant so they blend into the white card. E2E tests and page objects updated for the kebab menu. Co-authored-by: Cursor <cursoragent@cursor.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: 648ea53 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Greptile SummaryVisual polish pass on dashboard tiles: tiles become white
Confidence Score: 5/5Safe to merge — changes are purely visual/structural with no data-path or auth-path impact. All logic changes (kebab menu consolidation, context-based card header, new CSS tokens) are self-contained within the dashboard tile rendering path. The React 19 context API usage is valid given the project is on React ^19.2.3. The hovered state is retained for the tile hover-indicator pill, so nothing is orphaned. E2E helpers are correctly wired through openTileActionsMenu. No data mutations, API calls, or auth checks are modified. ChartContainer.tsx — the full-bleed negative-margin technique couples HEADER_SPACING to Bootstrap's px-2 value; worth a second glance if spacing tokens are ever customised. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Tile renders] --> B[ChartContainerCardHeaderProvider\nsets context = true]
B --> C[renderChartContent]
C --> D{Chart type?}
D -->|Time/Table/Number/Pie/Heatmap| E[Chart component\ne.g. DBTimeChart]
D -->|Search| F[ChartContainer directly\ntoolbarItems = toolbar]
E --> G[ChartContainer\ncardHeader = true from context]
F --> G
G --> H[Resets context to false\nfor nested containers]
H --> I{showHeader?}
I -->|title or toolbarItems| J[Card-style header\nfull-bleed separator\nkebab menu on right]
I -->|neither| K[No header rendered]
J --> L[Chart content]
K --> L
M[Fullscreen modal portal] --> N[renderChartContent\noutside Provider]
N --> O[ChartContainer\ncardHeader = false default]
O --> P[Plain inline header\nno separator]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[Tile renders] --> B[ChartContainerCardHeaderProvider\nsets context = true]
B --> C[renderChartContent]
C --> D{Chart type?}
D -->|Time/Table/Number/Pie/Heatmap| E[Chart component\ne.g. DBTimeChart]
D -->|Search| F[ChartContainer directly\ntoolbarItems = toolbar]
E --> G[ChartContainer\ncardHeader = true from context]
F --> G
G --> H[Resets context to false\nfor nested containers]
H --> I{showHeader?}
I -->|title or toolbarItems| J[Card-style header\nfull-bleed separator\nkebab menu on right]
I -->|neither| K[No header rendered]
J --> L[Chart content]
K --> L
M[Fullscreen modal portal] --> N[renderChartContent\noutside Provider]
N --> O[ChartContainer\ncardHeader = false default]
O --> P[Plain inline header\nno separator]
Reviews (3): Last reviewed commit: "test(app): update dashboard E2E for keba..." | Re-trigger Greptile |
| async openTileActionsMenu(tileIndex: number) { | ||
| await this.hoverOverTile(tileIndex); | ||
| await this.page | ||
| .locator('[data-testid^="tile-actions-button-"]') | ||
| .nth(tileIndex) | ||
| .click(); | ||
| } |
There was a problem hiding this comment.
Unnecessary hover step in
openTileActionsMenu
The hoverOverTile call is a leftover from when the kebab button was only revealed on hover (visibility: hidden toggled by hovered state). Now that the actions button is always visible in the DOM (the visibility guard was removed from hoverToolbar), the hover step adds latency to every call to editTile, duplicateTile, deleteTile, and openFullscreenForTile without serving any functional purpose.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
E2E Test Results✅ All tests passed • 225 passed • 3 skipped • 1483s
Tests ran across 4 shards in parallel. |
…oken - Move tile actions into a right-aligned kebab (after chart controls) and slim the tile header height. - Use IconBellPlus for the "add alert" affordance instead of an overlaid "+" badge that was invisible on the light header. - Group headers: always-visible drag/add/kebab controls, bg-body header with a sunken (recessed) tile-area body and padding around nested tiles. - Remove the redundant Mantine tab-list underline on dashboard group tabs. - Rename --color-bg-muted-subtle -> --color-bg-sunken (and .bg-sunken) with explanatory comments, since it's a recessed backdrop behind bg-body cards. Co-authored-by: Cursor <cursoragent@cursor.com>
Tile edit/duplicate/delete moved into the actions (kebab) menu, so the "verify tile interactions" steps now open the menu before asserting those items are visible, while the alert bell is checked directly in the header. Co-authored-by: Cursor <cursoragent@cursor.com>
Summary
A visual-polish pass on dashboards to make tiles read as distinct cards and give groups a cleaner, more consistent layout.
Tiles
bg-body(white in light mode) background with a border, sitting on a recessed "sunken" page background so they read as elevated cards.⋮menu rendered as a toolbar suffix, so it sits at the far right after each chart's own controls (display switcher, granularity). The alert affordance stays alongside it and is always visible.IconBellPluswhen no alert is configured (reads clearly on the light header) andIconBell+ a colored status indicator when an alert exists.Groups
⋮overflow controls are always visible in the group header (no longer hover-only).bg-body; the tile area below uses the sunken background with padding around the nested tiles.::beforeunderline, since the group border + header/body color split already separate the tab row from the content (the active-tab indicator is preserved).Theming
--color-bg-muted-subtle→--color-bg-sunken(and.bg-muted-subtle→.bg-sunken) with explanatory comments, since the token is a recessed backdrop that sits belowbg-bodycards rather than a "subtler muted".Tests
Test plan
bg-bodycards on a sunken page background (light + dark).bell +with no alert and a status dot when an alert exists; both visible on light/dark headers.bg-body, tile area is sunken with padding; no underline under the group tabs (active-tab indicator still shows).make dev-e2e FILE=dashboard