diff --git a/packages/docs-app/src/blueprint.mdx b/packages/docs-app/src/blueprint.mdx
index 175e262505c..2a5b755e18f 100644
--- a/packages/docs-app/src/blueprint.mdx
+++ b/packages/docs-app/src/blueprint.mdx
@@ -25,9 +25,7 @@ Check out the [migration guides to upgrade from v5.x →](https://github.com/
home to over 40 UI components.
Install it with your Node.js package manager of choice:
-```sh copy
-pnpm add @blueprintjs/core react react-dom
-```
+@reactDocs InstallSnippet
Additional UI components and APIs are available in:
diff --git a/packages/docs-app/src/components/installSnippet.tsx b/packages/docs-app/src/components/installSnippet.tsx
new file mode 100644
index 00000000000..07abc70e4e1
--- /dev/null
+++ b/packages/docs-app/src/components/installSnippet.tsx
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2026 Palantir Technologies, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { CodeToggle, type CodeToggleTab } from "@blueprintjs/docs-theme";
+
+const PACKAGE_MANAGER_PREFERENCE_KEY = "bp-docs-pm-preference";
+
+const INSTALL_TARGET = "@blueprintjs/core react react-dom";
+
+// Append a new entry here to add another package manager (e.g. bun).
+const TABS: readonly CodeToggleTab[] = [
+ { code: `npm install ${INSTALL_TARGET}`, id: "npm", label: "npm" },
+ { code: `yarn add ${INSTALL_TARGET}`, id: "yarn", label: "yarn" },
+ { code: `pnpm add ${INSTALL_TARGET}`, id: "pnpm", label: "pnpm" },
+];
+
+/**
+ * Tabbed install snippet showing the same package across the supported
+ * package managers. The user's choice is persisted across pages so the docs
+ * remember which client the reader uses.
+ */
+export const InstallSnippet: React.FC = () => (
+
`. */
+ code: string;
+}
+
+export interface CodeToggleProps {
+ /**
+ * Tabs to render, in display order. The first tab is selected by default
+ * when no persisted preference is found.
+ */
+ tabs: readonly CodeToggleTab[];
+
+ /**
+ * Required `id` for the underlying `` element. Must be unique within
+ * the rendered page.
+ */
+ id: string;
+
+ /**
+ * If provided, the user's selection is persisted in `localStorage` under
+ * this key and shared across all `CodeToggle` instances using the same key.
+ * Useful for global preferences like the package manager choice.
+ */
+ storageKey?: string;
+}
+
+function readStoredPreference(storageKey: string | undefined, validIds: readonly string[]): string | undefined {
+ if (storageKey === undefined || typeof window === "undefined") {
+ return undefined;
+ }
+ const stored = window.localStorage.getItem(storageKey);
+ return stored != null && validIds.includes(stored) ? stored : undefined;
+}
+
+/**
+ * Generic tabbed code-snippet toggle. Each tab renders a `` with
+ * its corresponding snippet. When `storageKey` is provided, the selection is
+ * persisted in `localStorage` so the same choice carries across pages.
+ */
+export const CodeToggle: React.FC = ({ tabs, id, storageKey }) => {
+ const validIds = useMemo(() => tabs.map(t => t.id), [tabs]);
+ const defaultId = tabs[0]?.id ?? "";
+ const [selected, setSelected] = useState(defaultId);
+
+ // Hydrate from localStorage after mount to avoid SSR / first-render mismatches.
+ useEffect(() => {
+ const stored = readStoredPreference(storageKey, validIds);
+ if (stored !== undefined) {
+ setSelected(stored);
+ }
+ }, [storageKey, validIds]);
+
+ const handleChange = useCallback(
+ (newTabId: TabId) => {
+ const next = String(newTabId);
+ if (!validIds.includes(next)) {
+ return;
+ }
+ setSelected(next);
+ if (storageKey !== undefined && typeof window !== "undefined") {
+ window.localStorage.setItem(storageKey, next);
+ }
+ },
+ [storageKey, validIds],
+ );
+
+ return (
+
+ {tabs.map(tab => (
+
+ {tab.code}
+
+ }
+ />
+ ))}
+
+ );
+};
diff --git a/packages/docs-theme/src/index.ts b/packages/docs-theme/src/index.ts
index 2b2af5a7c01..9544d7b944c 100644
--- a/packages/docs-theme/src/index.ts
+++ b/packages/docs-theme/src/index.ts
@@ -18,6 +18,7 @@ export * from "./components/banner";
export * from "./components/documentation";
export * from "./components/example";
export * from "./components/codeExample";
+export * from "./components/codeToggle";
export * from "./components/navMenuItem";
export * from "./components/navButton";
export * from "./common";