Skip to content

A11y: BoxButton does not set attributes important for buttons semantically #1615

@rvveber

Description

@rvveber

const BoxButton = forwardRef<HTMLDivElement, BoxButtonType>(
({ $css, ...props }, ref) => {
const theme = props.$theme || 'greyscale';
const variation = props.$variation || '400';
return (
<Box
ref={ref}
as="button"
$background="none"
$margin="none"
$padding="none"
$hasTransition
$css={css`
cursor: ${props.disabled ? 'not-allowed' : 'pointer'};
border: none;
outline: none;
font-family: inherit;
color: ${props.disabled
? `var(--c--theme--colors--${theme}-400) !important`
: `inherit`};
&:focus-visible {
transition: none;
outline: 2px solid var(--c--theme--colors--${theme}-${variation});
border-radius: 1px;
outline-offset: 4px;
}
${$css || ''}
`}
{...props}
className={`--docs--box-button ${props.className || ''}`}
onClick={(event: React.MouseEvent<HTMLDivElement>) => {
if (props.disabled) {
return;
}
props.onClick?.(event);
}}
/>
);
},
);

  • Problem: BoxButton renders as="button" but still keeps a HTMLDivElement ref and never forwards disabled or type attributes. It also only blocks clicks manually, so screen readers and keyboards still treat the control as fully interactive, and it defaults to submitting a form when used inside one.
  • Impact: Disabled actions remain actionable for assistive technology, resulting in confusing state announcements and accidental form submission.
  • Acceptance criteria / fix ideas:
    • Forward the ref as HTMLButtonElement when as="button".
    • Default to type="button" to avoid unwanted form submissions.
    • Pass the disabled prop directly and expose aria-disabled so assistive tech perceives the disabled state accurately.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions