Skip to content

fix(mui): prevent nested interactive elements in navigation buttons#7266

Open
kaigritun wants to merge 3 commits intorefinedev:mainfrom
kaigritun:fix/mui-button-nested-interactive-elements
Open

fix(mui): prevent nested interactive elements in navigation buttons#7266
kaigritun wants to merge 3 commits intorefinedev:mainfrom
kaigritun:fix/mui-button-nested-interactive-elements

Conversation

@kaigritun
Copy link

Summary

This PR fixes an accessibility issue where navigation buttons (CreateButton, EditButton, ShowButton, ListButton, CloneButton) render a <button> element inside an <a> element.

Problem

The current implementation wraps <Button> inside <LinkComponent>:

<LinkComponent to={to}>
  <Button>...</Button>
</LinkComponent>

This creates nested interactive elements (<a><button></a>), which:

Solution

Use MUI's component prop to render the Button as the LinkComponent directly:

<Button component={LinkComponent} to={to}>
  ...
</Button>

This approach:

  • Maintains all existing button styling
  • Preserves navigation behavior
  • Fixes the nested interactive elements issue
  • Follows MUI's recommended pattern for link buttons

Changes

  • packages/mui/src/components/buttons/create/index.tsx
  • packages/mui/src/components/buttons/edit/index.tsx
  • packages/mui/src/components/buttons/show/index.tsx
  • packages/mui/src/components/buttons/list/index.tsx
  • packages/mui/src/components/buttons/clone/index.tsx

Testing

The fix maintains backward compatibility - all existing props and behaviors are preserved. The only change is the rendered HTML structure.

Fixes #7085

Use Button's component prop to render as LinkComponent directly instead of
nesting Button inside LinkComponent. This fixes an accessibility issue where
button elements were incorrectly nested inside anchor elements.

Affects: CreateButton, EditButton, ShowButton, ListButton, CloneButton

Fixes refinedev#7085
@kaigritun kaigritun requested review from a team as code owners February 11, 2026 19:52
@changeset-bot
Copy link

changeset-bot bot commented Feb 11, 2026

🦋 Changeset detected

Latest commit: 7237c5c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@refinedev/mui Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@cypress
Copy link

cypress bot commented Feb 12, 2026

refine    Run #12469

Run Properties:  status check passed Passed #12469  •  git commit ddd08da8bc: Merge pull request #7263 from refinedev/fix-react-admin-old-blog
Project refine
Branch Review main
Run status status check passed Passed #12469
Run duration 18m 38s
Commit git commit ddd08da8bc: Merge pull request #7263 from refinedev/fix-react-admin-old-blog
Committer Özgür Akça
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 0
Tests that did not run due to a developer annotating a test with .skip  Pending 22
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 368
View all changes introduced in this branch ↗︎

@BatuhanW BatuhanW changed the base branch from master to main February 12, 2026 07:38
<Button
component={LinkComponent}
to={to}
replace={false}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is removing replace intentional?

onClick(e);
}
}}
style={{ textDecoration: "none" }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The order of props are changed, so the diff is a bit hard to read. Could you try to keep current order as much as possible?

@kaigritun kaigritun force-pushed the fix/mui-button-nested-interactive-elements branch from 442a79d to b38da2f Compare February 12, 2026 08:03
@kaigritun
Copy link
Author

Thanks for the review @BatuhanW! I've addressed both of your comments:

  1. replace prop: Good catch! Removing replace={false} was not intentional. I've restored it in the latest commit. The prop is now passed to the Button component and will be forwarded to the LinkComponent via the component prop.

  2. Prop order: I've reorganized the props to maintain the original order as much as possible. The new structure-specific props (component, to, replace) are added after disabled to minimize the diff, while keeping all other props in their original order (startIcon, title, sx, data-testid, className, ...restProps).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] CreateButton of Material UI integration renders button in anchor

2 participants