Add a footer slot to GlDashboardPanel
What does this MR do?
Closes #3629 (closed)
This adds an optional footer slot to GlDashboardPanel, for content that belongs below the visualization, such as a link to a more detailed view.
Today the only place for that content is the #body slot, and the body container (gl-grow gl-overflow-y-auto) is the panel's scroll area. When the visualization fills the panel, as a chart with height="auto" does, anything placed after it in #body sits below the visible part of that area. GitLab's analytics dashboards needed such a link in gitlab-org/gitlab!253534 (merged) and work around the gap in extended_dashboard_panel.vue by splitting #body into a flex column with a scroll container of its own, with a TODO pointing at the issue.
What changes:
- The footer renders after the body container, as its sibling in the panel's
gl-flex gl-h-full gl-flex-colcolumn and before thealert-messageslot, in adivwithgl-mt-3 gl-shrink-0. The body container and its classes are unchanged, so it stays the scroll area and the footer stays visible. - The footer renders only when the slot is passed and the panel is not loading. A panel that does not pass it gets no new element, only the empty comment Vue leaves for a
v-if. - The wrapper is a
divrather than afooterelement, which is what GlModal's header and footer slots render by default since !5497 (merged). - The wrapper's classes and
data-testid="panel-footer"are the ones GitLab's workaround renders for its footer today. - Specs for the slot, the loading state and the layout, run under Vue 2 and Vue 3; a
WithFooterstory with its visual snapshot; aminorchangeset; and a short "Footer" paragraph under Code reference on the dashboard panel page.
One thing I left out on purpose: GitLab's workaround also makes its scroll container focusable while its content overflows. GlDashboardPanel's body container has no such handling today, with or without a footer, and this MR does not change that, so the slot stays purely additive. I'm happy to follow up on it if you want the panel to handle it.
@rcrespo3 asked for this slot in the issue, so I'd value their look when they're back. The new snapshot also needs a product designer's approval, since designers own tests/__image_snapshots__/.
How I tested it
- The four specs that need the slot (
renders the footer slot in the footer,renders the footer right after the body container, not inside it,keeps the footer from shrinking when the body overflows,renders the footer once loading finishes) fail with the component change removed, under Vue 2 and Vue 3, and all 52 specs ofdashboard_panel.spec.jspass with it, under both. - Dropping either half of the
v-if($scopedSlots.footeror!loading) fails a spec. - I built the test Storybook three ways, as the three
ui:visual*jobs do (yarn storybook:build:testwith Vue 2, withVUE_VERSION=3, and withVUE_VERSION=3 VUE_COMPILER_VERSION=2), and rantest-storybook --browsers firefoxon the dashboard panel stories insidemcr.microsoft.com/playwright:v1.63.0-jammy, the image of those jobs. The 15 existing dashboard panel snapshots match, and the newWithFootersnapshot matches under all three builds, so it should not need thepipeline:ui-update-screenshotslabel. - Measured in Chrome against the test Storybook, in the
WithFooterstory (a 400px panel):- With the footer slot, the body container is 308px tall with nothing to scroll (
scrollHeight308,clientHeight308), and the link sits below it inside the panel. - With the same link moved into the body container instead, which is where content passed through
#bodyends up, the body scrolls (scrollHeight358,clientHeight337) and the link starts at y=385, below the body's visible bottom edge at y=383.
- With the footer slot, the body container is 308px tall with nothing to scroll (
yarn lint:eslint,yarn lint:prettierandyarn lint:markdownlintpass, as do the lefthook pre-commit hooks.
Screenshots or screen recordings
Before: the link passed through #body |
After: the link in the footer slot |
|---|---|
![]() |
![]() |
Both are the WithFooter story in the test Storybook built from this branch, a 400px panel with a line chart that fills it. For the first, I moved the footer's link into the body container in the browser, which is where a link passed through #body ends up today: it is still in the panel, below the visible part of the body's scroll area. The story's visual snapshot is in this MR's diff as storyshots-spec-js-image-storyshots-dashboards-dashboards-panel-with-footer-1-snap.png.
Integrations
The slot is new and optional, so no project needs a migration. In GitLab, app/assets/javascripts/vue_shared/components/customizable_dashboard/extended_dashboard_panel.vue can pass its footer through this slot once a release that has it is in GitLab.
- GitLab: mr_url (Run the
ui:create_integration_merge_requestCI job, which automatically creates the merge request and updates this item for you.) - CustomersDot: mr_url
- Duo UI: mr_url
- Status Page: mr_url
- Docs: mr_url
- Switchboard: mr_url
Does this MR meet the acceptance criteria?
This checklist encourages the authors, reviewers, and maintainers of merge requests (MRs) to confirm changes were analyzed for conformity with the project's guidelines, security and accessibility.
Toggle the acceptance checklist
Conformity
- The “What does this MR do?” section in the MR description is filled out, explaining the reasons for and scope of the proposed changes, per “Say why not just what”.
- For example, if the MR is focused on usage guidelines, addressing accessibility challenges could be added in a separate MR.
- Relevant label(s) are applied to the MR.
- The MR is added to a milestone.
- Added the
~"component:*"label(s) if applicable. - A changeset is added when this MR will do a patch, minor, or major update. More information can be found in
doc/changesets.md.
Components
- GitLab UI's contributing guidelines.
- If the MR changes a component's API, integration MR(s) have been opened (see integrations above).
Documentation
- If creating a new component page from scratch, it follows the page template structure.
- Content follows the GitLab Documentation Style Guide when appropriate.
- Related pages are cross-linked, where helpful. Component pages have related components and patterns defined in their Markdown front matter.
- If embedding a Figma file, it follows the Figma embed guide.
- Review requested from any GitLab designer or directly from a maintainer or trainee maintainer.
- Maintainer review follows the Pajamas UX maintainer review checklist.
Security
If this MR contains changes to processing or storing of credentials or tokens, authorization and authentication methods and other items described in the security review guidelines:
- Label as security and @ mention
@gitlab-com/gl-security/appsec - Security reports checked/validated by a reviewer from the AppSec team
Accessibility
If this MR adds or modifies a component, take a few moments to review the following:
- All actions and functionality can be done with a keyboard.
- Links, buttons, and controls have a visible focus state.
- All content is presented in text or with a text equivalent. For example, alt text for SVG, or
aria-labelfor icons that have meaning or perform actions. - Changes in a component’s state are announced by a screen reader. For example, changing
aria-expanded="false"toaria-expanded="true"when an accordion is expanded. - Color combinations have sufficient contrast.

