From 07295373508bebc25a7ab0f5d062f6ca1ea45e9a Mon Sep 17 00:00:00 2001 From: Daniel Tschinder <231804+danez@users.noreply.github.com> Date: Sat, 16 Nov 2024 22:20:19 +0100 Subject: [PATCH] Update built-in components --- packages/website/package.json | 5 +- packages/website/src/components/Select.tsx | 131 +++++++++------------ packages/website/src/utils/usePopper.ts | 42 ------- pnpm-lock.yaml | 38 +----- 4 files changed, 61 insertions(+), 155 deletions(-) delete mode 100644 packages/website/src/utils/usePopper.ts diff --git a/packages/website/package.json b/packages/website/package.json index 2de7e238764..0e9ed64b066 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -14,14 +14,13 @@ "@codemirror/lang-javascript": "6.2.2", "@codemirror/lang-json": "6.0.1", "@codemirror/view": "6.34.1", - "@headlessui/react": "1.7.19", - "@popperjs/core": "2.11.8", + "@headlessui/react": "2.2.0", "@types/react": "18.3.11", "@types/react-dom": "18.3.1", "@uiw/react-codemirror": "4.23.5", "clsx": "2.1.1", "next": "14.2.16", - "next-themes": "0.3.0", + "next-themes": "0.4.3", "nextra": "3.2.3", "nextra-theme-docs": "3.2.3", "postcss": "8.4.47", diff --git a/packages/website/src/components/Select.tsx b/packages/website/src/components/Select.tsx index 8aae391b9b5..f0c6ed20782 100644 --- a/packages/website/src/components/Select.tsx +++ b/packages/website/src/components/Select.tsx @@ -1,10 +1,12 @@ -import type { ReactElement, ReactNode } from 'react'; +import { + Listbox, + ListboxButton, + ListboxOption, + ListboxOptions, +} from '@headlessui/react'; import cn from 'clsx'; -import { Listbox, Transition } from '@headlessui/react'; import { CheckIcon } from 'nextra/icons'; -import { usePopper } from '../utils/usePopper'; -import { createPortal } from 'react-dom'; -import { useMounted } from 'nextra/hooks'; +import type { ReactElement } from 'react'; interface MenuOption { key: string; @@ -26,82 +28,59 @@ export function Select({ title, className, }: MenuProps): ReactElement { - const [trigger, container] = usePopper({ - strategy: 'fixed', - placement: 'top-start', - modifiers: [ - { name: 'offset', options: { offset: [0, 10] } }, - { - name: 'sameWidth', - enabled: true, - fn({ state }) { - state.styles.popper.minWidth = `${state.rects.reference.width}px`; - }, - phase: 'beforeWrite', - requires: ['computeStyles'], - }, - ], - }); - return ( - {({ open }) => ( - + cn( + 'h-7 rounded-md px-2 text-xs font-medium transition-colors', open ? 'dark:bg-primary-100/10 bg-gray-200 text-gray-900 dark:text-gray-50' - : 'dark:hover:bg-primary-100/5 hover:bg-gray-100 hover:text-gray-900 dark:hover:text-gray-50', + : hover + ? 'dark:bg-primary-100/5 bg-gray-100 text-gray-900 dark:text-gray-50' + : 'text-gray-600 dark:text-gray-400', + focus && 'nextra-focusable', className, - )} - > - {selected.name} - - - {options.map((option) => ( - - cn( - active - ? 'bg-primary-50 text-primary-600 dark:bg-primary-500/10' - : 'text-gray-800 dark:text-gray-100', - 'relative cursor-pointer whitespace-nowrap py-1.5', - 'transition-colors ltr:pl-3 ltr:pr-9 rtl:pl-9 rtl:pr-3', - ) - } - > - {option.name} - {option.key === selected.key && ( - - - - )} - - ))} - - - - )} + ) + } + > + {selected.name} + + + cn( + 'nextra-focus', + open ? 'opacity-100' : 'opacity-0', + 'z-20 max-h-64 min-w-[--button-width] rounded-md border border-black/5 bg-[rgb(var(--nextra-bg),.8)] py-1 text-sm shadow-lg backdrop-blur-lg transition-opacity motion-reduce:transition-none dark:border-white/20', + ) + } + > + {options.map((option) => ( + + cn( + focus + ? 'bg-primary-50 text-primary-600 dark:bg-primary-500/10' + : 'text-gray-800 dark:text-gray-100', + 'cursor-pointer whitespace-nowrap px-3 py-1.5', + 'transition-colors', + option.key === selected.key && + 'flex items-center justify-between gap-3', + ) + } + > + {option.name} + {option.key === selected.key && } + + ))} + ); } - -function Portal(props: { children: ReactNode }): ReactElement | null { - const mounted = useMounted(); - - if (!mounted) return null; - - return createPortal(props.children, document.body); -} diff --git a/packages/website/src/utils/usePopper.ts b/packages/website/src/utils/usePopper.ts deleted file mode 100644 index 7caf347ba04..00000000000 --- a/packages/website/src/utils/usePopper.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { RefCallback } from 'react'; -import { useRef, useCallback, useMemo } from 'react'; -import type { Options } from '@popperjs/core'; -import { createPopper } from '@popperjs/core'; - -/** - * https://github.com/tailwindlabs/headlessui/issues/59 - * Example implementation to use Popper: https://popper.js.org - */ -export function usePopper( - options?: Partial, -): [RefCallback, RefCallback] { - const reference = useRef(null); - const popper = useRef(null); - - const cleanupCallback = useRef<() => void>(); - - const instantiatePopper = useCallback(() => { - if (!reference.current || !popper.current) return; - - cleanupCallback.current?.(); - cleanupCallback.current = createPopper( - reference.current, - popper.current, - options, - ).destroy; - }, [reference, popper, cleanupCallback, options]); - - return useMemo( - () => [ - (referenceDomNode) => { - reference.current = referenceDomNode; - instantiatePopper(); - }, - (popperDomNode) => { - popper.current = popperDomNode; - instantiatePopper(); - }, - ], - [reference, popper, instantiatePopper], - ); -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index efc3189f8f3..d0d04562e76 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -157,11 +157,8 @@ importers: specifier: 6.34.1 version: 6.34.1 '@headlessui/react': - specifier: 1.7.19 - version: 1.7.19(react-dom@18.3.1)(react@18.3.1) - '@popperjs/core': - specifier: 2.11.8 - version: 2.11.8 + specifier: 2.2.0 + version: 2.2.0(react-dom@18.3.1)(react@18.3.1) '@types/react': specifier: 18.3.11 version: 18.3.11 @@ -178,8 +175,8 @@ importers: specifier: 14.2.16 version: 14.2.16(react-dom@18.3.1)(react@18.3.1) next-themes: - specifier: 0.3.0 - version: 0.3.0(react-dom@18.3.1)(react@18.3.1) + specifier: 0.4.3 + version: 0.4.3(react-dom@18.3.1)(react@18.3.1) nextra: specifier: 3.2.3 version: 3.2.3(@types/react@18.3.11)(acorn@8.13.0)(next@14.2.16)(react-dom@18.3.1)(react@18.3.1)(typescript@5.6.3) @@ -1015,19 +1012,6 @@ packages: tslib: 2.8.0 dev: false - /@headlessui/react@1.7.19(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw==} - engines: {node: '>=10'} - peerDependencies: - react: ^16 || ^17 || ^18 - react-dom: ^16 || ^17 || ^18 - dependencies: - '@tanstack/react-virtual': 3.10.8(react-dom@18.3.1)(react@18.3.1) - client-only: 0.0.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - /@headlessui/react@2.2.0(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-RzCEg+LXsuI7mHiSomsu/gBJSjpupm6A1qIZ5sWjd7JhARNlMiSA4kKfJpCKwU9tE+zMRterhhrP74PvfJrpXQ==} engines: {node: '>=10'} @@ -1604,10 +1588,6 @@ packages: engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} dev: true - /@popperjs/core@2.11.8: - resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} - dev: false - /@react-aria/focus@3.18.4(react@18.3.1): resolution: {integrity: sha512-91J35077w9UNaMK1cpMUEFRkNNz0uZjnSwiyBCFuRdaVuivO53wNC9XtWSDNDdcO5cGy87vfJRVAiyoCn/mjqA==} peerDependencies: @@ -6628,16 +6608,6 @@ packages: resolution: {integrity: sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==} dev: true - /next-themes@0.3.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w==} - peerDependencies: - react: ^16.8 || ^17 || ^18 - react-dom: ^16.8 || ^17 || ^18 - dependencies: - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - /next-themes@0.4.3(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-nG84VPkTdUHR2YeD89YchvV4I9RbiMAql3GiLEQlPvq1ioaqPaIReK+yMRdg/zgiXws620qS1rU30TiWmmG9lA==} peerDependencies: