Rams MCP · The full engine, now in your coding agent
vuejs on GitHub

vuejs/core

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.

4issues
Critical & Serious

Top fix

Add accessible names to icon-only header buttons, not just tooltips

See the fix

Verdict

Visual polish outpaces interaction rigor: solid tokens and URL state, undercut by icon buttons with no accessible names and a keyboard trap. The alert() dialog for copy confirmation is a blunt instrument in an otherwise considered header, fix the labeling gaps first.

Files Rams reviewed

packages-private/sfc-playground/src/App.vue

packages-private/sfc-playground/src/Header.vue

packages-private/sfc-playground/src/VersionSelect.vue

packages-private/sfc-playground/src/icons/Sun.vue

packages-private/dts-test/componentInstance.test-d.tsx

packages-private/dts-test/componentTypeExtensions.test-d.tsx

packages-private/dts-test/functionalComponent.test-d.tsx

packages-private/dts-test/tsx.test-d.tsx

packages-private/sfc-playground/src/download/template/index.html

packages-private/sfc-playground/src/icons/Copy.vue

packages-private/sfc-playground/src/icons/Download.vue

packages-private/sfc-playground/src/icons/GitHub.vue

packages-private/sfc-playground/src/icons/Moon.vue

packages-private/sfc-playground/src/icons/Reload.vue

packages-private/sfc-playground/src/icons/Share.vue

packages-private/template-explorer/style.css

packages/vue/__tests__/e2e/hydration-strat-custom.html

packages/vue/__tests__/e2e/hydration-strat-interaction.html

packages/vue/__tests__/e2e/hydration-strat-media.html

packages/vue/__tests__/e2e/hydration-strat-visible.html

packages/vue/examples/classic/commits.html

packages/vue/examples/classic/grid.html

packages/vue/examples/classic/markdown.html

packages/vue/examples/classic/svg.html

packages/vue/examples/classic/todomvc.html

packages/vue/examples/classic/tree.html

packages/vue/examples/composition/commits.html

packages/vue/examples/composition/grid.html

packages/vue/examples/composition/markdown.html

packages/vue/examples/composition/svg.html

95/100

Accessibility

1 critical1 serious
AccessibilityCritical

packages-private/sfc-playground/src/Header.vue:130

Icon-only header buttons have no accessible name for screen readers

The toggle-dark, share, reload, and download buttons in Header.vue (lines 122-142) render only an SVG icon inside a <button> with a title attribute ("Copy sharable URL", "Reload page", "Download project files", "Switch to dark theme"). title is a tooltip, not an accessible name: most screen readers don't announce it reliably, so these four controls read as unlabeled "button" to assistive tech.

Why it matters

A screen reader user tabbing through the header hears four buttons with no name and no way to tell copy-link from reload from download, blocking that action entirely.

Fix

Add aria-label to every icon-only button so its accessible name matches the visible intent of the title.

<button title="Copy sharable URL" class="share" @click="copyLink">
  <Share />
</button>
<button title="Copy sharable URL" aria-label="Copy sharable URL" class="share" @click="copyLink">
  <Share />
</button>
AccessibilitySerious

packages-private/sfc-playground/src/Header.vue:88

"This Commit" reset link has no href, dropping it from tab order

The <a @click="resetVueVersion">This Commit ({{ currentCommit }})</a> at line 88 has a click handler but no href attribute. Without href, an anchor is not a real link: it's not keyboard-focusable and doesn't appear in the tab order, unlike the adjacent "Commits History" link which does have an href.

Why it matters

Keyboard-only users can tab through the version menu but skip straight past this item, so they can never reset to the current commit without a mouse.

Fix

Convert the reset control to a <button> so it gets native keyboard focus and activation for free.

<li :class="{ active: vueVersion === `@${currentCommit}` }">
  <a @click="resetVueVersion">This Commit ({{ currentCommit }})</a>
</li>
<li :class="{ active: vueVersion === `@${currentCommit}` }">
  <button type="button" @click="resetVueVersion">This Commit ({{ currentCommit }})</button>
</li>
98/100

Color

1 serious
ColorSerious

packages-private/sfc-playground/src/Header.vue:224

DEV status label text fails contrast against its green background

.toggle-prod span sets color: #fff on background: var(--green) at font-size: 12px (lines 224-227), used to show the "DEV" label. White on the --green token (~#3ca877) computes to roughly 2.95:1, below the 4.5:1 WCAG AA threshold for small text.

Why it matters

Low-vision users can't reliably read whether the playground is in DEV or PROD mode, and that state affects debugging behavior.

Fix

Darken the green token or switch to a near-black text color on this badge to reach 4.5:1 for 12px text.

.toggle-prod span {
  background: var(--green);
  color: #fff;
}
.toggle-prod span {
  background: var(--green);
  color: #0a0a0a;
}

Get this score on every PR.

Rams reviews each pull request on your repo and posts inline one-click fixes — about a minute per review.

Install Rams free
98/100

UX

1 serious
UXSerious

packages-private/sfc-playground/src/Header.vue:55

Copy link confirmation blocks the UI with a native alert dialog

copyLink() (line 47-56) writes to the clipboard then calls alert('Sharable URL has been copied to clipboard.'). A native alert() halts the whole page and forces an explicit OK click before the user can do anything else, just to confirm a copy action.

Why it matters

Every share action now costs an extra forced click and a jarring modal interruption, which is disproportionate feedback for a low-stakes clipboard copy.

Fix

Replace the blocking alert with a transient inline confirmation (toast or temporary label change) near the share button.

await navigator.clipboard.writeText(location.href)
alert('Sharable URL has been copied to clipboard.')
await navigator.clipboard.writeText(location.href)
copied.value = true
setTimeout(() => (copied.value = false), 2000)

Typography

No issues found

Spacing

No issues found

Components

No issues found

Motion

No issues found

Craft

No issues found

Working well

  • Using CSS custom properties (--bg, --border) for the header and options panel keeps those surfaces visually consistent across #header and #options instead of duplicating hex values.
  • Persisting playground state to the URL hash via watchEffect + history.replaceState is a clean, dependency-free way to make every session shareable without extra UI chrome.
  • Dark mode redefines --bg, --border, --highlight as a hand-tuned palette rather than inverting light-mode hex values, which is the right approach for a designed dark theme.

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 vuejs/core’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