Rams MCP · The full engine, now in your coding agent
element-plus on GitHub

element-plus/element-plus

Reviewed against Rams quality heuristics: accessibility, color, typography, spacing, components, motion, UX, and craft.

30 files reviewed·August 1, 2026

View on GitHub

Elevated

Design risk in this codebase.

2issues
Critical

Top fix

Make the custom close control a focusable, keyboard-operable button

See the fix

Verdict

Alert.vue nails the announcement semantics but ships two broken dismiss controls: one div can't be tabbed to, one icon button has no name. Screen reader and keyboard users literally cannot close the alert, a basic failure sitting right next to otherwise careful styling.

Files Rams reviewed

packages/components/affix/src/affix.vue

packages/components/alert/src/alert.vue

packages/components/anchor/src/anchor-link.vue

packages/components/anchor/src/anchor.vue

packages/components/autocomplete/src/autocomplete.vue

packages/components/avatar/src/avatar-group.tsx

packages/components/avatar/src/avatar.vue

packages/components/backtop/src/backtop.vue

packages/components/badge/src/badge.vue

packages/components/breadcrumb/src/breadcrumb-item.vue

packages/components/button/src/button.vue

packages/components/calendar/src/calendar.vue

packages/components/calendar/src/date-table.vue

packages/components/calendar/src/select-controller.vue

packages/components/card/src/card.vue

packages/components/carousel/src/carousel-item.vue

packages/components/carousel/src/carousel.vue

packages/components/cascader-panel/src/index.vue

packages/components/cascader-panel/src/menu.vue

packages/components/cascader-panel/src/node-content.tsx

packages/components/cascader-panel/src/node.vue

packages/components/checkbox/src/checkbox-button.vue

packages/components/checkbox/src/checkbox-group.vue

packages/components/checkbox/src/checkbox.vue

packages/components/col/src/col.vue

packages/components/collapse-transition/src/collapse-transition.vue

packages/components/collapse/src/collapse-item.vue

packages/components/color-picker-panel/src/color-picker-panel.vue

packages/components/color-picker-panel/src/components/alpha-slider.vue

packages/components/color-picker-panel/src/components/hue-slider.vue

94/100

Accessibility

2 critical
AccessibilityCritical

packages/components/alert/src/alert.vue:29

Custom close button div is unreachable by keyboard users

In alert.vue, when `closeText` is set the dismiss control renders as a plain `<div class="[ns.e('close-btn'), ns.is('customed')]" @click="close">{{ closeText }}</div>` instead of a `<button>`. It has no tabindex, no keydown handler, and no ARIA role, so it never enters the tab order and Enter/Space do nothing even when focus lands on it another way.

Why it matters

Keyboard-only and switch-device users cannot dismiss the alert at all when a custom close label is used, locking them out of a control that mouse users can operate freely.

Fix

Render the custom close control as a native `<button type="button">` so it inherits focusability and keyboard activation for free.

<div
  v-if="closeText"
  :class="[ns.e('close-btn'), ns.is('customed')]"
  @click="close"
>
  {{ closeText }}
</div>
<button
  v-if="closeText"
  type="button"
  :class="[ns.e('close-btn'), ns.is('customed')]"
  @click="close"
>
  {{ closeText }}
</button>
AccessibilityCritical

packages/components/alert/src/alert.vue:37

Icon-only close button has no accessible name for screen readers

The default dismiss control, `<el-icon v-else :class="ns.e('close-btn')" @click="close"><Close /></el-icon>`, renders only a Close icon with no `aria-label`, `aria-labelledby`, or visible text. This is the path taken whenever `closeText` is not supplied, which is the common case.

Why it matters

Screen reader users hear nothing actionable when they reach this control, so they can't identify or trigger the dismiss action, effectively locking them out of closing the alert.

Fix

Add an aria-label (e.g. localized 'close') to the icon-only close control so assistive tech announces its purpose.

<el-icon v-else :class="ns.e('close-btn')" @click="close">
  <Close />
</el-icon>
<el-icon
  v-else
  :class="ns.e('close-btn')"
  aria-label="close"
  role="button"
  @click="close"
>
  <Close />
</el-icon>

Typography

No issues found

Color

No issues found

Spacing

No issues found

Components

No issues found

Motion

No issues found

UX

No issues found

Craft

No issues found

Working well

  • Active/is-customed state styling is driven through ns.is('customed') rather than inline styles, keeping the close-button variant inside the component's design-system namespace instead of ad hoc CSS.
  • The root alert div carries role="alert", giving it an implicit live region so title and description text is announced automatically when the alert mounts, no extra ARIA wiring needed.

Scored August 1, 2026 with Rams Engine v0.0.3 · Engine changelog
First scored July 29, 2026: 59/100. This rescore on v0.0.3: 59/100.

This page is an automated design review of element-plus/element-plus’s UI code: 30 files read against 291 versioned rules covering accessibility, color, typography, spacing, components, UX, motion, and craft. The score is out of 100; confirmed criticals cap it — one at 59, two at 49, three or more at 39.

More design scores

Score your own repo.

Free on public repos, no account. The same engine that scored this page reads your UI code and mints a score page like this one.

Public repos only. The full engine reviews the UI code and mints a public score page — we email you the link too. Already-scored repos open instantly.

Or get a design review on every pull requestInstall Rams