Skip to content

Comments

feat: add CodeTabs component for tabbed code blocks#2035

Open
dan-lee wants to merge 1 commit intomainfrom
feat/code-tabs
Open

feat: add CodeTabs component for tabbed code blocks#2035
dan-lee wants to merge 1 commit intomainfrom
feat/code-tabs

Conversation

@dan-lee
Copy link
Contributor

@dan-lee dan-lee commented Feb 21, 2026

Summary

  • New CodeTabs MDX component that groups multiple fenced code blocks into a tabbed UI
  • Supports custom tab labels, language icons (npm/pnpm/yarn/bun), and synced tabs via syncKey
  • Remark plugin to transform <CodeTabs> in MDX at build time
  • Docs page with usage examples

Preview: https://zudoku-dev-git-feat-code-tabs.zuplosite.com/docs/components/code-tabs

Copilot AI review requested due to automatic review settings February 21, 2026 15:45
@dan-lee dan-lee added the feature Feature label Feb 21, 2026
@dan-lee dan-lee requested a review from mosch February 21, 2026 15:45
@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)
zudoku-cosmo-cargo Ready Ready Preview, Comment Feb 21, 2026 4:25pm
zudoku-dev Ready Ready Preview, Comment Feb 21, 2026 4:25pm

Request Review

@github-actions
Copy link

github-actions bot commented Feb 21, 2026

Preview build of published Zudoku package for commit c0cc57d.

See the deployment at: https://26a74c07.cosmocargo-public-package.pages.dev

Note

This is a preview of the Cosmo Cargo example using the Zudoku package published to a local registry to ensure it'll be working when published to the public NPM registry.

Last updated: 2026-02-21T16:27:29.850Z

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a new CodeTabs MDX component that provides tabbed code blocks, enabling developers to show multiple code examples (e.g., different languages or package managers) in a single, space-efficient UI. The implementation includes a build-time remark plugin that transforms fenced code blocks within <CodeTabs> tags, a React component with Zustand-powered tab synchronization across browser tabs, and support for package manager icons (npm, pnpm, yarn, bun).

Changes:

  • New CodeTabs component with tab syncing via syncKey that persists to localStorage and syncs across browser tabs
  • Remark plugin (remarkCodeTabs) that transforms code blocks within <CodeTabs> into CodeTabPanel elements at build time
  • Refactored CodeBlock component to extract reusable parts (CopyCodeButton, style classes) and add icon prop support
  • Extracted HighlightedCode component from SyntaxHighlight with graceful fallback when highlighter is unavailable
  • Added language icons for npm, pnpm, yarn, and bun package managers
  • Documentation page with usage examples and prop tables

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/zudoku/src/vite/plugin-mdx.ts Adds remarkCodeTabs plugin to MDX processing pipeline
packages/zudoku/src/vite/mdx/remark-code-tabs.ts Remark plugin that transforms fenced code blocks within CodeTabs into CodeTabPanel elements
packages/zudoku/src/lib/util/MdxComponents.tsx Registers CodeTabs/CodeTabPanel components and adds icon prop to code element, fixes regex pattern
packages/zudoku/src/lib/ui/SyntaxHighlight.tsx Extracts HighlightedCode component and adds fallback for missing highlighter
packages/zudoku/src/lib/ui/CodeTabs.tsx Main CodeTabs component with tab syncing, Zustand store, and HighlightedCode integration
packages/zudoku/src/lib/ui/CodeBlock.tsx Refactors to extract CopyCodeButton, style classes, and adds icon prop
packages/zudoku/src/lib/shiki.ts Extracts parseMetaString function, adds meta parameter to highlight function, strips pre wrapper
packages/zudoku/src/lib/components/LanguageIcon.tsx Adds pnpm, npm, yarn, and bun icon mappings with patterns
packages/zudoku/src/lib/assets/language-icons/*.tsx New SVG icon components for package managers
packages/zudoku/src/app/main.css Adjusts line width calculation for code blocks
docs/src/ThemeEditor.tsx Changes useEffect to useLayoutEffect for DOM manipulation (unrelated fix)
docs/sidebar.ts Adds code-tabs page to documentation sidebar
docs/pages/docs/components/code-tabs.mdx Documentation page with usage examples and API reference
Comments suppressed due to low confidence (2)

docs/pages/docs/components/code-tabs.mdx:159

  • There's a typo with an extra semicolon before the package variable. The semicolon should be removed.
    <CodeTabPanel language="sh" title="yarn" icon="yarn" code={`yarn add ;${pkg}`} />

packages/zudoku/src/lib/ui/CodeTabs.tsx:106

  • When syncKey is provided but syncedTabKey is not found in any panel (findIndex returns -1), the activeIndex calculation becomes Math.max(0, -1) which is 0. This is correct fallback behavior. However, if panels is empty, panels.length - 1 becomes -1, and Math.min(0, -1) results in -1 as the activeIndex. This could cause issues when trying to access panels.at(-1) (which returns the last element) or when setting the TabsPrimitive.Root value to "-1". Consider adding an early return or guard when panels array is empty.
  const activeIndex = Math.min(
    Math.max(0, syncKey ? syncedIndex : localTab),
    panels.length - 1,
  );

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant