Skip to content

fix(a11y): improve accessibility for package command copy actions#998

Open
IdrisGit wants to merge 25 commits intonpmx-dev:mainfrom
IdrisGit:fix-copy-button-visibility
Open

fix(a11y): improve accessibility for package command copy actions#998
IdrisGit wants to merge 25 commits intonpmx-dev:mainfrom
IdrisGit:fix-copy-button-visibility

Conversation

@IdrisGit
Copy link
Copy Markdown
Contributor

@IdrisGit IdrisGit commented Feb 5, 2026

There are two issues I am trying to solve in this PR:

  1. Improve the discoverability of the copy command button.
  2. Improve a11y by preventing flashes and button's position jumps when switching between commands or changing the package manager option.

I was confused where the copy button was and when I decided to highlight using cursor and copy manually that I saw the copy button popup.

screen recording of the issue and the fix

copy_button_compressed.mp4

side note: as a side effect it also fixes an issue on mobile where it's very hard to know where the copy command, since the opacity of the button changes based on the hover state.

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment Apr 21, 2026 11:48am
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview Apr 21, 2026 11:48am
npmx-lunaria Ignored Ignored Apr 21, 2026 11:48am

Request Review

@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 5, 2026

Codecov Report

❌ Patch coverage is 68.00000% with 8 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
app/components/Package/SkillsModal.vue 20.00% 2 Missing and 2 partials ⚠️
app/components/Terminal/Install.vue 76.92% 3 Missing ⚠️
app/components/Terminal/Execute.vue 80.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 5, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Copy buttons in app/components/Terminal/Execute.vue, app/components/Terminal/Install.vue and app/components/Package/SkillsModal.vue were changed from hidden-by-default (opacity/group-hover) to persistently visible; their inner content was replaced with an icon that toggles between a copy icon and a checkmark based on copy state. Button border classes were standardised (including border-solid) and hover/focus styling simplified. test/e2e/create-command.spec.ts was updated to remove hover steps, assert persistent visibility of copy buttons, and add Run Command copy tests that verify clipboard contents and copy confirmation behaviour.

Possibly related PRs

Suggested reviewers

  • danielroe
  • ghostdevv
🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The pull request description clearly explains the two main issues being addressed: improving copy button discoverability and enhancing accessibility by preventing flashes and button position jumps. It directly relates to the changeset which updates button visibility and styling across multiple component files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
app/components/Terminal/Execute.vue (1)

71-74: Drop per-button focus-visible utility; rely on the global button focus style.

The inline focus-visible:outline-accent/70 on a <button> conflicts with the global focus-visible rule in app/assets/main.css. Please remove it to keep focus styling consistent.

Proposed change
-            class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95 focus-visible:outline-accent/70"
+            class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95"

Based on learnings: focus-visible styling for buttons and selects is applied globally via main.css; avoid per-element focus-visible utility classes like focus-visible:outline-accent/70.

app/components/Terminal/Install.vue (1)

124-127: Remove per-button focus-visible utilities and rely on the global rule.

These three buttons still include focus-visible:outline-accent/70, which conflicts with the project’s global focus-visible styling in app/assets/main.css.

Proposed change
-            class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border border-solid rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95 focus-visible:outline-accent/70"
+            class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border border-solid rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95"
-              class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border border-solid rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95 focus-visible:outline-accent/70"
+              class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border border-solid rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95"
-              class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border border-solid rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95 focus-visible:outline-accent/70"
+              class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border border-solid rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95"

Based on learnings: focus-visible styling for buttons and selects is applied globally via main.css; avoid per-element focus-visible utility classes like focus-visible:outline-accent/70.

Also applies to: 186-189, 231-233

Comment thread test/e2e/create-command.spec.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Comment thread app/components/Package/SkillsModal.vue Outdated
@graphieros
Copy link
Copy Markdown
Contributor

I like it. I just feel the eye has to travel from the button to its related content. How could this be mitigated ?

@IdrisGit
Copy link
Copy Markdown
Contributor Author

IdrisGit commented Feb 5, 2026

I like it. I just feel the eye has to travel from the button to its related content. How could this be mitigated ?

@graphieros fair point, I think quick way would be to remove the right align and show the button in it's original place, later we can think about a better position or if you have any ideas.

image

@graphieros
Copy link
Copy Markdown
Contributor

I think we need to know what others think.

The initial intention was to avoid cluttering the content.
Perhaps just a copy icon with a tooltip ?

@IdrisGit
Copy link
Copy Markdown
Contributor Author

IdrisGit commented Feb 5, 2026

@graphieros yeah that makes sense, I will try with icons and post screenshots here

@IdrisGit
Copy link
Copy Markdown
Contributor Author

IdrisGit commented Feb 5, 2026

Ok after trying few things and researching other platforms:

  • I feel like the original solution is more consistent, since almost all docs website place copy button at end and users are trained to look there so it shouldn't be an issue.
  • Tooltips themselves have issues and I don't like conveying important information using tooltips, imo they should only be used for optional details.
  • We can get to this later if we observe any issues

@IdrisGit IdrisGit force-pushed the fix-copy-button-visibility branch from 905a187 to 17c4dd8 Compare February 6, 2026 06:20
@knowler knowler added the a11y Related to accessibility and inclusion label Feb 7, 2026
Copy link
Copy Markdown
Member

@knowler knowler left a comment

Choose a reason for hiding this comment

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

I think this is a great change. I consider copy buttons like these to be added conveniences since users can already select and copy text, so I typically am a bit more lenient about only revealing them on hover/focus (as a compromise). We do this for copying the package name at the top of the page, since there’s already a lot of clutter. This case is a bit different because we do have the space.

With regard to clutter, I think we should find a way to better distinguish the button from the adjacent command’s text. Perhaps thicker borders or inverting the background/foreground colours.

