diff --git a/package.json b/package.json index 843b04def630..d9ab9f67ff49 100644 --- a/package.json +++ b/package.json @@ -23,10 +23,10 @@ "devDependencies": { "@edgeandnode/eslint-config": "^2.0.3", "eslint": "^8.56.0", - "eslint-plugin-mdx": "^2.3.3", + "eslint-plugin-mdx": "^2.3.4", "husky": "^8.0.3", "lint-staged": "^15.2.0", - "prettier": "^3.2.2", + "prettier": "^3.2.4", "remark-frontmatter": "^5.0.0", "remark-lint-first-heading-level": "^3.1.2", "remark-lint-heading-increment": "^3.1.2", diff --git a/packages/nextra-theme/package.json b/packages/nextra-theme/package.json index 29c6afc34406..ec9dec037dd8 100644 --- a/packages/nextra-theme/package.json +++ b/packages/nextra-theme/package.json @@ -25,8 +25,8 @@ "typecheck": "tsc --noEmit" }, "peerDependencies": { - "@edgeandnode/gds": "3.0.0-analytics-1705417983862-638dd10aea79fa5729496361fefc704c7dd2d0b1", - "@edgeandnode/go": "4.0.0-analytics-1705417983862-638dd10aea79fa5729496361fefc704c7dd2d0b1", + "@edgeandnode/gds": "^3.0.0", + "@edgeandnode/go": "^4.0.0", "@emotion/react": "^11.11", "next": "^13", "next-seo": "^6", @@ -43,13 +43,13 @@ "react-use": "^17.4.3" }, "devDependencies": { - "@edgeandnode/gds": "3.0.0-analytics-1705417983862-638dd10aea79fa5729496361fefc704c7dd2d0b1", - "@edgeandnode/go": "4.0.0-analytics-1705417983862-638dd10aea79fa5729496361fefc704c7dd2d0b1", + "@edgeandnode/gds": "^3.3.0", + "@edgeandnode/go": "^4.3.0", "@emotion/react": "^11.11.3", "@types/lodash": "^4.14.202", "@types/react": "^18.2.48", "@types/react-dom": "^18.2.18", - "next": "^14.0.4", + "next": "^14.1.0", "next-seo": "^6.4.0", "nextra": "^2.13.2", "react": "^18.2.0", diff --git a/packages/nextra-theme/src/components/DocSearch.tsx b/packages/nextra-theme/src/components/DocSearch.tsx index bf6d289da923..0e2c871266e5 100644 --- a/packages/nextra-theme/src/components/DocSearch.tsx +++ b/packages/nextra-theme/src/components/DocSearch.tsx @@ -1,28 +1,30 @@ import { DocSearchModal, DocSearchProps, useDocSearchKeyboardEvents } from '@docsearch/react' -import { Global } from '@emotion/react' import { useCallback, useRef, useState } from 'react' import { createPortal } from 'react-dom' -import { Theme } from 'theme-ui' +import { Global } from 'theme-ui' import { BorderRadius, + BorderWidth, buildBorder, buildTransition, Flex, FontSize, FontWeight, Icon, + Link, Opacity, + Responsive, Spacing, Text, + useTheme, } from '@edgeandnode/gds' -const BREAKPOINT = '751px' - export function DocSearch(props: DocSearchProps) { const searchButtonRef = useRef(null) const [isOpen, setIsOpen] = useState(false) const [initialQuery, setInitialQuery] = useState(props.initialQuery || undefined) + const { theme } = useTheme() const onOpen = useCallback(() => { setIsOpen(true) @@ -49,37 +51,93 @@ export function DocSearch(props: DocSearchProps) { }) return ( -
- {/* TODO: Replace by `Chip` component when it's ready in the new GDS */} - + + - {isOpen - ? createPortal( + {isOpen ? ( + <> + {createPortal( , document.body, - ) - : null} - - ({ - html: { - '--docsearch-spacing': '0 !important', - '--docsearch-container-background': `${theme.colors!.Midnight88} !important`, - '--docsearch-modal-width': 'min(calc(100vw - 32px), 840px) !important', - '--docsearch-modal-background': '#292738 !important', - '--docsearch-modal-shadow': 'none !important', - '--docsearch-searchbox-height': '96px !important', - '--docsearch-searchbox-focus-background': 'transparent !important', - '--docsearch-searchbox-shadow': 'none !important', - '--docsearch-hit-background': 'transparent !important', - '--docsearch-hit-color': `${theme.colors!.White88} !important`, - '--docsearch-hit-active-color': `${theme.colors!.White} !important`, - '--docsearch-highlight-color': `${theme.colors!.Purple} !important`, - }, - '.DocSearch-Modal': { - border: buildBorder('White8')(theme), - overflow: 'hidden', - cursor: 'default', - [`@media (min-width: ${BREAKPOINT})`]: { - margin: '96px auto auto', - }, - }, - '.DocSearch-SearchBar': { - padding: `0 ${Spacing['24px']}`, - '&::after': { - content: `''`, - zIndex: 100, - position: 'absolute', - left: Spacing['24px'], - right: Spacing['24px'], - bottom: '-1px', - borderBottom: buildBorder('White16')(theme), - backgroundColor: 'var(--docsearch-modal-background)', - }, - }, - '.DocSearch-Form': { - padding: 0, - }, - '.DocSearch-MagnifierLabel, .DocSearch-LoadingIndicator': { - color: 'white', - svg: { - width: '18px', - height: '18px', - }, - }, - '.DocSearch-Input': { - padding: `${Spacing['32px']} ${Spacing['16px']}`, - outline: 'none', - fontSize: FontSize['18px'], - }, - '.DocSearch-Reset': { - padding: 0, - color: `${theme.colors!.White48}`, - transition: buildTransition('COLORS'), - '&:hover': { - color: `${theme.colors!.White}`, - }, - }, - '.DocSearch-Cancel': { - marginInlineStart: Spacing['16px'], - marginInlineEnd: Spacing['4px'], - color: 'inherit', - }, - '.DocSearch-Dropdown': { - maxHeight: 'calc(100vh - 96px)', - [`@media (min-width: ${BREAKPOINT})`]: { - maxHeight: 'max(192px, calc(100vh - 288px))', - }, - scrollPaddingTop: '32px', - }, - '.DocSearch-Dropdown-Container': { - padding: `${Spacing['24px']} ${Spacing['16px']}`, - paddingBottom: Spacing['64px'], - [`@media (min-width: ${BREAKPOINT})`]: { - padding: `${Spacing['24px']} ${Spacing['32px']}`, - }, - }, - '.DocSearch-Hits': { - width: 'auto', - '& + .DocSearch-Hits': { - marginTop: Spacing['16px'], - }, - mark: { - color: 'inherit', - textDecoration: 'underline', - }, - }, - '.DocSearch-Hit-source': { - margin: 0, - marginBottom: Spacing['2px'], - padding: `0 ${Spacing['16px']}`, - fontWeight: FontWeight.MEDIUM, - fontSize: FontSize['12px'], - textTransform: 'uppercase', - letterSpacing: '0.15em', - color: `${theme.colors!.White32}`, - }, - '.DocSearch-Hit': { - padding: 0, - a: { - padding: `0 ${Spacing['16px']}`, - borderRadius: BorderRadius.S, - }, - '&[aria-selected=true] a': { - backgroundColor: `${theme.colors!.White8}`, - }, - }, - '.DocSearch-Hit-Container': { - height: 'auto', - padding: `${Spacing['12px']} 0`, - }, - '.DocSearch-Hit-Tree': { - width: Spacing['16px'], - height: 0, - opacity: 0, - }, - '.DocSearch-Hit-icon': { - display: 'none', - }, - '.DocSearch-Hit-content-wrapper': { - margin: 0, - }, - '.DocSearch-Hit-title': { - fontSize: FontSize['16px'], - fontWeight: FontWeight.SEMIBOLD, - overflow: 'hidden', - textOverflow: 'ellipsis', - }, - '.DocSearch-Hit-path': { - marginTop: Spacing['4px'], - fontSize: FontSize['16px'], - fontWeight: FontWeight.REGULAR, - overflow: 'hidden', - textOverflow: 'ellipsis', - }, - '.DocSearch-Hit-action': { - marginInlineStart: Spacing['16px'], - }, - '.DocSearch-HitsFooter': { - display: 'none', - }, - '.DocSearch-Footer': { - position: 'fixed', - bottom: 0, - left: 0, - right: 0, - padding: Spacing['16px'], - backgroundColor: 'transparent', - boxShadow: 'none', - '&::before': { - content: `''`, - position: 'absolute', - left: 0, - right: 0, - top: 0, - bottom: 0, - backgroundColor: 'var(--docsearch-modal-background)', - opacity: Opacity['88%'], - [`@media (min-width: ${BREAKPOINT})`]: { + )} + -
+ }} + /> + + ) : null} + ) } diff --git a/packages/nextra-theme/src/index.tsx b/packages/nextra-theme/src/index.tsx index 6762b9d9057a..5338bc3c9b7e 100644 --- a/packages/nextra-theme/src/index.tsx +++ b/packages/nextra-theme/src/index.tsx @@ -3,7 +3,7 @@ import { NextSeo, NextSeoProps } from 'next-seo' import { NextraThemeLayoutProps } from 'nextra' import { useFSRoute } from 'nextra/hooks' import { MDXProvider } from 'nextra/mdx' -import { Item, normalizePages } from 'nextra/normalize-pages' +import { normalizePages } from 'nextra/normalize-pages' import { ReactElement, useCallback, useMemo } from 'react' import { useSet } from 'react-use' import { ThemeUICSSObject } from 'theme-ui' @@ -16,6 +16,7 @@ import { CodeBlock, CodeInline, Difficulty, + DocSearch, EditPageLink, Heading, Image, @@ -76,6 +77,7 @@ export { CodeBlock, CodeInline, Difficulty, + DocSearch, Heading, Image, LinkInline, @@ -176,7 +178,7 @@ export default function NextraLayout({ children, pageOpts, pageProps }: NextraTh -
+
@@ -184,7 +186,6 @@ export default function NextraLayout({ children, pageOpts, pageProps }: NextraTh
{args.activePath.length > 1 ? (
- {/* eslint-disable-next-line @typescript-eslint/no-unsafe-return -- i don't know why it's complain */} {args.activePath.map((item) => item.title).join(' > ')}
) : null} diff --git a/packages/nextra-theme/src/layout/MDXLayoutNav.tsx b/packages/nextra-theme/src/layout/MDXLayoutNav.tsx index 6554a9c1d177..36aae862bcb8 100644 --- a/packages/nextra-theme/src/layout/MDXLayoutNav.tsx +++ b/packages/nextra-theme/src/layout/MDXLayoutNav.tsx @@ -1,27 +1,13 @@ -import { DocSearchHit } from '@docsearch/react/dist/esm/types' import { keyframes } from '@emotion/react' import * as Collapsible from '@radix-ui/react-collapsible' -import { useRouter } from 'next/router' import { Item } from 'nextra/normalize-pages' import { Fragment, PropsWithChildren, useContext, useEffect, useState } from 'react' -import { - BorderRadius, - buildTransition, - Flex, - Icon, - Link, - NestedStrings, - Spacing, - Text, - useI18n, -} from '@edgeandnode/gds' +import { BorderRadius, buildTransition, Flex, Icon, Spacing, Text, useI18n } from '@edgeandnode/gds' -import { DocSearch, NavTree } from '@/components' +import { NavTree } from '@/components' import { NavContext } from '@/layout' -const removeBasePathFromUrl = (url: string) => url.substring((process.env.BASE_PATH ?? '').length) - const animationExpand = keyframes({ from: { height: 0 }, to: { height: 'var(--radix-collapsible-content-height)' }, @@ -48,8 +34,7 @@ const DesktopWrapper = ({ children }: PropsWithChildren<{}>) => { top: 'var(--gds-header-height-visible)', maxHeight: 'calc(100vh - var(--gds-header-height-visible))', paddingInlineEnd: Spacing['24px'], - pt: Spacing['32px'], - pb: Spacing['16px'], + py: Spacing['16px'], overflowY: 'auto', }} > @@ -129,55 +114,13 @@ const MobileWrapper = ({ title, children }: PropsWithChildren<{ title?: string } ) } -const DocSearchHit = ({ hit, children }: PropsWithChildren<{ hit: { url: string } }>) => ( - {children} -) - export const MDXLayoutNav = ({ mobile = false }: { mobile?: boolean }) => { - const router = useRouter() const { activePath, directories } = useContext(NavContext)! - const { t, translations, locale } = useI18n() - const Wrapper = mobile ? MobileWrapper : DesktopWrapper - const activePage = activePath.at(-1) || { route: '', title: '' } return ( -
- - items.map((item) => ({ - ...item, - url: item.url.replace('https://thegraph.com/docs', process.env.BASE_PATH ?? ''), - })) - } - hitComponent={DocSearchHit} - navigator={{ - navigate({ itemUrl }) { - void router.push(removeBasePathFromUrl(itemUrl)) - }, - navigateNewTab({ itemUrl }) { - const windowReference = window.open(itemUrl, '_blank', 'noopener') - if (windowReference) { - windowReference.focus() - } - }, - navigateNewWindow({ itemUrl }) { - window.open(itemUrl, '_blank', 'noopener') - }, - }} - translations={translations.docsearch as NestedStrings} - placeholder={t('docsearch.button.buttonText')} - /> -
{directories.map((pageItem) => (function renderSidebar(pageItem: Item) { diff --git a/packages/nextra-theme/src/layout/MDXLayoutOutline.tsx b/packages/nextra-theme/src/layout/MDXLayoutOutline.tsx index 898e3902821c..8c0a6fff75f5 100644 --- a/packages/nextra-theme/src/layout/MDXLayoutOutline.tsx +++ b/packages/nextra-theme/src/layout/MDXLayoutOutline.tsx @@ -1,13 +1,13 @@ import { useContext, useEffect, useState } from 'react' -import { buildTransition, Divider, Flex, Link, Spacing, Text, useI18n } from '@edgeandnode/gds' +import { buildTransition, Divider, Link, Spacing, Text, useI18n } from '@edgeandnode/gds' import { EditPageLink } from '@/components' import { DocumentContext } from '@/layout' export const MDXLayoutOutline = () => { const { headings, highlightedOutlineItemId } = useContext(DocumentContext)! - const [enableTransition, setEnableTransition] = useState(false) + const [_enableTransition, setEnableTransition] = useState(false) const { t } = useI18n() // Fix issue where the `translateY` is animated on initial load @@ -23,16 +23,14 @@ export const MDXLayoutOutline = () => { top: 'var(--gds-header-height-visible)', maxHeight: 'calc(100vh - var(--gds-header-height-visible))', px: Spacing['8px'], - py: Spacing['32px'], + py: Spacing['24px'], overflowY: 'auto', }} > - - - + {headings.length > 0 ? ( <> - +
+ [ + defaultContent, + null, + <> + {defaultContent} + {docSearch} + , + ]} + rightContent={(defaultContent) => [ + <> + {defaultContent} + {docSearch} + , + null, + defaultContent, + ]} + /> } headerSticky footer={}