diff --git a/src/client/app/composables/codeGroups.ts b/src/client/app/composables/codeGroups.ts
index d8a38ba72741..681630e9ad87 100644
--- a/src/client/app/composables/codeGroups.ts
+++ b/src/client/app/composables/codeGroups.ts
@@ -13,6 +13,38 @@ export function useCodeGroups() {
   }
 
   if (inBrowser) {
+    function syncMultipleCodeGroups(group: HTMLElement) {
+      const selector = group.className
+        .split(' ')
+        .filter(Boolean)
+        .map((c) => `.${c}`)
+        .join('')
+      let checkTabText =
+        group.querySelector('input:checked')?.nextElementSibling?.textContent ||
+        ''
+      document.querySelectorAll(selector).forEach((groupEl) => {
+        if (group === groupEl) {
+          return
+        }
+        const labels = groupEl.querySelectorAll('label')
+        if (!labels.length) return
+        const targetIndex = Array.from(labels).findIndex(
+          (label) => label.textContent === checkTabText
+        )
+        if (targetIndex < 0) return
+        const input = labels[targetIndex]
+          .previousElementSibling as HTMLInputElement
+        input.checked = true
+        const blocks = groupEl.querySelector('.blocks')
+        if (!blocks) return
+        const current = blocks.children[targetIndex]
+        if (!current) return
+        Array.from(blocks.children).forEach((child) => {
+          child.classList.remove('active')
+        })
+        blocks.children[targetIndex].classList.add('active')
+      })
+    }
     window.addEventListener('click', (e) => {
       const el = e.target as HTMLInputElement
 
@@ -38,6 +70,8 @@ export function useCodeGroups() {
         current.classList.remove('active')
         next.classList.add('active')
 
+        syncMultipleCodeGroups(group)
+
         const label = group?.querySelector(`label[for="${el.id}"]`)
         label?.scrollIntoView({ block: 'nearest' })
       }