As well, I do not think we should right align them. This actually reduces the usability/discoverability for some users as they have trace across a bunch of empty space (i.e. a physical and/or cognitive challenge) or they might not notices they’re there (e.g. magnifier users or folks with visual impairments like tunnel vision).

@IdrisGit IdrisGit force-pushed the fix-copy-button-visibility branch from 17c4dd8 to 97c7c56 Compare February 7, 2026 09:11
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/components/Terminal/Install.vue (1)

186-192: ⚠️ Potential issue | 🟡 Minor

Add missing accessibility attributes for consistency.

This button is missing the aria-label attribute and aria-live="polite" wrapper that the install command (line 127-130) and create command (line 234-239) buttons have. For a PR focused on accessibility, these should be consistent.

Suggested fix
            <button
              type="button"
-              class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border border-solid rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95 focus-visible:outline-accent/70"
+              class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border border-solid rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95"
+              :aria-label="$t('package.get_started.copy_command')"
              `@click.stop`="copyRunCommand(executableInfo?.primaryCommand)"
            >
-              {{ runCopied ? $t('common.copied') : $t('common.copy') }}
+              <span aria-live="polite">{{ runCopied ? $t('common.copied') : $t('common.copy') }}</span>
            </button>
🧹 Nitpick comments (3)
app/components/Terminal/Execute.vue (1)

71-78: Remove inline focus-visible:outline-accent/70 utility; rely on global styling.

Per project guidelines, focus-visible styling for buttons is handled globally in main.css. The inline focus-visible:outline-accent/70 class should be removed.

Additionally, for consistency with the Install.vue buttons:

  1. Add border-solid to match the standardised border styling
  2. Consider wrapping the button text in <span aria-live="polite"> so screen readers announce the "Copied" state change
Suggested fix
          <button
            type="button"
-            class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95 focus-visible:outline-accent/70"
+            class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border border-solid rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95"
            :aria-label="$t('package.get_started.copy_command')"
            `@click.stop`="copyExecuteCommand"
          >
-            {{ executeCopied ? $t('common.copied') : $t('common.copy') }}
+            <span aria-live="polite">{{ executeCopied ? $t('common.copied') : $t('common.copy') }}</span>
          </button>

Based on learnings: "In the npmx.dev project, ensure that focus-visible styling for button and select elements is implemented globally in app/assets/main.css… Do not apply per-element inline utility classes like focus-visible:outline-accent/70 on these elements."

app/components/Terminal/Install.vue (2)

124-131: Remove inline focus-visible:outline-accent/70 utility.

Per project guidelines, focus-visible styling for buttons is handled globally in main.css. Remove the inline utility class.

Suggested fix
          <button
            type="button"
-            class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border border-solid rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95 focus-visible:outline-accent/70"
+            class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border border-solid rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95"
            :aria-label="$t('package.get_started.copy_command')"
            `@click.stop`="copyInstallCommand"
          >

Based on learnings: "In the npmx.dev project… Do not apply per-element inline utility classes like focus-visible:outline-accent/70 on these elements."


231-240: Same issue: remove inline focus-visible:outline-accent/70.

As with the other buttons, remove the inline focus-visible utility class to rely on the global styling.

Suggested fix
            <button
              type="button"
-              class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border border-solid rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95 focus-visible:outline-accent/70"
+              class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border border-solid rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95"
              :aria-label="$t('package.create.copy_command')"
              `@click.stop`="copyCreateCommand"
            >

@IdrisGit
Copy link
Copy Markdown
Contributor Author

IdrisGit commented Feb 7, 2026

Here is one way we can do it, keeps the button near the command, no surprise on hover and uses existing copy icons for familiarity

image

@graphieros
Copy link
Copy Markdown
Contributor

I think this looks very nice

@IdrisGit
Copy link
Copy Markdown
Contributor Author

waiting for this PR (#2047) to get merged so I can use the useAnnouncer

@github-actions

This comment has been minimized.

@github-actions github-actions Bot added the stale This has become stale and may be closed soon label Apr 18, 2026
@knowler knowler removed stale This has become stale and may be closed soon blocked labels Apr 18, 2026
@knowler
Copy link
Copy Markdown
Member

knowler commented Apr 20, 2026

@IdrisGit Nuxt has been updated so I believe this should be unblocked now. Let me know if you have time to continue this and/or you need another review.

@IdrisGit
Copy link
Copy Markdown
Contributor Author

@knowler yes this unblocks the PR, I will update it after work and ping you for the review, thanks for the headsup.

@ghostdevv ghostdevv marked this pull request as draft April 20, 2026 13:20
@ghostdevv
Copy link
Copy Markdown
Contributor

Will mark as draft while you work on it 🙏

@IdrisGit
Copy link
Copy Markdown
Contributor Author

@knowler can I get another review on this PR. There are two things I want to know:

  1. I have updated the i18n translations only in English, as I am not very fluent in other languages, do you want me to update other languages as well (using Google translate and existing phrases in the repo) or let others add translations?
  2. Do you want me to update the PR title? (feel free to update it yourself as well) if it needs to be updated.

@knowler
Copy link
Copy Markdown
Member

knowler commented Apr 21, 2026

@IdrisGit I’ll review this when I get a chance over the next few days.

Answers to your questions:

  1. Let others add translations. We don’t expect translations to be updated unless people are capable (I’m certainly not).
  2. You can update the PR title/description to match the changes. Mark as ready for review once that’s done.

@IdrisGit IdrisGit marked this pull request as ready for review April 22, 2026 14:07
@IdrisGit IdrisGit changed the title fix(a11y, ui): make copy commands buttons always visible fix(a11y): improve accessibility for package command copy actions Apr 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a11y Related to accessibility and inclusion

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants