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-col column and before the alert-message slot, in a div with gl-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 div rather than a footer element, 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 WithFooter story with its visual snapshot; a minor changeset; 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 of dashboard_panel.spec.js pass with it, under both.
  • Dropping either half of the v-if ($scopedSlots.footer or !loading) fails a spec.
  • I built the test Storybook three ways, as the three ui:visual* jobs do (yarn storybook:build:test with Vue 2, with VUE_VERSION=3, and with VUE_VERSION=3 VUE_COMPILER_VERSION=2), and ran test-storybook --browsers firefox on the dashboard panel stories inside mcr.microsoft.com/playwright:v1.63.0-jammy, the image of those jobs. The 15 existing dashboard panel snapshots match, and the new WithFooter snapshot matches under all three builds, so it should not need the pipeline:ui-update-screenshots label.
  • Measured in Chrome against the test Storybook, in the WithFooter story (a 400px panel):
    • With the footer slot, the body container is 308px tall with nothing to scroll (scrollHeight 308, clientHeight 308), 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 #body ends up, the body scrolls (scrollHeight 358, clientHeight 337) and the link starts at y=385, below the body's visible bottom edge at y=383.
  • yarn lint:eslint, yarn lint:prettier and yarn lint:markdownlint pass, as do the lefthook pre-commit hooks.

Screenshots or screen recordings

Before: the link passed through #body After: the link in the footer slot
Dashboard panel whose link sits below the visible part of the body Dashboard panel with the link visible in the footer below the chart

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.

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

Documentation

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-label for 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" to aria-expanded="true" when an accordion is expanded.
  • Color combinations have sufficient contrast.
Edited by José M. Requena Plens

Merge request reports

Loading
Loading