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">, -) => ( -
- - -
-); +) => ; 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 ( +
+ + +
+ ); +};