Skip to content

Commit

Permalink
Merge pull request #13541 from ethereum/shadcn-search
Browse files Browse the repository at this point in the history
Shadcn migration - search modal
  • Loading branch information
wackerow authored Aug 13, 2024
2 parents 096e581 + bbeeccc commit 2fb4687
Show file tree
Hide file tree
Showing 12 changed files with 238 additions and 359 deletions.
55 changes: 12 additions & 43 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@
"env": {
"es6": true
},
"plugins": [
"simple-import-sort",
"@typescript-eslint",
"unused-imports"
],
"plugins": ["simple-import-sort", "@typescript-eslint", "unused-imports"],
"parser": "@typescript-eslint/parser",
"rules": {
"simple-import-sort/imports": [
Expand All @@ -26,55 +22,29 @@
],
// Packages. `react` related packages come first.
// Also, put `react-icons` in sorting order not with `react`
[
"^react(?!-.)$",
"^\\w",
"^@\\w"
],
["^react(?!-.)$", "^\\w", "^@\\w"],
// The Chakra theme directory if imported to story file or other places
[
"^@/@chakra-ui"
],
["^@/@chakra-ui"],
// From the `types` directory.
[
"^@/lib/types",
"^@/lib/interfaces"
],
["^@/lib/types", "^@/lib/interfaces"],
// From the `components` directory.
[
"^@/components"
],
["^@/components"],
// From the `utils` directory.
[
"^@/lib/utils"
],
["^@/lib/utils"],
// From the `data` directory.
[
"^@/data"
],
["^@/data"],
// From the `constants` directory.
["^@/lib/constants"],
// From the `.storybook/utils` file
["^@/storybook-utils"],
// Parent imports. Put `..` last.
[
"^\\.\\.(?!/?$)",
"^\\.\\./?$"
],
["^\\.\\.(?!/?$)", "^\\.\\./?$"],
// Other relative imports. Put same-folder imports and `.` last.
[
"^\\./(?=.*/)(?!/?$)",
"^\\.(?!/?$)",
"^\\./?$"
],
["^\\./(?=.*/)(?!/?$)", "^\\.(?!/?$)", "^\\./?$"],
// Style imports.
[
"^.+\\.s?css$"
],
["^.+s?css$"],
// Side effect imports.
[
"^\\u0000"
]
["^\\u0000"]
]
}
],
Expand All @@ -89,7 +59,7 @@
],
"unused-imports/no-unused-vars": [
"error",
{
{
"args": "all",
"argsIgnorePattern": "^_$",
"varsIgnorePattern": "^_$"
Expand All @@ -98,4 +68,3 @@
"unused-imports/no-unused-imports-ts": "warn"
}
}

2 changes: 2 additions & 0 deletions .storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import ThemeProvider from "@/components/ThemeProvider"

import i18n, { baseLocales } from "./i18next"

import "@docsearch/css"
import "../src/styles/global.css"
import "../src/styles/fonts.css"
import "../src/styles/docsearch.css"

MotionGlobalConfig.skipAnimations = isChromatic()

Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@
"@next/bundle-analyzer": "^14.2.5",
"@radix-ui/react-accordion": "^1.2.0",
"@radix-ui/react-checkbox": "^1.1.1",
"@radix-ui/react-compose-refs": "^1.1.0",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-navigation-menu": "^1.2.0",
"@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-portal": "^1.1.1",
"@radix-ui/react-progress": "^1.1.0",
"@radix-ui/react-radio-group": "^1.2.0",
"@radix-ui/react-slot": "^1.1.0",
Expand Down
3 changes: 2 additions & 1 deletion src/components/Nav/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { lazy, Suspense, useRef } from "react"
import { useTranslation } from "next-i18next"
import { Box, Flex, Hide, Show, useDisclosure } from "@chakra-ui/react"
import { Box, Flex, Hide, Show } from "@chakra-ui/react"

import { EthHomeIcon } from "@/components/icons"
import { BaseLink } from "@/components/Link"
Expand All @@ -14,6 +14,7 @@ import DesktopNavMenu from "./Desktop"
import Menu from "./Menu"
import { useNav } from "./useNav"

import { useDisclosure } from "@/hooks/useDisclosure"
import { useIsClient } from "@/hooks/useIsClient"

const MobileNavMenu = lazy(() => import("./Mobile"))
Expand Down
27 changes: 19 additions & 8 deletions src/components/Search/SearchButton.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
import * as React from "react"
import { Button, forwardRef } from "@chakra-ui/react"
import { DocSearchButton, DocSearchButtonProps } from "@docsearch/react"
import { useTranslation } from "react-i18next"
import { DocSearchButton } from "@docsearch/react"

import { getSearchButtonStyles } from "./utils"
import { Button, type ButtonProps } from "../ui/buttons/Button"

const SearchButton = forwardRef<DocSearchButtonProps, "button">(
const SearchButton = React.forwardRef<HTMLButtonElement, ButtonProps>(
(props, ref) => {
const { t } = useTranslation("common")

return (
<Button
as={DocSearchButton}
ref={ref}
className="DocSearch-Button"
{...getSearchButtonStyles()}
variant="ghost"
className="me-3 border border-disabled hover:border-primary-hover"
{...props}
/>
asChild
>
<DocSearchButton
translations={{
buttonText: t("search"),
buttonAriaLabel: t("search"),
}}
/>
</Button>
)
}
)

SearchButton.displayName = "SearchButton"

export default SearchButton
25 changes: 8 additions & 17 deletions src/components/Search/SearchModal.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
import * as React from "react"
import { chakra } from "@chakra-ui/react"
import { DocSearchModal, DocSearchModalProps } from "@docsearch/react"

import { getSearchModalStyles } from "./utils"

type ModalPropsNoScroll = Omit<DocSearchModalProps, "initialScrollY">

const DocSearchModalWithChakra = chakra(
(props: ModalPropsNoScroll & { className?: string }) => {
const { className, ...docModalProps } = props
const windowScrollY = typeof window === "undefined" ? 0 : window.scrollY
return (
<div className={className}>
<DocSearchModal initialScrollY={windowScrollY} {...docModalProps} />
</div>
)
}
)

const SearchModal = (props: ModalPropsNoScroll) => {
return <DocSearchModalWithChakra {...props} sx={getSearchModalStyles()} />
const SearchModal = (props: ModalPropsNoScroll & { className?: string }) => {
const { className, ...docModalProps } = props
const windowScrollY = typeof window === "undefined" ? 0 : window.scrollY
return (
<div className={className}>
<DocSearchModal initialScrollY={windowScrollY} {...docModalProps} />
</div>
)
}

export default SearchModal
76 changes: 25 additions & 51 deletions src/components/Search/index.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,32 @@
import { useRef } from "react"
import { forwardRef, useRef } from "react"
import dynamic from "next/dynamic"
import { useRouter } from "next/router"
import { useTranslation } from "next-i18next"
import { MdSearch } from "react-icons/md"
import {
Box,
forwardRef,
IconButtonProps,
Portal,
ThemeTypings,
type UseDisclosureReturn,
useMergeRefs,
} from "@chakra-ui/react"
import { useDocSearchKeyboardEvents } from "@docsearch/react"
import { DocSearchHit } from "@docsearch/react/dist/esm/types"

import { Button } from "@/components/Buttons"
import { useComposedRefs } from "@radix-ui/react-compose-refs"
import * as Portal from "@radix-ui/react-portal"

import { trackCustomEvent } from "@/lib/utils/matomo"
import { sanitizeHitTitle } from "@/lib/utils/sanitizeHitTitle"
import { sanitizeHitUrl } from "@/lib/utils/url"

import { Button } from "../ui/buttons/Button"

import SearchButton from "./SearchButton"

import "@docsearch/css"
import { type useDisclosure } from "@/hooks/useDisclosure"

const SearchModal = dynamic(() => import("./SearchModal"))

export const SearchIconButton = forwardRef<IconButtonProps, "button">(
(props, ref) => (
<Button
ref={ref}
variant="ghost"
isSecondary
px={2}
_hover={{
color: "primary.base",
transform: "rotate(5deg)",
transition: "transform 0.2s ease-in-out",
}}
transition="transform 0.2s ease-in-out"
{...props}
>
<MdSearch />
</Button>
)
)
type Props = ReturnType<typeof useDisclosure>

type Props = Pick<UseDisclosureReturn, "isOpen" | "onOpen" | "onClose">

const Search = forwardRef<Props, "button">(
const Search = forwardRef<HTMLButtonElement, Props>(
({ isOpen, onOpen, onClose }, ref) => {
const { locale } = useRouter()
const searchButtonRef = useRef<HTMLButtonElement>(null)
const mergedButtonRefs = useMergeRefs(ref, searchButtonRef)
const mergedButtonRefs = useComposedRefs(ref, searchButtonRef)
const { t } = useTranslation("common")

useDocSearchKeyboardEvents({
Expand All @@ -68,11 +41,9 @@ const Search = forwardRef<Props, "button">(
const indexName =
process.env.NEXT_PUBLIC_ALGOLIA_BASE_SEARCH_INDEX_NAME || "ethereumorg"

const breakpointToken: ThemeTypings["breakpoints"] = "xl"

return (
<>
<Box hideBelow={breakpointToken}>
<div className="hidden xl:block">
<SearchButton
ref={mergedButtonRefs}
onClick={() => {
Expand All @@ -83,14 +54,14 @@ const Search = forwardRef<Props, "button">(
eventName: "search open",
})
}}
translations={{
buttonText: t("search"),
buttonAriaLabel: t("search"),
}}
/>
</Box>
<Box hideFrom={breakpointToken}>
<SearchIconButton
</div>
<div className="block xl:hidden">
<Button
ref={mergedButtonRefs}
className="px-2 transition-transform duration-200 ease-in-out hover:rotate-6 hover:text-primary"
variant="ghost"
isSecondary
onClick={() => {
onOpen()
trackCustomEvent({
Expand All @@ -99,11 +70,12 @@ const Search = forwardRef<Props, "button">(
eventName: "search open",
})
}}
ref={mergedButtonRefs}
aria-label={t("aria-toggle-search-button")}
/>
</Box>
<Portal>
>
<MdSearch />
</Button>
</div>
<Portal.Root>
{isOpen && (
<SearchModal
apiKey={apiKey}
Expand Down Expand Up @@ -171,10 +143,12 @@ const Search = forwardRef<Props, "button">(
}}
/>
)}
</Portal>
</Portal.Root>
</>
)
}
)

Search.displayName = "Search"

export default Search
Loading

0 comments on commit 2fb4687

Please sign in to comment.