Skip to content

Commit 2fb4687

Browse files
authored
Merge pull request #13541 from ethereum/shadcn-search
Shadcn migration - search modal
2 parents 096e581 + bbeeccc commit 2fb4687

File tree

12 files changed

+238
-359
lines changed

12 files changed

+238
-359
lines changed

.eslintrc.json

Lines changed: 12 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@
99
"env": {
1010
"es6": true
1111
},
12-
"plugins": [
13-
"simple-import-sort",
14-
"@typescript-eslint",
15-
"unused-imports"
16-
],
12+
"plugins": ["simple-import-sort", "@typescript-eslint", "unused-imports"],
1713
"parser": "@typescript-eslint/parser",
1814
"rules": {
1915
"simple-import-sort/imports": [
@@ -26,55 +22,29 @@
2622
],
2723
// Packages. `react` related packages come first.
2824
// Also, put `react-icons` in sorting order not with `react`
29-
[
30-
"^react(?!-.)$",
31-
"^\\w",
32-
"^@\\w"
33-
],
25+
["^react(?!-.)$", "^\\w", "^@\\w"],
3426
// The Chakra theme directory if imported to story file or other places
35-
[
36-
"^@/@chakra-ui"
37-
],
27+
["^@/@chakra-ui"],
3828
// From the `types` directory.
39-
[
40-
"^@/lib/types",
41-
"^@/lib/interfaces"
42-
],
29+
["^@/lib/types", "^@/lib/interfaces"],
4330
// From the `components` directory.
44-
[
45-
"^@/components"
46-
],
31+
["^@/components"],
4732
// From the `utils` directory.
48-
[
49-
"^@/lib/utils"
50-
],
33+
["^@/lib/utils"],
5134
// From the `data` directory.
52-
[
53-
"^@/data"
54-
],
35+
["^@/data"],
5536
// From the `constants` directory.
5637
["^@/lib/constants"],
5738
// From the `.storybook/utils` file
5839
["^@/storybook-utils"],
5940
// Parent imports. Put `..` last.
60-
[
61-
"^\\.\\.(?!/?$)",
62-
"^\\.\\./?$"
63-
],
41+
["^\\.\\.(?!/?$)", "^\\.\\./?$"],
6442
// Other relative imports. Put same-folder imports and `.` last.
65-
[
66-
"^\\./(?=.*/)(?!/?$)",
67-
"^\\.(?!/?$)",
68-
"^\\./?$"
69-
],
43+
["^\\./(?=.*/)(?!/?$)", "^\\.(?!/?$)", "^\\./?$"],
7044
// Style imports.
71-
[
72-
"^.+\\.s?css$"
73-
],
45+
["^.+s?css$"],
7446
// Side effect imports.
75-
[
76-
"^\\u0000"
77-
]
47+
["^\\u0000"]
7848
]
7949
}
8050
],
@@ -89,7 +59,7 @@
8959
],
9060
"unused-imports/no-unused-vars": [
9161
"error",
92-
{
62+
{
9363
"args": "all",
9464
"argsIgnorePattern": "^_$",
9565
"varsIgnorePattern": "^_$"
@@ -98,4 +68,3 @@
9868
"unused-imports/no-unused-imports-ts": "warn"
9969
}
10070
}
101-

.storybook/preview.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ import ThemeProvider from "@/components/ThemeProvider"
77

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

10+
import "@docsearch/css"
1011
import "../src/styles/global.css"
1112
import "../src/styles/fonts.css"
13+
import "../src/styles/docsearch.css"
1214

1315
MotionGlobalConfig.skipAnimations = isChromatic()
1416

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,11 @@
3737
"@next/bundle-analyzer": "^14.2.5",
3838
"@radix-ui/react-accordion": "^1.2.0",
3939
"@radix-ui/react-checkbox": "^1.1.1",
40+
"@radix-ui/react-compose-refs": "^1.1.0",
4041
"@radix-ui/react-dialog": "^1.1.1",
4142
"@radix-ui/react-navigation-menu": "^1.2.0",
4243
"@radix-ui/react-popover": "^1.1.1",
44+
"@radix-ui/react-portal": "^1.1.1",
4345
"@radix-ui/react-progress": "^1.1.0",
4446
"@radix-ui/react-radio-group": "^1.2.0",
4547
"@radix-ui/react-slot": "^1.1.0",

src/components/Nav/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { lazy, Suspense, useRef } from "react"
22
import { useTranslation } from "next-i18next"
3-
import { Box, Flex, Hide, Show, useDisclosure } from "@chakra-ui/react"
3+
import { Box, Flex, Hide, Show } from "@chakra-ui/react"
44

55
import { EthHomeIcon } from "@/components/icons"
66
import { BaseLink } from "@/components/Link"
@@ -14,6 +14,7 @@ import DesktopNavMenu from "./Desktop"
1414
import Menu from "./Menu"
1515
import { useNav } from "./useNav"
1616

17+
import { useDisclosure } from "@/hooks/useDisclosure"
1718
import { useIsClient } from "@/hooks/useIsClient"
1819

1920
const MobileNavMenu = lazy(() => import("./Mobile"))
Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,32 @@
11
import * as React from "react"
2-
import { Button, forwardRef } from "@chakra-ui/react"
3-
import { DocSearchButton, DocSearchButtonProps } from "@docsearch/react"
2+
import { useTranslation } from "react-i18next"
3+
import { DocSearchButton } from "@docsearch/react"
44

5-
import { getSearchButtonStyles } from "./utils"
5+
import { Button, type ButtonProps } from "../ui/buttons/Button"
66

7-
const SearchButton = forwardRef<DocSearchButtonProps, "button">(
7+
const SearchButton = React.forwardRef<HTMLButtonElement, ButtonProps>(
88
(props, ref) => {
9+
const { t } = useTranslation("common")
10+
911
return (
1012
<Button
11-
as={DocSearchButton}
1213
ref={ref}
13-
className="DocSearch-Button"
14-
{...getSearchButtonStyles()}
14+
variant="ghost"
15+
className="me-3 border border-disabled hover:border-primary-hover"
1516
{...props}
16-
/>
17+
asChild
18+
>
19+
<DocSearchButton
20+
translations={{
21+
buttonText: t("search"),
22+
buttonAriaLabel: t("search"),
23+
}}
24+
/>
25+
</Button>
1726
)
1827
}
1928
)
2029

30+
SearchButton.displayName = "SearchButton"
31+
2132
export default SearchButton

src/components/Search/SearchModal.tsx

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,16 @@
11
import * as React from "react"
2-
import { chakra } from "@chakra-ui/react"
32
import { DocSearchModal, DocSearchModalProps } from "@docsearch/react"
43

5-
import { getSearchModalStyles } from "./utils"
6-
74
type ModalPropsNoScroll = Omit<DocSearchModalProps, "initialScrollY">
85

9-
const DocSearchModalWithChakra = chakra(
10-
(props: ModalPropsNoScroll & { className?: string }) => {
11-
const { className, ...docModalProps } = props
12-
const windowScrollY = typeof window === "undefined" ? 0 : window.scrollY
13-
return (
14-
<div className={className}>
15-
<DocSearchModal initialScrollY={windowScrollY} {...docModalProps} />
16-
</div>
17-
)
18-
}
19-
)
20-
21-
const SearchModal = (props: ModalPropsNoScroll) => {
22-
return <DocSearchModalWithChakra {...props} sx={getSearchModalStyles()} />
6+
const SearchModal = (props: ModalPropsNoScroll & { className?: string }) => {
7+
const { className, ...docModalProps } = props
8+
const windowScrollY = typeof window === "undefined" ? 0 : window.scrollY
9+
return (
10+
<div className={className}>
11+
<DocSearchModal initialScrollY={windowScrollY} {...docModalProps} />
12+
</div>
13+
)
2314
}
2415

2516
export default SearchModal

src/components/Search/index.tsx

Lines changed: 25 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,32 @@
1-
import { useRef } from "react"
1+
import { forwardRef, useRef } from "react"
22
import dynamic from "next/dynamic"
33
import { useRouter } from "next/router"
44
import { useTranslation } from "next-i18next"
55
import { MdSearch } from "react-icons/md"
6-
import {
7-
Box,
8-
forwardRef,
9-
IconButtonProps,
10-
Portal,
11-
ThemeTypings,
12-
type UseDisclosureReturn,
13-
useMergeRefs,
14-
} from "@chakra-ui/react"
156
import { useDocSearchKeyboardEvents } from "@docsearch/react"
167
import { DocSearchHit } from "@docsearch/react/dist/esm/types"
17-
18-
import { Button } from "@/components/Buttons"
8+
import { useComposedRefs } from "@radix-ui/react-compose-refs"
9+
import * as Portal from "@radix-ui/react-portal"
1910

2011
import { trackCustomEvent } from "@/lib/utils/matomo"
2112
import { sanitizeHitTitle } from "@/lib/utils/sanitizeHitTitle"
2213
import { sanitizeHitUrl } from "@/lib/utils/url"
2314

15+
import { Button } from "../ui/buttons/Button"
16+
2417
import SearchButton from "./SearchButton"
2518

26-
import "@docsearch/css"
19+
import { type useDisclosure } from "@/hooks/useDisclosure"
2720

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

30-
export const SearchIconButton = forwardRef<IconButtonProps, "button">(
31-
(props, ref) => (
32-
<Button
33-
ref={ref}
34-
variant="ghost"
35-
isSecondary
36-
px={2}
37-
_hover={{
38-
color: "primary.base",
39-
transform: "rotate(5deg)",
40-
transition: "transform 0.2s ease-in-out",
41-
}}
42-
transition="transform 0.2s ease-in-out"
43-
{...props}
44-
>
45-
<MdSearch />
46-
</Button>
47-
)
48-
)
23+
type Props = ReturnType<typeof useDisclosure>
4924

50-
type Props = Pick<UseDisclosureReturn, "isOpen" | "onOpen" | "onClose">
51-
52-
const Search = forwardRef<Props, "button">(
25+
const Search = forwardRef<HTMLButtonElement, Props>(
5326
({ isOpen, onOpen, onClose }, ref) => {
5427
const { locale } = useRouter()
5528
const searchButtonRef = useRef<HTMLButtonElement>(null)
56-
const mergedButtonRefs = useMergeRefs(ref, searchButtonRef)
29+
const mergedButtonRefs = useComposedRefs(ref, searchButtonRef)
5730
const { t } = useTranslation("common")
5831

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

71-
const breakpointToken: ThemeTypings["breakpoints"] = "xl"
72-
7344
return (
7445
<>
75-
<Box hideBelow={breakpointToken}>
46+
<div className="hidden xl:block">
7647
<SearchButton
7748
ref={mergedButtonRefs}
7849
onClick={() => {
@@ -83,14 +54,14 @@ const Search = forwardRef<Props, "button">(
8354
eventName: "search open",
8455
})
8556
}}
86-
translations={{
87-
buttonText: t("search"),
88-
buttonAriaLabel: t("search"),
89-
}}
9057
/>
91-
</Box>
92-
<Box hideFrom={breakpointToken}>
93-
<SearchIconButton
58+
</div>
59+
<div className="block xl:hidden">
60+
<Button
61+
ref={mergedButtonRefs}
62+
className="px-2 transition-transform duration-200 ease-in-out hover:rotate-6 hover:text-primary"
63+
variant="ghost"
64+
isSecondary
9465
onClick={() => {
9566
onOpen()
9667
trackCustomEvent({
@@ -99,11 +70,12 @@ const Search = forwardRef<Props, "button">(
9970
eventName: "search open",
10071
})
10172
}}
102-
ref={mergedButtonRefs}
10373
aria-label={t("aria-toggle-search-button")}
104-
/>
105-
</Box>
106-
<Portal>
74+
>
75+
<MdSearch />
76+
</Button>
77+
</div>
78+
<Portal.Root>
10779
{isOpen && (
10880
<SearchModal
10981
apiKey={apiKey}
@@ -171,10 +143,12 @@ const Search = forwardRef<Props, "button">(
171143
}}
172144
/>
173145
)}
174-
</Portal>
146+
</Portal.Root>
175147
</>
176148
)
177149
}
178150
)
179151

152+
Search.displayName = "Search"
153+
180154
export default Search

0 commit comments

Comments
 (0)