From 435d6e8a68a7bf135bbaa7ea0bd963564a7084fe Mon Sep 17 00:00:00 2001 From: Andreas Schultz Date: Wed, 4 Nov 2026 14:17:30 +0100 Subject: [PATCH 01/10] Support accessible names for titleless activity error reports - Forward aria-label and aria-labelledby through SilkActivityControl to ActivityExecutionErrorReportModal and its dialog - Add regression coverage for titleless error reports. --- CHANGELOG.md | 5 ++ ...ActivityExecutionErrorReportModal.test.tsx | 46 +++++++++++++++++++ .../ActivityExecutionErrorReportModal.tsx | 6 ++- .../ActivityControl/SilkActivityControl.tsx | 4 +- 4 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 src/cmem/ActivityControl/ActivityExecutionErrorReportModal.test.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 303eee5d1..c10f18632 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ## [Unreleased] +### Added + +- ``, `` + - support `aria-label` and `aria-labelledby` for naming activity error report dialogs without a visible title + ## [26.2.0] - 2026-10-05 ### Added diff --git a/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.test.tsx b/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.test.tsx new file mode 100644 index 000000000..18728771e --- /dev/null +++ b/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.test.tsx @@ -0,0 +1,46 @@ +import React from "react"; +import "@testing-library/jest-dom"; +import { fireEvent, render, screen, waitFor } from "@testing-library/react"; +import { SilkActivityControl, SilkActivityControlProps } from "./SilkActivityControl"; + +it("forwards the accessible name to a titleless activity error report", async () => { + const failureReportAction = { + title: "", + "aria-label": "Activity execution error report", + renderReport: () =>

Error details

