diff --git a/apps/developer-hub/src/components/Root/index.tsx b/apps/developer-hub/src/components/Root/index.tsx
index 3ac4818b0f..13241c3c27 100644
--- a/apps/developer-hub/src/components/Root/index.tsx
+++ b/apps/developer-hub/src/components/Root/index.tsx
@@ -2,13 +2,15 @@ import { AppShell } from "@pythnetwork/component-library/AppShell";
import { RootProvider as FumadocsRootProvider } from "fumadocs-ui/provider";
import { NuqsAdapter } from "nuqs/adapters/next/app";
import type { ReactNode } from "react";
-import "./global.css";
import {
AMPLITUDE_API_KEY,
ENABLE_ACCESSIBILITY_REPORTING,
GOOGLE_ANALYTICS_ID,
} from "../../config/server";
+import { SearchButton } from "../search-button";
+
+import "./global.css";
export const TABS = [
{ segment: "", children: "Home" },
@@ -23,14 +25,28 @@ type Props = {
};
export const Root = ({ children }: Props) => (
-
- {children}
-
+ }
+ mainCta={{
+ label: "Insights",
+ href: "https://insights.pyth.network/",
+ }}
+ providers={[NuqsAdapter]}
+ tabs={TABS}
+ >
+ {children}
+
+
);
diff --git a/apps/developer-hub/src/components/search-button.tsx b/apps/developer-hub/src/components/search-button.tsx
new file mode 100644
index 0000000000..f02e978860
--- /dev/null
+++ b/apps/developer-hub/src/components/search-button.tsx
@@ -0,0 +1,29 @@
+"use client";
+
+import { SearchButton as SearchButtonComponent } from "@pythnetwork/component-library/SearchButton";
+import DefaultSearchDialog from "fumadocs-ui/components/dialog/search-default";
+import { useCallback, useState } from "react";
+
+export const SearchButton = () => {
+ const [open, setOpen] = useState(false);
+
+ const handleSearch = useCallback(() => {
+ setOpen(true);
+ }, []);
+
+ return (
+ <>
+
+
+ >
+ );
+};
diff --git a/apps/developer-hub/src/config/layout.config.tsx b/apps/developer-hub/src/config/layout.config.tsx
index f0a50f1058..2c80fba569 100644
--- a/apps/developer-hub/src/config/layout.config.tsx
+++ b/apps/developer-hub/src/config/layout.config.tsx
@@ -5,31 +5,20 @@ import { source } from "../source";
export const baseOptions: BaseLayoutProps = {
nav: {
- enabled: false,
+ enabled: true,
},
themeSwitch: {
enabled: false,
},
+ searchToggle: {
+ enabled: false,
+ },
};
export const docsOptions: DocsLayoutProps = {
...baseOptions,
tree: source.pageTree,
sidebar: {
- tabs: {
- transform(option, node) {
- const meta = source.getNodeMeta(node);
- if (!meta || !node.icon) return option;
-
- return {
- ...option,
- icon: (
-
- {node.icon}
-
- ),
- };
- },
- },
+ tabs: false,
},
};
diff --git a/apps/insights/src/components/Root/search-button.module.scss b/apps/insights/src/components/Root/search-button.module.scss
index dea6dcc8a7..9e5753cc52 100644
--- a/apps/insights/src/components/Root/search-button.module.scss
+++ b/apps/insights/src/components/Root/search-button.module.scss
@@ -1,21 +1,5 @@
@use "@pythnetwork/component-library/theme";
-.searchButton {
- .largeScreenSearchButton {
- display: none;
-
- @include theme.breakpoint("md") {
- display: inline-flex;
- }
- }
-
- .smallScreenSearchButton {
- @include theme.breakpoint("md") {
- display: none;
- }
- }
-}
-
.searchDialogContents {
gap: theme.spacing(1);
display: flex;
diff --git a/apps/insights/src/components/Root/search-button.tsx b/apps/insights/src/components/Root/search-button.tsx
index b604e6122b..9d98fd5674 100644
--- a/apps/insights/src/components/Root/search-button.tsx
+++ b/apps/insights/src/components/Root/search-button.tsx
@@ -1,14 +1,13 @@
"use client";
-import { MagnifyingGlass } from "@phosphor-icons/react/dist/ssr/MagnifyingGlass";
import { XCircle } from "@phosphor-icons/react/dist/ssr/XCircle";
import { Badge } from "@pythnetwork/component-library/Badge";
import type { Props as ButtonProps } from "@pythnetwork/component-library/Button";
import { Button } from "@pythnetwork/component-library/Button";
import { NoResults } from "@pythnetwork/component-library/NoResults";
+import { SearchButton as SearchButtonComponent } from "@pythnetwork/component-library/SearchButton";
import { SearchInput } from "@pythnetwork/component-library/SearchInput";
import { SingleToggleGroup } from "@pythnetwork/component-library/SingleToggleGroup";
-import { Skeleton } from "@pythnetwork/component-library/Skeleton";
import {
ListLayout,
Virtualizer,
@@ -23,7 +22,6 @@ import { useLogger } from "@pythnetwork/component-library/useLogger";
import { matchSorter } from "match-sorter";
import type { ReactNode } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
-import { useIsSSR } from "react-aria";
import { Cluster, ClusterToName } from "../../services/pyth";
import { AssetClassBadge } from "../AssetClassBadge";
@@ -74,31 +72,7 @@ const ResolvedSearchButton = (props: ResolvedSearchButtonProps) => {
const SearchButtonImpl = (
props: Omit, "children">,
-) => (
-
- }
- size="sm"
- rounded
- {...props}
- >
-
-
- }
- size="sm"
- rounded
- {...props}
- >
- Search
-
-
-);
+) => ;
const useSearchDrawer = ({ feeds, publishers }: ResolvedSearchButtonProps) => {
const drawer = useDrawer();
@@ -152,16 +126,6 @@ const useSearchHotkey = (openSearchDrawer: () => void) => {
}, [handleKeyDown]);
};
-const SearchShortcutText = () => {
- const isSSR = useIsSSR();
- return isSSR ? : ;
-};
-
-const SearchTextImpl = () => {
- const isMac = useMemo(() => navigator.userAgent.includes("Mac"), []);
- return isMac ? "⌘ K" : "Ctrl K";
-};
-
type SearchDialogContentsProps = ResolvedSearchButtonProps;
const SearchDialogContents = ({
diff --git a/packages/component-library/src/SearchButton/index.module.scss b/packages/component-library/src/SearchButton/index.module.scss
new file mode 100644
index 0000000000..05a3643b3d
--- /dev/null
+++ b/packages/component-library/src/SearchButton/index.module.scss
@@ -0,0 +1,17 @@
+@use "../theme";
+
+.searchButton {
+ .largeScreenSearchButton {
+ display: none;
+
+ @include theme.breakpoint("md") {
+ display: inline-flex;
+ }
+ }
+
+ .smallScreenSearchButton {
+ @include theme.breakpoint("md") {
+ display: none;
+ }
+ }
+}
diff --git a/packages/component-library/src/SearchButton/index.stories.tsx b/packages/component-library/src/SearchButton/index.stories.tsx
new file mode 100644
index 0000000000..5df1ea8b96
--- /dev/null
+++ b/packages/component-library/src/SearchButton/index.stories.tsx
@@ -0,0 +1,44 @@
+import * as icons from "@phosphor-icons/react/dist/ssr";
+import type { Meta, StoryObj } from "@storybook/react";
+
+import { SearchButton as SearchButtonComponent } from "./index.jsx";
+import { SIZES } from "../Button/index.jsx";
+
+const iconControl = {
+ control: "select",
+ options: Object.keys(icons),
+ mapping: Object.fromEntries(
+ Object.entries(icons).map(([iconName, Icon]) => [
+ iconName,
+ ,
+ ]),
+ ),
+} as const;
+
+const meta = {
+ component: SearchButtonComponent,
+ argTypes: {
+ size: {
+ control: "inline-radio",
+ options: SIZES,
+ table: {
+ category: "Variant",
+ },
+ },
+ beforeIcon: {
+ ...iconControl,
+ table: {
+ category: "Contents",
+ },
+ },
+ },
+} satisfies Meta;
+export default meta;
+
+export const SearchButton = {
+ args: {
+ largeScreenContent: "Search",
+ smallScreenContent: "Search",
+ size: "sm",
+ },
+} satisfies StoryObj;
diff --git a/packages/component-library/src/SearchButton/index.tsx b/packages/component-library/src/SearchButton/index.tsx
new file mode 100644
index 0000000000..ed93dbbf64
--- /dev/null
+++ b/packages/component-library/src/SearchButton/index.tsx
@@ -0,0 +1,67 @@
+"use client";
+
+import { MagnifyingGlass } from "@phosphor-icons/react/dist/ssr/MagnifyingGlass";
+import clsx from "clsx";
+import type { ReactNode } from "react";
+import { useMemo } from "react";
+import { useIsSSR } from "react-aria";
+import { Button as BaseButton } from "react-aria-components";
+
+import type { Props as ButtonProps } from "../Button";
+import { Button } from "../Button";
+import { Skeleton } from "../Skeleton";
+import styles from "./index.module.scss";
+
+type OwnProps = {
+ largeScreenContent?: ReactNode;
+ smallScreenContent?: ReactNode;
+};
+
+type Props = Pick<
+ ButtonProps,
+ "beforeIcon" | "size" | "onClick" | "className" | "isPending"
+> &
+ OwnProps;
+
+const SearchShortcutText = () => {
+ const isSSR = useIsSSR();
+ return isSSR ? : ;
+};
+
+const SearchTextImpl = () => {
+ const isMac = useMemo(() => navigator.userAgent.includes("Mac"), []);
+ return isMac ? "⌘ K" : "Ctrl K";
+};
+
+export const SearchButton = ({
+ beforeIcon,
+ largeScreenContent,
+ smallScreenContent,
+ ...props
+}: Props) => {
+ return (
+
+ }
+ size="sm"
+ rounded
+ {...props}
+ >
+ {largeScreenContent ?? }
+
+ }
+ size="sm"
+ rounded
+ {...props}
+ >
+ {smallScreenContent ?? }
+
+
+ );
+};