feat: add CodeTabs component for tabbed code blocks#2035
feat: add CodeTabs component for tabbed code blocks#2035
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
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 |
There was a problem hiding this comment.
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
CodeTabscomponent with tab syncing viasyncKeythat persists to localStorage and syncs across browser tabs - Remark plugin (
remarkCodeTabs) that transforms code blocks within<CodeTabs>intoCodeTabPanelelements at build time - Refactored
CodeBlockcomponent to extract reusable parts (CopyCodeButton, style classes) and addiconprop support - Extracted
HighlightedCodecomponent fromSyntaxHighlightwith 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
syncKeyis provided butsyncedTabKeyis not found in any panel (findIndex returns -1), theactiveIndexcalculation becomesMath.max(0, -1)which is 0. This is correct fallback behavior. However, ifpanelsis empty,panels.length - 1becomes -1, andMath.min(0, -1)results in -1 as the activeIndex. This could cause issues when trying to accesspanels.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.
0f43e9f to
3b85967
Compare
3b85967 to
c0cc57d
Compare
Summary
CodeTabsMDX component that groups multiple fenced code blocks into a tabbed UIsyncKey<CodeTabs>in MDX at build timePreview: https://zudoku-dev-git-feat-code-tabs.zuplosite.com/docs/components/code-tabs