diff --git a/packages/ui-checkbox/src/Checkbox/__tests__/Checkbox.test.tsx b/packages/ui-checkbox/src/Checkbox/__tests__/Checkbox.test.tsx
index 45e6d94b9b..069ac2c761 100644
--- a/packages/ui-checkbox/src/Checkbox/__tests__/Checkbox.test.tsx
+++ b/packages/ui-checkbox/src/Checkbox/__tests__/Checkbox.test.tsx
@@ -275,6 +275,37 @@ describe('', () => {
expect(input).not.toHaveAttribute('aria-invalid')
})
+ describe('`toggle` variant', () => {
+ it('should expose a button role and pressed state', () => {
+ renderCheckbox({ variant: 'toggle', defaultChecked: true })
+ const toggle = screen.getByRole('button')
+
+ expect(toggle).toHaveAttribute('aria-pressed', 'true')
+ expect(screen.queryByRole('checkbox')).not.toBeInTheDocument()
+ })
+
+ it('should update the pressed state when toggled', async () => {
+ renderCheckbox({ variant: 'toggle', defaultChecked: false })
+ const toggle = screen.getByRole('button')
+
+ expect(toggle).toHaveAttribute('aria-pressed', 'false')
+
+ await userEvent.click(toggle)
+
+ await waitFor(() => {
+ expect(toggle).toHaveAttribute('aria-pressed', 'true')
+ })
+ })
+
+ it('should leave the `simple` variant as a checkbox', () => {
+ renderCheckbox({ variant: 'simple' })
+ const input = screen.getByRole('checkbox')
+
+ expect(input).not.toHaveAttribute('role')
+ expect(input).not.toHaveAttribute('aria-pressed')
+ })
+ })
+
describe('for a11y', () => {
it('`simple` variant should meet standards', async () => {
const { container } = renderCheckbox({ variant: 'simple' })
diff --git a/packages/ui-checkbox/src/Checkbox/v2/index.tsx b/packages/ui-checkbox/src/Checkbox/v2/index.tsx
index a9a1991680..1e9b301046 100644
--- a/packages/ui-checkbox/src/Checkbox/v2/index.tsx
+++ b/packages/ui-checkbox/src/Checkbox/v2/index.tsx
@@ -343,6 +343,8 @@ class Checkbox extends Component {
readOnly={readOnly}
aria-readonly={readOnly ? true : undefined}
aria-checked={indeterminate ? 'mixed' : undefined}
+ role={variant === 'toggle' ? 'button' : undefined}
+ aria-pressed={variant === 'toggle' ? this.checked : undefined}
aria-invalid={this.invalid ? 'true' : undefined}
// Keep messages in the description so the accessible name contains only the label.
aria-labelledby={