Skip to content

- fix: Make Command Prompts Non-Selectable in CodeGroup#21681

Open
somandhir wants to merge 2 commits intovitejs:mainfrom
somandhir:fix-homepage-copy-issue
Open

- fix: Make Command Prompts Non-Selectable in CodeGroup#21681
somandhir wants to merge 2 commits intovitejs:mainfrom
somandhir:fix-homepage-copy-issue

Conversation

@somandhir
Copy link

@somandhir somandhir commented Feb 21, 2026

  • What is this PR solving? Write a clear and concise description.
    When users triple-click on terminal commands in the CodeGroup component (e.g., $ npm create vite@latest), the entire line including the prompt ($) is selected. This makes it inconvenient to copy just the command itself

Modified the CodeGroup component to:

Split the shell prompt from the command: The regex pattern ^(\s*$\s+)(.*)$ separates the $ prefix from the actual command text
Render in separate spans: The prompt and command are now rendered in distinct elements with different styling
Disable selection on prompt: Added CSS rules with user-select: none on the prompt span, so triple-clicking only selects the command portion

>
<button class="copy"></button>
<span class="lang">{{ tab.language || 'bash' }}</span>
<pre><code><span class="prompt" v-if="splitCommand(tab.code).prompt">{{ splitCommand(tab.code).prompt }}</span><span class="command">{{ splitCommand(tab.code).command }}</span></code></pre>
Copy link
Contributor

Choose a reason for hiding this comment

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

Performance issue: splitCommand(tab.code) is called three times in a single render for the same input (once for v-if check, once for prompt display, once for command display). This causes the regex to execute three times per tab unnecessarily.

Fix: Compute the split result once and reuse it:

<script setup lang="ts">
const getSplitCommand = (code: string) => {
  const match = code.match(/^(\s*\$\s+)(.*)$/)
  return match ? { prompt: match[1], command: match[2] } : { prompt: '', command: code }
}
</script>

<template>
  <div v-for="(tab, index) in tabs" :key="`content-${index}`">
    <template v-memo="[tab.code]">
      <pre><code><template v-if="getSplitCommand(tab.code).prompt"><span class="prompt">{{ getSplitCommand(tab.code).prompt }}</span></template><span class="command">{{ getSplitCommand(tab.code).command }}</span></code></pre>
    </template>
  </div>
</template>

Or better, use a computed property to cache results per tab.

Spotted by Graphite Agent

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

Copy link
Author

Choose a reason for hiding this comment

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

Performance issue: splitCommand(tab.code) is called three times in a single render for the same input (once for v-if check, once for prompt display, once for command display). This causes the regex to execute three times per tab unnecessarily.

Fix: Compute the split result once and reuse it:

<script setup lang="ts">
const getSplitCommand = (code: string) => {
  const match = code.match(/^(\s*\$\s+)(.*)$/)
  return match ? { prompt: match[1], command: match[2] } : { prompt: '', command: code }
}
</script>

<template>
  <div v-for="(tab, index) in tabs" :key="`content-${index}`">
    <template v-memo="[tab.code]">
      <pre><code><template v-if="getSplitCommand(tab.code).prompt"><span class="prompt">{{ getSplitCommand(tab.code).prompt }}</span></template><span class="command">{{ getSplitCommand(tab.code).command }}</span></code></pre>
    </template>
  </div>
</template>

Or better, use a computed property to cache results per tab.

Spotted by Graphite AgentFix in GraphiteIs this helpful? React 👍 or 👎 to let us know.

I've optimized the component to eliminate the redundant regex executions:

Changes made:

Replaced the function with a computed property: splitCommands now maps over all tabs once and caches the results
Updated the template: Changed from calling splitCommand(tab.code) three times to accessing splitCommands[index] which is pre-computed and cached
Performance improvement:

Before: Regex executed 3x per tab per render (once for v-if, twice for display)
After: Regex executed 1x per tab total (cached in computed property)
The computed property reactively recalculates only when props.tabs changes, making the component significantly more efficient

@somandhir somandhir changed the title fix(site): Make Command Prompts Non-Selectable in CodeGroup Fix(site): Make Command Prompts Non-Selectable in CodeGroup Feb 21, 2026
@somandhir somandhir changed the title Fix(site): Make Command Prompts Non-Selectable in CodeGroup - fix(site): Make Command Prompts Non-Selectable in CodeGroup Feb 21, 2026
@somandhir somandhir changed the title - fix(site): Make Command Prompts Non-Selectable in CodeGroup - fix: Make Command Prompts Non-Selectable in CodeGroup Feb 21, 2026
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.

$ prompt in code blocks gets selected on triple-click, causing bad copy-paste experience (2)

1 participant