diff --git a/packages/pluggableWidgets/checkbox-radio-selection-web/CHANGELOG.md b/packages/pluggableWidgets/checkbox-radio-selection-web/CHANGELOG.md
index b0cfd176d8..3622a1c456 100644
--- a/packages/pluggableWidgets/checkbox-radio-selection-web/CHANGELOG.md
+++ b/packages/pluggableWidgets/checkbox-radio-selection-web/CHANGELOG.md
@@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
## [Unreleased]
+### Added
+
+- We added a missing validation alert.
+
## [1.0.0] - 2025-08-25
### Added
diff --git a/packages/pluggableWidgets/checkbox-radio-selection-web/src/components/CheckboxSelection/CheckboxSelection.tsx b/packages/pluggableWidgets/checkbox-radio-selection-web/src/components/CheckboxSelection/CheckboxSelection.tsx
index 3fa5178d3c..b7890b5e40 100644
--- a/packages/pluggableWidgets/checkbox-radio-selection-web/src/components/CheckboxSelection/CheckboxSelection.tsx
+++ b/packages/pluggableWidgets/checkbox-radio-selection-web/src/components/CheckboxSelection/CheckboxSelection.tsx
@@ -1,7 +1,9 @@
import classNames from "classnames";
import { createElement, MouseEvent, ReactElement } from "react";
import { MultiSelector, SelectionBaseProps } from "../../helpers/types";
+import { getValidationErrorId } from "../../helpers/utils";
import { CaptionContent } from "../CaptionContent";
+import { ValidationAlert } from "@mendix/widget-plugin-component-kit/Alert";
import { Placeholder } from "../Placeholder";
export function CheckboxSelection({
@@ -18,6 +20,9 @@ export function CheckboxSelection({
const isReadOnly = selector.readOnly;
const name = groupName?.value ?? inputId;
+ const validation = selector.validation;
+ const errorId = getValidationErrorId(inputId);
+
const handleChange = (optionId: string, checked: boolean): void => {
if (!isReadOnly) {
const newSelection = checked ? [...currentIds, optionId] : currentIds.filter(id => id !== optionId);
@@ -25,6 +30,8 @@ export function CheckboxSelection({
}
};
+ const isSingleCheckbox = options.length === 1;
+
return (
{options.map((optionId, index) => {
const isSelected = currentIds.includes(optionId);
@@ -55,6 +64,8 @@ export function CheckboxSelection({
disabled={isReadOnly}
tabIndex={tabIndex}
onChange={e => handleChange(optionId, e.target.checked)}
+ aria-describedby={isSingleCheckbox && selector.validation ? errorId : undefined}
+ aria-invalid={isSingleCheckbox && selector.validation ? true : undefined}
/>
) => {
@@ -71,6 +82,7 @@ export function CheckboxSelection({
);
})}
{options.length === 0 && }
+ {validation && {validation}}
);
}
diff --git a/packages/pluggableWidgets/checkbox-radio-selection-web/src/components/RadioSelection/RadioSelection.tsx b/packages/pluggableWidgets/checkbox-radio-selection-web/src/components/RadioSelection/RadioSelection.tsx
index 2840a13ee1..85d54759b2 100644
--- a/packages/pluggableWidgets/checkbox-radio-selection-web/src/components/RadioSelection/RadioSelection.tsx
+++ b/packages/pluggableWidgets/checkbox-radio-selection-web/src/components/RadioSelection/RadioSelection.tsx
@@ -1,7 +1,9 @@
import classNames from "classnames";
import { ChangeEvent, createElement, MouseEvent, ReactElement } from "react";
import { SelectionBaseProps, SingleSelector } from "../../helpers/types";
+import { getValidationErrorId } from "../../helpers/utils";
import { CaptionContent } from "../CaptionContent";
+import { ValidationAlert } from "@mendix/widget-plugin-component-kit/Alert";
import { Placeholder } from "../Placeholder";
import { If } from "@mendix/widget-plugin-component-kit/If";
@@ -24,6 +26,9 @@ export function RadioSelection({
const isReadOnly = selector.readOnly;
const name = groupName?.value ?? inputId;
+ const validation = selector.validation;
+ const errorId = getValidationErrorId(inputId);
+
const handleChange = (e: ChangeEvent): void => {
if (isReadOnly) {
return;
@@ -45,6 +50,8 @@ export function RadioSelection({
role={asSingleCheckbox ? "group" : "radiogroup"}
aria-labelledby={`${inputId}-label`}
aria-required={ariaRequired?.value}
+ aria-describedby={!asSingleCheckbox && selector.validation ? errorId : undefined}
+ aria-invalid={!asSingleCheckbox && selector.validation ? true : undefined}
>
{options.map((optionId, index) => {
const isSelected = currentId === optionId;
@@ -70,6 +77,8 @@ export function RadioSelection({
disabled={isReadOnly}
tabIndex={tabIndex}
onChange={handleChange}
+ aria-describedby={asSingleCheckbox && selector.validation ? errorId : undefined}
+ aria-invalid={asSingleCheckbox && selector.validation ? true : undefined}
/>
}
+ {validation && {validation}}
);
}
diff --git a/packages/pluggableWidgets/checkbox-radio-selection-web/src/helpers/utils.ts b/packages/pluggableWidgets/checkbox-radio-selection-web/src/helpers/utils.ts
index 1d9bb631a2..c05390081e 100644
--- a/packages/pluggableWidgets/checkbox-radio-selection-web/src/helpers/utils.ts
+++ b/packages/pluggableWidgets/checkbox-radio-selection-web/src/helpers/utils.ts
@@ -55,3 +55,7 @@ export function getCustomCaption(values: CheckboxRadioSelectionPreviewProps): st
}
return emptyStringFormat;
}
+
+export function getValidationErrorId(inputId?: string): string | undefined {
+ return inputId ? inputId + "-validation-message" : undefined;
+}