, + renderMarkdown: true, + fetchErrorReport: async () => "Error details", + downloadButtonValue: "Download", + closeButtonValue: "Close", + }; + const props: SilkActivityControlProps = { + label: "Execution", + initialStatus: { + activity: "execute", + activityLabel: "Execution", + isRunning: false, + failed: true, + statusName: "Finished", + progress: 100, + lastUpdateTime: 0, + message: "Failed", + cancelled: false, + concreteStatus: "Failed", + }, + registerForUpdates: jest.fn(), + unregisterFromUpdates: jest.fn(), + showStartAction: false, + showStopAction: false, + showReloadAction: false, + executeActivityAction: jest.fn(), + translate: (key) => key, + failureReportAction, + }; + render(); + fireEvent.click(screen.getByRole("button")); + const dialog = await screen.findByRole("dialog", { name: "Activity execution error report" }); + expect(dialog).toHaveAttribute("aria-modal", "true"); + expect(dialog.querySelector(".eccgui-card__title")).toBeEmptyDOMElement(); + fireEvent.click(screen.getByRole("button", { name: "Close" })); + await waitFor(() => expect(screen.queryByRole("dialog")).not.toBeInTheDocument()); +}); diff --git a/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.tsx b/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.tsx index be2e7a932..879812c3d 100644 --- a/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.tsx +++ b/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.tsx @@ -5,7 +5,7 @@ import SimpleDialog from "../../components/Dialog/SimpleDialog"; import IconButton from "../../components/Icon/IconButton"; import HtmlContentBlock from "../../components/Typography/HtmlContentBlock"; -interface ActivityExecutionErrorReportModalProps { +interface ActivityExecutionErrorReportModalProps extends Pick { // Title of the modal title?: string; // Called when the close button is clicked @@ -23,6 +23,8 @@ interface ActivityExecutionErrorReportModalProps { /** Shows the execution error report to the user and offers to download the report. */ export const ActivityExecutionErrorReportModal = ({ title, + "aria-label": ariaLabel, + "aria-labelledby": ariaLabelledby, onDiscard, report, downloadButtonValue, @@ -51,6 +53,8 @@ export const ActivityExecutionErrorReportModal = ({ return ( { // The title of the error report modal title?: string; // The element that will be rendered in the modal, either as Markdown or object @@ -362,6 +362,8 @@ export function useSilkActivityControl({ {errorReport && failureReportAction && ( Date: Thu, 5 Nov 2026 16:19:31 +0100 Subject: [PATCH 02/10] fetch Attributes from Modal, so they have descriptions in the storybook docs/ide, incl the note to be enforced at a later major --- src/cmem/ActivityControl/ActivityExecutionErrorReportModal.tsx | 3 ++- src/cmem/ActivityControl/SilkActivityControl.tsx | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.tsx b/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.tsx index 879812c3d..943950cdb 100644 --- a/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.tsx +++ b/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.tsx @@ -1,11 +1,12 @@ import React, { useState } from "react"; import Button from "../../components/Button/Button"; +import { ModalProps } from "../../components/Dialog/Modal"; import SimpleDialog from "../../components/Dialog/SimpleDialog"; import IconButton from "../../components/Icon/IconButton"; import HtmlContentBlock from "../../components/Typography/HtmlContentBlock"; -interface ActivityExecutionErrorReportModalProps extends Pick { +interface ActivityExecutionErrorReportModalProps extends Pick { // Title of the modal title?: string; // Called when the close button is clicked diff --git a/src/cmem/ActivityControl/SilkActivityControl.tsx b/src/cmem/ActivityControl/SilkActivityControl.tsx index c66d3df29..a9d414342 100644 --- a/src/cmem/ActivityControl/SilkActivityControl.tsx +++ b/src/cmem/ActivityControl/SilkActivityControl.tsx @@ -3,6 +3,7 @@ import { Intent } from "@blueprintjs/core/src/common/intent"; import { Icon, Spacing } from "../../"; import { IntentTypes } from "../../common/Intent"; +import { ModalProps } from "../../components/Dialog/Modal"; import { TestableComponent } from "../../components/interfaces"; import { ElapsedDateTimeDisplay, ElapsedDateTimeDisplayUnits } from "../DateTimeDisplay/ElapsedDateTimeDisplay"; @@ -90,7 +91,7 @@ const defaultLayout: SilkActivityControlLayoutProps = { visualization: "spinner", }; -interface IErrorReportAction extends Pick { +interface IErrorReportAction extends Pick { // The title of the error report modal title?: string; // The element that will be rendered in the modal, either as Markdown or object From 7d059ea3e850442a4fd7db72fc131efef8eb8668 Mon Sep 17 00:00:00 2001 From: Michael Haschke Date: Thu, 5 Nov 2026 16:28:23 +0100 Subject: [PATCH 03/10] Remove dulicated functionality and add a label to the button --- .../ActivityExecutionErrorReportModal.tsx | 13 +++---------- src/components/Dialog/SimpleDialog.tsx | 2 ++ src/components/Dialog/tests/SimpleDialog.test.tsx | 7 +++++++ 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.tsx b/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.tsx index 943950cdb..fe48ad49e 100644 --- a/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.tsx +++ b/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.tsx @@ -1,9 +1,8 @@ -import React, { useState } from "react"; +import React from "react"; import Button from "../../components/Button/Button"; import { ModalProps } from "../../components/Dialog/Modal"; import SimpleDialog from "../../components/Dialog/SimpleDialog"; -import IconButton from "../../components/Icon/IconButton"; import HtmlContentBlock from "../../components/Typography/HtmlContentBlock"; interface ActivityExecutionErrorReportModalProps extends Pick { @@ -32,7 +31,6 @@ export const ActivityExecutionErrorReportModal = ({ closeButtonValue, fetchErrorReport, }: ActivityExecutionErrorReportModalProps) => { - const [displayFullscreen, setDisplayFullscreen] = useState(false); const fileName = "Activity execution report from " + new Date().toISOString().replace(/T/, " ").replace(/:/g, "-").substr(0, 19) + @@ -57,14 +55,9 @@ export const ActivityExecutionErrorReportModal = ({ aria-label={ariaLabel} aria-labelledby={ariaLabelledby} isOpen={true} - size={displayFullscreen ? "fullscreen" : "large"} + size="large" + showFullScreenToggler onClose={onDiscard} - headerOptions={ - setDisplayFullscreen(!displayFullscreen)} - /> - } actions={[