Skip to content

fix(theme): align CodeSnippets outer tab with Docusaurus storage slot#1464

Merged
sserrata merged 3 commits into
PaloAltoNetworks:mainfrom
zohuyhieuzo03:fix/code-samples-tab-storage-slot
May 19, 2026
Merged

fix(theme): align CodeSnippets outer tab with Docusaurus storage slot#1464
sserrata merged 3 commits into
PaloAltoNetworks:mainfrom
zohuyhieuzo03:fix/code-samples-tab-storage-slot

Conversation

@zohuyhieuzo03
Copy link
Copy Markdown
Contributor

@zohuyhieuzo03 zohuyhieuzo03 commented May 12, 2026

Summary

Aligns CodeSnippets outer language tab persistence with Docusaurus <Tabs groupId="code-samples"> by reading the same namespaced storage key via createStorageSlot, so the selected tab and rendered snippet stay in sync after refresh.

Changes

  • Theme (CodeSnippets): Replace raw localStorage.getItem('docusaurus.tab.code-samples') with createStorageSlot('docusaurus.tab.code-samples').get().
  • Theme (CodeSnippets): Derive a single initialOuterLanguage for useState and the outer CodeTabs defaultValue.
  • Theme (CodeSnippets): When multiple languages exist and nothing valid is persisted, prefer curl, then the first language.

Files Changed

Path Change
packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/CodeSnippets/index.tsx Modified (+22 / −14)

Testing

  1. npx eslint packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/CodeSnippets/index.tsx — clean locally.
  2. Manual: open a REST operation page with multiple code-sample languages, switch the outer tab, hard-refresh; active tab and snippet should match the persisted choice.
  3. Full yarn lint / yarn test: rely on PR CI (AGENTS.md; Node 20.19+ as in CI).

Related Issues

None.

CodeSnippets used raw localStorage key docusaurus.tab.code-samples, but
Docusaurus Tabs persist groupId with a namespaced key via createStorageSlot.
Align reads and default tab value; prefer curl when no persisted match.

Co-authored-by: Cursor <cursoragent@cursor.com>
@sserrata
Copy link
Copy Markdown
Member

Thanks for the PR — using createStorageSlot over raw localStorage is the right direction and the SSR guard is a nice improvement.

One suggestion before we merge: Docusaurus exports a useStorageSlot hook that handles both the SSR guard and reactivity for you, which would simplify this further:

const [persistedOuterLanguage] = useStorageSlot("docusaurus.tab.code-samples");

This would replace the IIFE + typeof window check and also means the component would re-render if the storage value changes (e.g., user switches tabs on another page and navigates back).

What do you think about switching to useStorageSlot? Happy to discuss tradeoffs if you have concerns.

@zohuyhieuzo03
Copy link
Copy Markdown
Contributor Author

Thanks — agreed. I’ll switch to useStorageSlot("docusaurus.tab.code-samples") so we rely on Docusaurus’ built-in SSR handling and stay reactive when the persisted tab changes. I’ll push an update shortly.

Replace createStorageSlot + window guard with Docusaurus useStorageSlot
for SSR-safe reads and storage reactivity. Memoize mergedLangs and sync
language state when persisted tab or language list changes.

Co-authored-by: Cursor <cursoragent@cursor.com>
@zohuyhieuzo03
Copy link
Copy Markdown
Contributor Author

I’ve updated the PR to use useStorageSlot("docusaurus.tab.code-samples") instead of the manual SSR guard + createStorageSlot().get(). I also memoized mergedLangs and added a small effect to keep language in sync when the persisted tab changes (or when the merged language list changes) so the outer tab state stays aligned with storage, not just on the initial read.

Let me know if you’d like any tweaks to that sync behavior.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 14, 2026

Visit the preview URL for this PR (updated for commit 85ce80c):

https://docusaurus-openapi-36b86--pr1464-vi2c1690.web.app

(expires Mon, 25 May 2026 20:14:02 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: bf293780ee827f578864d92193b8c2866acd459f

Copy link
Copy Markdown
Member

@sserrata sserrata left a comment

Choose a reason for hiding this comment

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

Thanks for the PR — the core change (switching to useStorageSlot) is solid and improves SSR safety.

However, the curl fallback in resolveOuterLanguageFromPersistedTab is a behavior regression:

return langs.find((l) => l.language === "curl") ?? langs[0];

When nothing is persisted in storage (first visit, cleared storage), this forces curl as the default regardless of the user's languageTabs ordering in docusaurus.config.js. The original code used mergedLangs[0], which respected the configured order.

Fix: change the fallback to just return langs[0]; — the array already reflects the user-defined ordering, so the first element is the correct default.

Update the default language selection logic in CodeSnippets to always return the first language in the list, removing the preference for "curl" when no match is found. This change streamlines the behavior and ensures a consistent fallback.
@zohuyhieuzo03
Copy link
Copy Markdown
Contributor Author

Thanks for the comment. I just updated it

@sserrata sserrata merged commit 963f846 into PaloAltoNetworks:main May 19, 2026
11 checks passed
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.

2 participants