Skip to content

Feat: Auto switch code tab to user preferred programming language#111

Merged
RAJ8664 merged 1 commit intomainfrom
default-language
Feb 21, 2026
Merged

Feat: Auto switch code tab to user preferred programming language#111
RAJ8664 merged 1 commit intomainfrom
default-language

Conversation

@RAJ8664
Copy link
Owner

@RAJ8664 RAJ8664 commented Feb 21, 2026

  • Key Changes:

    • Added a GLOBAL_LANG_KEY to store the selected language in localStorage.
    • Synced tab selection with a watcher and updated the click handler to use setActiveTab() so the global language state stays consistent.
  • Usage:

    • In any particular Code Tab, select your preferred programming language once.

Fixes #110

Summary by CodeRabbit

Improvements

  • Code language tab selections are now persisted across the documentation, automatically remembering your language preference for code examples across page navigation.

@vercel
Copy link

vercel bot commented Feb 21, 2026

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

Project Deployment Actions Updated (UTC)
prep Ready Ready Preview, Comment Feb 21, 2026 8:21pm

@coderabbitai
Copy link

coderabbitai bot commented Feb 21, 2026

📝 Walkthrough

Walkthrough

The CodeTabs component now persists the user's selected programming language to localStorage, enabling their language preference to remain consistent across all code examples throughout the site without requiring repeated switching.

Changes

Cohort / File(s) Summary
Language Persistence Layer
.vitepress/theme/components/CodeTabs.vue
Converts inline script to standard script block with localStorage-backed global language state. Adds onMounted hook to synchronize active tab with persisted preference, a watcher to update tabs when language changes, and a setActiveTab() setter to coordinate both local and global state updates.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A bunny hops with glee,
Language stays where users decree,
No more switching, what a sight,
The same tongue shines, morning and night! 🌙✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main feature: persisting and auto-switching code tabs to the user's preferred programming language across the site.
Linked Issues check ✅ Passed The code changes fully implement issue #110's requirements: localStorage persistence of language preference, automatic tab switching across examples, and global language state synchronization.
Out of Scope Changes check ✅ Passed All changes in CodeTabs.vue are directly scoped to implementing the persistent language preference feature described in the linked issue.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch default-language

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


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.

@RAJ8664 RAJ8664 added the enhancement New feature or request label Feb 21, 2026
@RAJ8664 RAJ8664 merged commit 0042275 into main Feb 21, 2026
7 of 8 checks passed
Copy link

@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: 2

🧹 Nitpick comments (2)
.vitepress/theme/components/CodeTabs.vue (2)

49-56: Watcher redundantly updates activeTab for the component instance that triggered the change.

When setActiveTab(i) is called, it sets activeTab.value = index directly (line 59), then sets globalActiveLanguage.value (line 60), which fires this watcher and sets activeTab.value = index a second time on the same instance. Adding a guard avoids the redundant re-assignment:

♻️ Proposed refactor
 watch(globalActiveLanguage, (newLang) => {
   if (newLang) {
     const index = props.languages.findIndex((lang) => lang.name === newLang)
-    if (index !== -1) {
+    if (index !== -1 && index !== activeTab.value) {
       activeTab.value = index
     }
   }
 })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.vitepress/theme/components/CodeTabs.vue around lines 49 - 56, The watcher
on globalActiveLanguage redundantly re-assigns activeTab for the same component
instance that already set it via setActiveTab; update the watch callback in
CodeTabs.vue to only assign activeTab.value when the resolved index differs from
the current activeTab.value (i.e., after computing index from props.languages,
check index !== -1 && activeTab.value !== index before setting activeTab.value)
so setActiveTab and the watcher don't perform the same assignment twice.

43-46: Silently persists an auto-selected default to localStorage without user action.

When no stored preference exists, line 45 sets globalActiveLanguage.value, which immediately triggers the module-level watcher (lines 16–20) to write that value to localStorage. This means the first CodeTabs component to mount determines the "preferred language" permanently — before the user has made any explicit choice. The PR intent is to persist user selections, not auto-persist defaults.

Consider only writing to localStorage on an explicit user action (i.e., inside setActiveTab), and removing the globalActiveLanguage assignment from the else if fallback:

♻️ Proposed fix
 onMounted(() => {
   if (globalActiveLanguage.value) {
     const index = props.languages.findIndex(
       (lang) => lang.name === globalActiveLanguage.value,
     )
     if (index !== -1) {
       activeTab.value = index
     }
-  } else if (props.languages.length > 0) {
-    // Note: If no global language is set, use the first tab's language as default
-    globalActiveLanguage.value = props.languages[0].name
   }
 })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.vitepress/theme/components/CodeTabs.vue around lines 43 - 46, The current
fallback in CodeTabs.vue auto-assigns globalActiveLanguage.value (the else-if
branch) which triggers the module-level watcher and writes a default into
localStorage; remove that auto-assignment so no default is persisted on mount,
and ensure persistence happens only when the user explicitly changes tabs by
writing to localStorage inside setActiveTab (or by having setActiveTab call a
helper that sets globalActiveLanguage and writes to localStorage). Also remove
or adjust the module-level watcher that unconditionally writes
globalActiveLanguage to localStorage so it no longer persists
programmatic/initial assignments—only persist inside the user-action pathway
implemented by setActiveTab.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.vitepress/theme/components/CodeTabs.vue:
- Around line 58-61: The setActiveTab function accesses
props.languages[index].name without validating index; add a defensive bounds
check in setActiveTab (referencing setActiveTab, activeTab,
globalActiveLanguage, and props.languages) so it only reads
props.languages[index].name when index >= 0 && index < props.languages.length;
if the index is out of range, still set activeTab (or bail) and set
globalActiveLanguage to a safe fallback (e.g., props.languages[0]?.name or an
empty string) to avoid runtime crashes when called programmatically.
- Line 4: GLOBAL_LANG_KEY currently holds a language name ('java') instead of a
descriptive storage key; change its value to a clear identifier like
'preferred-language' and update all usages (e.g.,
localStorage.getItem(GLOBAL_LANG_KEY), localStorage.setItem(GLOBAL_LANG_KEY,
...)) so preferences are stored under that key; ensure any code referencing
GLOBAL_LANG_KEY (the constant itself in CodeTabs.vue and any methods that
read/write localStorage) continues to work without semantic changes.

---

Nitpick comments:
In @.vitepress/theme/components/CodeTabs.vue:
- Around line 49-56: The watcher on globalActiveLanguage redundantly re-assigns
activeTab for the same component instance that already set it via setActiveTab;
update the watch callback in CodeTabs.vue to only assign activeTab.value when
the resolved index differs from the current activeTab.value (i.e., after
computing index from props.languages, check index !== -1 && activeTab.value !==
index before setting activeTab.value) so setActiveTab and the watcher don't
perform the same assignment twice.
- Around line 43-46: The current fallback in CodeTabs.vue auto-assigns
globalActiveLanguage.value (the else-if branch) which triggers the module-level
watcher and writes a default into localStorage; remove that auto-assignment so
no default is persisted on mount, and ensure persistence happens only when the
user explicitly changes tabs by writing to localStorage inside setActiveTab (or
by having setActiveTab call a helper that sets globalActiveLanguage and writes
to localStorage). Also remove or adjust the module-level watcher that
unconditionally writes globalActiveLanguage to localStorage so it no longer
persists programmatic/initial assignments—only persist inside the user-action
pathway implemented by setActiveTab.

<script>
import { ref, watch, onMounted, nextTick } from 'vue'

const GLOBAL_LANG_KEY = 'java'
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

GLOBAL_LANG_KEY holds a language name instead of a storage key identifier.

The constant value 'java' is a language name, not a storage key. This means all preferences are stored under localStorage.key = 'java' (e.g., localStorage.setItem('java', 'C++') when C++ is selected). The name GLOBAL_LANG_KEY strongly implies it should hold a descriptive key identifier like 'preferred-language'.

🐛 Proposed fix
-const GLOBAL_LANG_KEY = 'java'
+const GLOBAL_LANG_KEY = 'preferred-language'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const GLOBAL_LANG_KEY = 'java'
const GLOBAL_LANG_KEY = 'preferred-language'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.vitepress/theme/components/CodeTabs.vue at line 4, GLOBAL_LANG_KEY
currently holds a language name ('java') instead of a descriptive storage key;
change its value to a clear identifier like 'preferred-language' and update all
usages (e.g., localStorage.getItem(GLOBAL_LANG_KEY),
localStorage.setItem(GLOBAL_LANG_KEY, ...)) so preferences are stored under that
key; ensure any code referencing GLOBAL_LANG_KEY (the constant itself in
CodeTabs.vue and any methods that read/write localStorage) continues to work
without semantic changes.

Comment on lines +58 to +61
const setActiveTab = (index) => {
activeTab.value = index
globalActiveLanguage.value = props.languages[index].name
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Missing bounds check before accessing props.languages[index].

props.languages[index].name is accessed without verifying that index is within the array bounds. While v-for in the template makes an out-of-range call unlikely, a defensive guard prevents a potential runtime crash if setActiveTab is ever called programmatically:

🛡️ Proposed fix
 const setActiveTab = (index) => {
+  if (index < 0 || index >= props.languages.length) return
   activeTab.value = index
   globalActiveLanguage.value = props.languages[index].name
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const setActiveTab = (index) => {
activeTab.value = index
globalActiveLanguage.value = props.languages[index].name
}
const setActiveTab = (index) => {
if (index < 0 || index >= props.languages.length) return
activeTab.value = index
globalActiveLanguage.value = props.languages[index].name
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.vitepress/theme/components/CodeTabs.vue around lines 58 - 61, The
setActiveTab function accesses props.languages[index].name without validating
index; add a defensive bounds check in setActiveTab (referencing setActiveTab,
activeTab, globalActiveLanguage, and props.languages) so it only reads
props.languages[index].name when index >= 0 && index < props.languages.length;
if the index is out of range, still set activeTab (or bail) and set
globalActiveLanguage to a safe fallback (e.g., props.languages[0]?.name or an
empty string) to avoid runtime crashes when called programmatically.

@RAJ8664 RAJ8664 deleted the default-language branch February 23, 2026 05:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Able to choose a default language, so we dont have to switch to that language everytime...

1 participant