Checkbox: Improve accessibility of the indeterminate state (#112388)

use indeterminate instead of aria-checked
This commit is contained in:
Ashley Harrison
2025-10-15 13:35:44 +01:00
committed by GitHub
parent d3cd401734
commit 77b6271423
3 changed files with 17 additions and 14 deletions
-5
View File
@@ -696,11 +696,6 @@
"count": 3
}
},
"packages/grafana-ui/src/components/Forms/Checkbox.story.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"packages/grafana-ui/src/components/Forms/Form.story.tsx": {
"react-hooks/rules-of-hooks": {
"count": 9
@@ -18,8 +18,6 @@ const meta: Meta<typeof Checkbox> = {
controls: {
exclude: ['value', 'htmlValue'],
},
// TODO fix a11y issue in story and remove this
a11y: { test: 'off' },
},
};
@@ -94,7 +92,7 @@ export const AllStates: StoryFn<typeof Checkbox> = (args) => {
<Checkbox value={checked} onChange={onChange} {...args} />
<Checkbox value={true} label="Checked" />
<Checkbox value={false} label="Unchecked" />
<Checkbox value={false} indeterminate={true} label="Interdeterminate" />
<Checkbox value={false} indeterminate={true} label="Indeterminate" />
<Checkbox value={false} invalid={true} label="Invalid and unchecked" />
<Checkbox value={true} invalid={true} label="Invalid and checked" />
</Stack>
@@ -18,7 +18,7 @@ export interface CheckboxProps extends Omit<HTMLProps<HTMLInputElement>, 'value'
value?: boolean;
/** htmlValue allows to specify the input "value" attribute */
htmlValue?: string | number;
/** Sets the checkbox into a "mixed" state. This is only a visual change and does not affect the value. */
/** Sets the checkbox into a "mixed" state */
indeterminate?: boolean;
/** Show an invalid state around the input */
invalid?: boolean;
@@ -39,8 +39,6 @@ export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
);
const styles = useStyles2(getCheckboxStyles, invalid);
const ariaChecked = indeterminate ? 'mixed' : undefined;
return (
<label className={cx(styles.wrapper, className)}>
<div className={styles.checkboxWrapper}>
@@ -51,9 +49,21 @@ export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
disabled={disabled}
onChange={handleOnChange}
value={htmlValue}
aria-checked={ariaChecked}
{...inputProps}
ref={ref}
ref={(element) => {
if (element && indeterminate) {
element.indeterminate = true;
}
// we have to manually assign the ref since we need to modify the indeterminate property
if (ref) {
if (typeof ref === 'function') {
ref(element);
} else {
ref.current = element;
}
}
}}
/>
<span className={styles.checkmark} />
</div>
@@ -139,7 +149,7 @@ export const getCheckboxStyles = (theme: GrafanaTheme2, invalid = false) => {
}),
inputIndeterminate: css({
"&[aria-checked='mixed'] + span": {
'&:indeterminate + span': {
border: `1px solid ${getBorderColor(theme.colors.primary.main)}`,
background: theme.colors.primary.main,