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={[
}
+ downloadButtonValue="Download"
+ closeButtonValue="Close"
+ fetchErrorReport={async () => "Error details"}
+ />,
+ );
+ expect(screen.getByRole("dialog", { name: "Activity execution error report" })).toBeInTheDocument();
+ });
+});
From da446da1ca055e15c7416c452711c7819f9d337b Mon Sep 17 00:00:00 2001
From: Michael Haschke
Date: Thu, 5 Nov 2026 17:18:10 +0100
Subject: [PATCH 07/10] add option to translate fullscreen toggler
---
.../ActivityExecutionErrorReportModal.tsx | 10 +++++++---
src/cmem/ActivityControl/SilkActivityControl.tsx | 8 ++++++--
.../tests/SilkActivityControl.test.tsx | 15 ++++++++++++++-
src/components/Dialog/SimpleDialog.tsx | 15 ++++++++++++++-
src/components/Dialog/tests/SimpleDialog.test.tsx | 10 ++++++++++
5 files changed, 51 insertions(+), 7 deletions(-)
diff --git a/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.tsx b/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.tsx
index bc00e2c08..5f9ae0966 100644
--- a/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.tsx
+++ b/src/cmem/ActivityControl/ActivityExecutionErrorReportModal.tsx
@@ -1,11 +1,13 @@
import React from "react";
import Button from "../../components/Button/Button";
-import { ModalProps } from "../../components/Dialog/Modal";
-import SimpleDialog from "../../components/Dialog/SimpleDialog";
+import SimpleDialog, { SimpleDialogProps } from "../../components/Dialog/SimpleDialog";
import HtmlContentBlock from "../../components/Typography/HtmlContentBlock";
-interface ActivityExecutionErrorReportModalProps extends Pick {
+interface ActivityExecutionErrorReportModalProps extends Pick<
+ SimpleDialogProps,
+ "aria-label" | "aria-labelledby" | "fullScreenTogglerTexts"
+> {
/**
* Title of the modal.
* If set, it is used as the accessible name of the dialog via `aria-labelledby`
@@ -35,6 +37,7 @@ export const ActivityExecutionErrorReportModal = ({
report,
downloadButtonValue,
closeButtonValue,
+ fullScreenTogglerTexts,
fetchErrorReport,
}: ActivityExecutionErrorReportModalProps) => {
const fileName =
@@ -63,6 +66,7 @@ export const ActivityExecutionErrorReportModal = ({
isOpen={true}
size="large"
showFullScreenToggler
+ fullScreenTogglerTexts={fullScreenTogglerTexts}
onClose={onDiscard}
actions={[