Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/volto-button-block/news/26.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
This PR improves accessibility by rendering a semantic `<a>` tag instead of a `<Button>` when the component is linked (data.href). Buttons are meant for actions, while links indicate navigation. Using the correct HTML element helps assistive technologies (like screen readers) interpret the component properly and enhances keyboard navigation and semantics.

In edit mode, the button is still wrapped in a ConditionalLink, as before. In view mode, a plain `<a>` tag is rendered when a link is present, and a `<Button>` is used only if no link exists.

@tomschall
45 changes: 29 additions & 16 deletions packages/volto-button-block/src/components/View.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,36 @@ const View = (props) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [data.href]);

let link = hasLink ? (
data.href.length > 0 && (
<ConditionalLink
to={data.href[0]?.['@id']}
condition={!isEditMode}
openLinkInNewTab={data.openLinkInNewTab}
>
<Button className={(cx('button'), data.align)}>
let link;
if (hasLink && data.href.length > 0) {
if (isEditMode) {
link = (
<ConditionalLink
to={data.href[0]?.['@id']}
condition={!isEditMode}
openLinkInNewTab={data.openLinkInNewTab}
item={data.href[0]}
>
<Button className={(cx('button'), data.align)}>
{data.title || intl.formatMessage(messages.ButtonText)}
</Button>
</ConditionalLink>
);
} else {
// Accessibility: Render as <a> tag in view mode when link exists
link = (
<a href={data.href[0]?.['@id']} className={cx('button', data.align)}>
{data.title || intl.formatMessage(messages.ButtonText)}
</Button>
</ConditionalLink>
)
) : (
<Button className="noLink">
{data.title || intl.formatMessage(messages.ButtonText)}
</Button>
);
</a>
);
}
} else {
link = (
<Button className="noLink">
{data.title || intl.formatMessage(messages.ButtonText)}
</Button>
);
}

return (
<BlockWrapper {...props} ExtraWrapper={LegacyWrapper}>
Expand Down