feat(graph): update headlessui v2 (#29586)

This PR updates `headlessui/react` to v2 so that it is compatible with
the new graph library. This also bumps `preact` to `10.25` for `useId`
compat.
This commit is contained in:
Chau Tran 2025-01-13 10:52:23 -06:00 committed by GitHub
parent a352c81876
commit 669af5559f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 331 additions and 143 deletions

View File

@ -1,4 +1,10 @@
import { Menu, Transition } from '@headlessui/react';
import {
Menu,
MenuButton,
MenuItem,
MenuItems,
Transition,
} from '@headlessui/react';
import {
ComputerDesktopIcon,
MoonIcon,
@ -28,7 +34,7 @@ export function ThemePanel({
return (
<Menu as="div" className="relative inline-block text-left">
<div>
<Menu.Button
<MenuButton
className="inline-flex w-full justify-center rounded-md p-2 text-sm font-medium focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 dark:text-sky-500"
data-cy="theme-open-modal-button"
>
@ -42,7 +48,7 @@ export function ThemePanel({
{theme === 'dark' && (
<MoonIcon className="h-4 w-4" aria-hidden="true" />
)}
</Menu.Button>
</MenuButton>
</div>
<Transition
as={Fragment}
@ -53,15 +59,15 @@ export function ThemePanel({
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute right-0 z-50 mt-2 w-36 origin-top-right rounded-md bg-white text-slate-500 shadow-lg ring-1 ring-slate-900/10 ring-opacity-5 focus:outline-none dark:bg-slate-800 dark:text-slate-400 dark:ring-0">
<MenuItems className="absolute right-0 z-50 mt-2 w-36 origin-top-right rounded-md bg-white text-slate-500 shadow-lg ring-1 ring-slate-900/10 ring-opacity-5 focus:outline-none dark:bg-slate-800 dark:text-slate-400 dark:ring-0">
<div className="px-1 py-1">
<Menu.Item>
{({ active }) => (
<MenuItem>
{({ focus }) => (
<button
data-cy="system-theme-button"
className={classNames(
theme === 'system' ? 'text-blue-500 dark:text-sky-500' : '',
active ? 'bg-slate-50 dark:bg-slate-600/30' : '',
focus ? 'bg-slate-50 dark:bg-slate-600/30' : '',
'group flex w-full items-center rounded-md px-2 py-2 text-sm'
)}
onClick={() => setTheme('system')}
@ -73,14 +79,14 @@ export function ThemePanel({
System
</button>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
</MenuItem>
<MenuItem>
{({ focus }) => (
<button
data-cy="light-theme-button"
className={classNames(
theme === 'light' ? 'text-blue-500 dark:text-sky-500' : '',
active ? 'bg-slate-50 dark:bg-slate-600/30' : '',
focus ? 'bg-slate-50 dark:bg-slate-600/30' : '',
'group flex w-full items-center rounded-md px-2 py-2 text-sm'
)}
onClick={() => setTheme('light')}
@ -89,14 +95,14 @@ export function ThemePanel({
Light
</button>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
</MenuItem>
<MenuItem>
{({ focus }) => (
<button
data-cy="dark-theme-button"
className={classNames(
theme === 'dark' ? 'text-blue-500 dark:text-sky-500' : '',
active ? 'bg-slate-50 dark:bg-slate-600/30' : '',
focus ? 'bg-slate-50 dark:bg-slate-600/30' : '',
'group flex w-full items-center rounded-md px-2 py-2 text-sm'
)}
onClick={() => setTheme('dark')}
@ -105,9 +111,9 @@ export function ThemePanel({
Dark
</button>
)}
</Menu.Item>
</MenuItem>
</div>
</Menu.Items>
</MenuItems>
</Transition>
</Menu>
);

View File

@ -1,4 +1,11 @@
import { Dialog, Transition } from '@headlessui/react';
import {
Description,
Dialog,
DialogPanel,
DialogTitle,
Transition,
TransitionChild,
} from '@headlessui/react';
import { ChangeEvent, Fragment, useMemo, useState } from 'react';
import { GithubIcon } from '@nx/nx-dev/ui-common';
import { cx } from '@nx/nx-dev/ui-primitives';
@ -58,7 +65,7 @@ function FeedbackDialog({
return (
<Transition appear show={isOpen} as={Fragment}>
<Dialog open={isOpen} onClose={closeDialog} className="relative z-50">
<Transition.Child
<TransitionChild
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
@ -72,12 +79,12 @@ function FeedbackDialog({
className="fixed inset-0 bg-black/10 backdrop-blur-sm dark:bg-white/10"
aria-hidden="true"
/>
</Transition.Child>
</TransitionChild>
{/* This is the modal */}
<div className="fixed inset-0 w-full overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4">
<Transition.Child
<TransitionChild
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
@ -86,8 +93,8 @@ function FeedbackDialog({
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className="relative w-full max-w-2xl transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all dark:bg-slate-900">
<Dialog.Title
<DialogPanel className="relative w-full max-w-2xl transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all dark:bg-slate-900">
<DialogTitle
as="h3"
className="bg-white p-4 text-center text-lg font-medium leading-6 text-slate-700 dark:bg-slate-900 dark:text-slate-400"
>
@ -95,7 +102,7 @@ function FeedbackDialog({
<button className={styles.closebutton} onClick={closeDialog}>
&times;
</button>
</Dialog.Title>
</DialogTitle>
{/* The anatomy here should be
@ -217,11 +224,11 @@ function FeedbackDialog({
</ul>
{isIdea && (
<div className={styles.fadeinout}>
<Dialog.Description>
<Description>
We are always looking to improve our documentation. If you
have any suggestions, please let us know.
</Dialog.Description>
<Dialog.Description className="pt-4">
</Description>
<Description className="pt-4">
<textarea
rows={5}
className="box-border w-full rounded dark:bg-gray-800"
@ -229,8 +236,8 @@ function FeedbackDialog({
value={feedback}
onChange={updateFeedback}
></textarea>
</Dialog.Description>
<Dialog.Description className="relative mt-4 flex justify-end rounded-l-md">
</Description>
<Description className="relative mt-4 flex justify-end rounded-l-md">
<button
onClick={submitFeedback}
disabled={formDisabled}
@ -245,11 +252,11 @@ function FeedbackDialog({
>
Done
</button>
</Dialog.Description>
</Description>
</div>
)}
</Dialog.Panel>
</Transition.Child>
</DialogPanel>
</TransitionChild>
</div>
</div>
</Dialog>

View File

@ -4,7 +4,13 @@ import { FC, Fragment, SVGProps, useEffect, useState } from 'react';
import { usePathname, useSearchParams } from 'next/navigation';
import { ChevronDownIcon } from '@heroicons/react/24/outline';
import { Menu, Transition } from '@headlessui/react';
import {
Menu,
MenuButton,
MenuItem,
MenuItems,
Transition,
} from '@headlessui/react';
import { cx } from '@nx/nx-dev/ui-primitives';
import { BlogPostDataEntry } from '@nx/nx-dev/data-access-documents/node-only';
@ -102,7 +108,7 @@ export function Filters({
{/* MOBILE */}
<div className="relative lg:hidden">
<Menu as="div" className="inline-block text-left">
<Menu.Button
<MenuButton
className="inline-flex w-full justify-center rounded-md border border-slate-400 bg-white px-4 py-2 text-sm font-medium text-slate-700 shadow-sm transition hover:bg-slate-50 hover:text-slate-600 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-200 dark:hover:bg-slate-700"
aria-label="Select filter topic"
>
@ -111,7 +117,7 @@ export function Filters({
className="-mr-1 ml-2 h-5 w-5 text-violet-200 hover:text-violet-100"
aria-hidden="true"
/>
</Menu.Button>
</MenuButton>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
@ -121,13 +127,13 @@ export function Filters({
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items
<MenuItems
as="ul"
className="absolute right-0 z-[31] mt-2 flex w-56 origin-top-right flex-col gap-4 rounded-md bg-white p-4 shadow-lg ring-1 ring-black/5 focus:outline-none dark:bg-slate-800 dark:text-white"
aria-label="Filter topics"
>
{filters.map((filter) => (
<Menu.Item as="li" className="text-lg" key={filter.value}>
<MenuItem as="li" className="text-lg" key={filter.value}>
<Link
className={cx('flex items-center gap-2')}
href={updateFilter(filter.value)}
@ -141,9 +147,9 @@ export function Filters({
)}
{filter.label}
</Link>
</Menu.Item>
</MenuItem>
))}
</Menu.Items>
</MenuItems>
</Transition>
</Menu>
</div>

View File

@ -1,5 +1,10 @@
'use client';
import { Dialog, Transition } from '@headlessui/react';
import {
Dialog,
DialogPanel,
Transition,
TransitionChild,
} from '@headlessui/react';
import { cx } from '@nx/nx-dev/ui-primitives';
import { PlayIcon } from '@heroicons/react/24/outline';
import { motion } from 'framer-motion';
@ -92,7 +97,7 @@ export function Hero(): JSX.Element {
onClose={() => setIsOpen(false)}
className="relative z-10"
>
<Transition.Child
<TransitionChild
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
@ -102,10 +107,10 @@ export function Hero(): JSX.Element {
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-black/25 backdrop-blur-sm" />
</Transition.Child>
</TransitionChild>
<div className="fixed inset-0 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4 text-center">
<Transition.Child
<TransitionChild
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
@ -114,7 +119,7 @@ export function Hero(): JSX.Element {
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className="relative w-auto transform overflow-hidden rounded-2xl border border-slate-600 text-left align-middle shadow-xl transition-all focus:outline-none dark:border-slate-800">
<DialogPanel className="relative w-auto transform overflow-hidden rounded-2xl border border-slate-600 text-left align-middle shadow-xl transition-all focus:outline-none dark:border-slate-800">
<iframe
width="812"
height="468"
@ -125,8 +130,8 @@ export function Hero(): JSX.Element {
allowFullScreen
className="max-w-full"
/>
</Dialog.Panel>
</Transition.Child>
</DialogPanel>
</TransitionChild>
</div>
</div>
</Dialog>

View File

@ -11,7 +11,12 @@ import cx from 'classnames';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { ButtonLink } from '../button';
import { Popover, Transition } from '@headlessui/react';
import {
Popover,
PopoverButton,
PopoverPanel,
Transition,
} from '@headlessui/react';
import { resourceMenuItems } from './menu-items';
import { SectionsMenu } from './sections-menu';
import { DiscordIcon } from '../discord-icon';
@ -248,7 +253,7 @@ export function DocumentationHeader({
<Popover className="relative">
{({ open }) => (
<>
<Popover.Button
<PopoverButton
className={cx(
open ? 'text-blue-500 dark:text-sky-500' : '',
'group inline-flex items-center px-3 py-2 font-medium leading-tight outline-0 dark:text-slate-200'
@ -266,7 +271,7 @@ export function DocumentationHeader({
)}
aria-hidden="true"
/>
</Popover.Button>
</PopoverButton>
<Transition
as={Fragment}
@ -277,9 +282,9 @@ export function DocumentationHeader({
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1"
>
<Popover.Panel className="absolute left-60 z-30 mt-3 w-max max-w-2xl -translate-x-1/2 transform lg:left-20">
<PopoverPanel className="absolute left-60 z-30 mt-3 w-max max-w-2xl -translate-x-1/2 transform lg:left-20">
<SectionsMenu sections={resourceMenuItems} />
</Popover.Panel>
</PopoverPanel>
</Transition>
</>
)}

View File

@ -1,5 +1,15 @@
'use client';
import { Dialog, Disclosure, Popover, Transition } from '@headlessui/react';
import {
Dialog,
DialogPanel,
DialogTitle,
Disclosure,
DisclosureButton,
Popover,
PopoverButton,
Transition,
TransitionChild,
} from '@headlessui/react';
import {
Bars4Icon,
ChevronDownIcon,
@ -97,7 +107,7 @@ export function Header({ ctaButtons }: HeaderProps): ReactElement {
<Popover className="relative">
{({ open }) => (
<>
<Popover.Button
<PopoverButton
className={cx(
open ? 'text-blue-500 dark:text-sky-500' : '',
'group inline-flex items-center px-3 py-2 font-medium leading-tight outline-0 dark:text-slate-200'
@ -115,7 +125,7 @@ export function Header({ ctaButtons }: HeaderProps): ReactElement {
)}
aria-hidden="true"
/>
</Popover.Button>
</PopoverButton>
<Transition
as={Fragment}
@ -228,7 +238,7 @@ export function Header({ ctaButtons }: HeaderProps): ReactElement {
</div>
</div>
</div>
<Transition.Root show={isOpen} as={Fragment}>
<Transition show={isOpen} as={Fragment}>
<Dialog
as="div"
className="relative z-10"
@ -238,7 +248,7 @@ export function Header({ ctaButtons }: HeaderProps): ReactElement {
<div className="fixed inset-0 overflow-hidden">
<div className="absolute inset-0 overflow-hidden">
<div className="pointer-events-none fixed inset-y-0 right-0 flex max-w-full">
<Transition.Child
<TransitionChild
as={Fragment}
enter="transform transition ease-in-out duration-250 sm:duration-500"
enterFrom="translate-x-full"
@ -247,11 +257,11 @@ export function Header({ ctaButtons }: HeaderProps): ReactElement {
leaveFrom="translate-x-0"
leaveTo="translate-x-full"
>
<Dialog.Panel className="pointer-events-auto w-screen">
<DialogPanel className="pointer-events-auto w-screen">
<div className="flex h-full flex-col overflow-y-scroll bg-white py-6 shadow-xl dark:bg-slate-900">
<div className="px-4 sm:px-6">
<div className="flex items-start justify-between">
<Dialog.Title>
<DialogTitle>
<Link
href="/"
className="flex items-center text-slate-900 dark:text-white"
@ -269,7 +279,7 @@ export function Header({ ctaButtons }: HeaderProps): ReactElement {
</svg>
<span className="sr-only">Nx</span>
</Link>
</Dialog.Title>
</DialogTitle>
<div className="ml-3 flex h-7 items-center">
<button
type="button"
@ -321,7 +331,7 @@ export function Header({ ctaButtons }: HeaderProps): ReactElement {
<Disclosure as="div">
{({ open }) => (
<>
<Disclosure.Button
<DisclosureButton
className={cx(
open
? 'text-blue-500 dark:text-sky-500'
@ -339,7 +349,7 @@ export function Header({ ctaButtons }: HeaderProps): ReactElement {
'h-3 w-3 transition duration-150 ease-in-out group-hover:text-blue-500 dark:group-hover:text-sky-500'
)}
/>
</Disclosure.Button>
</DisclosureButton>
<Disclosure.Panel
as="ul"
className="space-y-1 pb-2"
@ -399,13 +409,13 @@ export function Header({ ctaButtons }: HeaderProps): ReactElement {
</div>
</div>
</div>
</Dialog.Panel>
</Transition.Child>
</DialogPanel>
</TransitionChild>
</div>
</div>
</div>
</Dialog>
</Transition.Root>
</Transition>
</div>
);
}

View File

@ -1,5 +1,10 @@
'use client';
import { Dialog, Transition } from '@headlessui/react';
import {
Dialog,
DialogPanel,
Transition,
TransitionChild,
} from '@headlessui/react';
import { XMarkIcon } from '@heroicons/react/24/outline';
import { AlgoliaSearch } from '@nx/nx-dev/feature-search';
import { Menu, MenuItem, MenuSection } from '@nx/nx-dev/models-menu';
@ -257,10 +262,10 @@ export function SidebarMobile({
};
return (
<Transition.Root show={navIsOpen} as={Fragment}>
<Transition show={navIsOpen} as={Fragment}>
<Dialog as="div" className="relative z-40" onClose={() => void 0}>
<div className="fixed inset-0 z-40 flex">
<Transition.Child
<TransitionChild
as={Fragment}
enter="transition ease-in-out duration-300 transform"
enterFrom="-translate-x-full"
@ -269,7 +274,7 @@ export function SidebarMobile({
leaveFrom="translate-x-0"
leaveTo="-translate-x-full"
>
<Dialog.Panel className="relative flex w-full flex-col overflow-y-auto bg-white dark:bg-slate-900">
<DialogPanel className="relative flex w-full flex-col overflow-y-auto bg-white dark:bg-slate-900">
{/*HEADER*/}
<div className="flex w-full items-center border-b border-slate-200 bg-slate-50 p-4 lg:hidden dark:border-slate-700 dark:bg-slate-800/60">
{/*CLOSE BUTTON*/}
@ -354,10 +359,10 @@ export function SidebarMobile({
</nav>
</div>
</div>
</Dialog.Panel>
</Transition.Child>
</DialogPanel>
</TransitionChild>
</div>
</Dialog>
</Transition.Root>
</Transition>
);
}

View File

@ -1,5 +1,11 @@
'use client';
import { Listbox, Transition } from '@headlessui/react';
import {
Listbox,
ListboxButton,
ListboxOption,
ListboxOptions,
Transition,
} from '@headlessui/react';
import { ChevronUpDownIcon } from '@heroicons/react/24/solid';
import Link from 'next/link';
import { Fragment, JSX, useState } from 'react';
@ -33,7 +39,7 @@ export function VersionPicker(): JSX.Element {
<Listbox value={selected}>
{({ open }) => (
<div className="relative">
<Listbox.Button
<ListboxButton
className={
'relative w-full cursor-pointer rounded-lg border border-slate-200 py-2 pl-3 pr-10 text-left font-medium focus:outline-none focus-visible:border-blue-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-blue-300 sm:text-sm dark:border-slate-700'
}
@ -45,7 +51,7 @@ export function VersionPicker(): JSX.Element {
aria-hidden="true"
/>
</span>
</Listbox.Button>
</ListboxButton>
<Transition
show={open}
as={Fragment}
@ -56,14 +62,14 @@ export function VersionPicker(): JSX.Element {
leaveFrom="transform scale-100 opacity-100"
leaveTo="transform scale-95 opacity-0"
>
<Listbox.Options
<ListboxOptions
static
className="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-sm bg-white py-1 pl-0 text-base shadow-md focus:outline-none sm:text-sm dark:bg-slate-800/90 dark:focus-within:ring-sky-500"
>
{versionOptions.map((item, idx) => (
<Listbox.Option
<ListboxOption
key={idx}
className={({ active }) =>
className={() =>
`relative cursor-pointer select-none list-none hover:bg-slate-50 dark:hover:bg-slate-800`
}
value={item}
@ -80,9 +86,9 @@ export function VersionPicker(): JSX.Element {
{item.label}
</Link>
)}
</Listbox.Option>
</ListboxOption>
))}
</Listbox.Options>
</ListboxOptions>
</Transition>
</div>
)}

View File

@ -7,7 +7,12 @@ import {
SVGProps,
type ReactElement,
} from 'react';
import { Dialog, Transition } from '@headlessui/react';
import {
Dialog,
DialogPanel,
Transition,
TransitionChild,
} from '@headlessui/react';
import {
ChevronLeftIcon,
ChevronRightIcon,
@ -377,7 +382,7 @@ export function CustomerTestimonialCarousel(): ReactElement {
onClose={() => setIsOpen(false)}
className="relative z-50"
>
<Transition.Child
<TransitionChild
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
@ -387,11 +392,11 @@ export function CustomerTestimonialCarousel(): ReactElement {
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-black/70 backdrop-blur-sm" />
</Transition.Child>
</TransitionChild>
<div className="fixed inset-0 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4">
<Transition.Child
<TransitionChild
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
@ -400,7 +405,7 @@ export function CustomerTestimonialCarousel(): ReactElement {
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className="w-full max-w-4xl overflow-hidden rounded-2xl bg-black shadow-2xl">
<DialogPanel className="w-full max-w-4xl overflow-hidden rounded-2xl bg-black shadow-2xl">
<div className="aspect-video">
<iframe
width="100%"
@ -412,8 +417,8 @@ export function CustomerTestimonialCarousel(): ReactElement {
className="h-full w-full"
/>
</div>
</Dialog.Panel>
</Transition.Child>
</DialogPanel>
</TransitionChild>
</div>
</div>
</Dialog>

View File

@ -1,4 +1,9 @@
import { Dialog, Transition } from '@headlessui/react';
import {
Dialog,
DialogPanel,
Transition,
TransitionChild,
} from '@headlessui/react';
import { Fragment, ReactElement } from 'react';
export interface VideoModalProps {
@ -22,7 +27,7 @@ export function VideoModal({
onClose={onClose}
className="relative z-50"
>
<Transition.Child
<TransitionChild
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
@ -32,10 +37,10 @@ export function VideoModal({
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-black/70 backdrop-blur-sm" />
</Transition.Child>
</TransitionChild>
<div className="fixed inset-0 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4 text-center">
<Transition.Child
<TransitionChild
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
@ -44,7 +49,7 @@ export function VideoModal({
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className="relative w-auto transform overflow-hidden rounded-2xl border border-white/10 bg-black text-left align-middle shadow-xl transition-all focus:outline-none">
<DialogPanel className="relative w-auto transform overflow-hidden rounded-2xl border border-white/10 bg-black text-left align-middle shadow-xl transition-all focus:outline-none">
<iframe
width="808"
height="454"
@ -55,8 +60,8 @@ export function VideoModal({
allowFullScreen
className="max-w-full"
/>
</Dialog.Panel>
</Transition.Child>
</DialogPanel>
</TransitionChild>
</div>
</div>
</Dialog>

View File

@ -1,4 +1,10 @@
import { Listbox, Transition } from '@headlessui/react';
import {
Listbox,
ListboxButton,
ListboxOption,
ListboxOptions,
Transition,
} from '@headlessui/react';
import { ChevronUpDownIcon } from '@heroicons/react/24/solid';
import { Fragment, JSX } from 'react';
@ -20,7 +26,7 @@ export function Selector<T = {}>(props: SelectorProps<T>): JSX.Element {
{({ open }) => (
<>
<div className="relative">
<Listbox.Button
<ListboxButton
className={
'relative w-full cursor-pointer border border-slate-200 py-2 pl-3 pr-10 text-left font-medium focus:outline-none focus-visible:border-blue-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-blue-300 sm:text-sm dark:border-slate-700' +
(props.className ? ` ${props.className}` : '')
@ -38,7 +44,7 @@ export function Selector<T = {}>(props: SelectorProps<T>): JSX.Element {
aria-hidden="true"
/>
</span>
</Listbox.Button>
</ListboxButton>
<Transition
show={open}
as={Fragment}
@ -49,28 +55,26 @@ export function Selector<T = {}>(props: SelectorProps<T>): JSX.Element {
leaveFrom="transform scale-100 opacity-100"
leaveTo="transform scale-95 opacity-0"
>
<Listbox.Options
<ListboxOptions
static
className="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-sm bg-white py-1 pl-0 text-base shadow-md focus:outline-none sm:text-sm dark:bg-slate-800/60 dark:focus-within:ring-sky-500"
>
{props.items.map((item, personIdx) => (
<Listbox.Option
<ListboxOption
key={personIdx}
className={({ active }) =>
className={() =>
`relative cursor-pointer select-none list-none px-3 py-2 hover:bg-slate-50 dark:hover:bg-slate-800`
}
value={item}
>
{({ selected, active }) => (
<>
{() => (
<span className={'block truncate font-medium'}>
{item.label}
</span>
</>
)}
</Listbox.Option>
</ListboxOption>
))}
</Listbox.Options>
</ListboxOptions>
</Transition>
</div>
</>

View File

@ -1,4 +1,9 @@
import { Dialog, Transition } from '@headlessui/react';
import {
Dialog,
DialogPanel,
Transition,
TransitionChild,
} from '@headlessui/react';
import { PlayIcon } from '@heroicons/react/24/outline';
import { AnimateValue, Marquee } from '@nx/nx-dev/ui-animations';
import {
@ -197,7 +202,7 @@ export function ApplicationCard(): JSX.Element {
onClose={() => setIsOpen(false)}
className="relative z-10"
>
<Transition.Child
<TransitionChild
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
@ -207,10 +212,10 @@ export function ApplicationCard(): JSX.Element {
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-black/25 backdrop-blur-sm" />
</Transition.Child>
</TransitionChild>
<div className="fixed inset-0 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4 text-center">
<Transition.Child
<TransitionChild
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
@ -219,7 +224,7 @@ export function ApplicationCard(): JSX.Element {
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className="relative w-auto transform overflow-hidden rounded-2xl border border-slate-600 text-left align-middle shadow-xl transition-all focus:outline-none dark:border-slate-800">
<DialogPanel className="relative w-auto transform overflow-hidden rounded-2xl border border-slate-600 text-left align-middle shadow-xl transition-all focus:outline-none dark:border-slate-800">
<iframe
width="812"
height="468"
@ -230,8 +235,8 @@ export function ApplicationCard(): JSX.Element {
allowFullScreen
className="max-w-full"
/>
</Dialog.Panel>
</Transition.Child>
</DialogPanel>
</TransitionChild>
</div>
</div>
</Dialog>

View File

@ -1,7 +1,7 @@
'use client';
import { ButtonLink, SectionHeading, Strong } from '@nx/nx-dev/ui-common';
import { ReactElement, useState, useEffect } from 'react';
import { Dialog, Transition } from '@headlessui/react';
import { Dialog, DialogPanel, Transition } from '@headlessui/react';
import Link from 'next/link';
const MOBILE_BREAKPOINT = 768;
@ -85,7 +85,7 @@ export function Hero(): ReactElement {
<div className="fixed inset-0 bg-black/25 backdrop-blur-sm" />
<div className="fixed inset-0 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4 text-center">
<Dialog.Panel className="relative w-auto transform overflow-hidden rounded-2xl border border-slate-600 text-left align-middle shadow-xl transition-all focus:outline-none dark:border-slate-800">
<DialogPanel className="relative w-auto transform overflow-hidden rounded-2xl border border-slate-600 text-left align-middle shadow-xl transition-all focus:outline-none dark:border-slate-800">
<iframe
width="812"
height="456"
@ -95,7 +95,7 @@ export function Hero(): ReactElement {
allowFullScreen
className="max-w-full"
/>
</Dialog.Panel>
</DialogPanel>
</div>
</div>
</Dialog>

View File

@ -1,5 +1,10 @@
'use client';
import { Disclosure, Transition } from '@headlessui/react';
import {
Disclosure,
DisclosureButton,
DisclosurePanel,
Transition,
} from '@headlessui/react';
import { ChevronDownIcon } from '@heroicons/react/24/outline';
import { SectionHeading } from '@nx/nx-dev/ui-common';
import { cx } from '@nx/nx-dev/ui-primitives';
@ -145,7 +150,7 @@ export function Faq(): ReactElement {
{({ open }) => (
<>
<dt className="text-lg">
<Disclosure.Button className="flex w-full items-start justify-between text-left text-slate-400">
<DisclosureButton className="flex w-full items-start justify-between text-left text-slate-400">
<span className="font-medium text-slate-800 dark:text-slate-300">
{faq.question}
</span>
@ -158,7 +163,7 @@ export function Faq(): ReactElement {
aria-hidden="true"
/>
</span>
</Disclosure.Button>
</DisclosureButton>
</dt>
<Transition
enter="transition duration-100 ease-out"
@ -168,11 +173,11 @@ export function Faq(): ReactElement {
leaveFrom="transform translate-y-0 opacity-100"
leaveTo="transform -translate-y-6 opacity-0"
>
<Disclosure.Panel as="dd" className="mt-2 pr-12">
<DisclosurePanel as="dd" className="mt-2 pr-12">
<p className="text-base text-slate-500 dark:text-slate-400">
{faq.answer}
</p>
</Disclosure.Panel>
</DisclosurePanel>
</Transition>
</>
)}

View File

@ -1,5 +1,12 @@
'use client';
import { Listbox, Transition } from '@headlessui/react';
import {
Label,
Listbox,
ListboxButton,
ListboxOption,
ListboxOptions,
Transition,
} from '@headlessui/react';
import {
ComputerDesktopIcon,
MoonIcon,
@ -48,8 +55,8 @@ export function ThemeSwitcher(): JSX.Element {
<div className="inline-block">
<div className="group relative flex h-full w-full items-center px-1">
<Listbox value={theme} onChange={setTheme}>
<Listbox.Label className="sr-only">Theme</Listbox.Label>
<Listbox.Button
<Label className="sr-only">Theme</Label>
<ListboxButton
type="button"
className={cx(
'inline-flex p-2 text-sm font-medium opacity-60 transition-opacity group-hover:opacity-100',
@ -57,7 +64,7 @@ export function ThemeSwitcher(): JSX.Element {
)}
>
{themeMap[theme].icon}
</Listbox.Button>
</ListboxButton>
<Transition
as={Fragment}
@ -68,17 +75,17 @@ export function ThemeSwitcher(): JSX.Element {
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Listbox.Options className="absolute -right-10 top-full z-50 mt-2 w-36 origin-top-right divide-y divide-slate-100 rounded-md bg-white shadow-lg ring-1 ring-black/5 focus:outline-none dark:divide-slate-800 dark:bg-slate-900 dark:ring-white/5">
<ListboxOptions className="absolute -right-10 top-full z-50 mt-2 w-36 origin-top-right divide-y divide-slate-100 rounded-md bg-white shadow-lg ring-1 ring-black/5 focus:outline-none dark:divide-slate-800 dark:bg-slate-900 dark:ring-white/5">
{availableThemes.map((t) => (
<Listbox.Option key={t.value} value={t.value} as={Fragment}>
{({ active, selected }) => (
<ListboxOption key={t.value} value={t.value} as={Fragment}>
{({ focus, selected }) => (
<li
className={cx(
'flex cursor-pointer items-center gap-2 px-4 py-2 text-sm',
{
'bg-slate-100 dark:bg-slate-800/60': active,
'text-blue-500 dark:text-sky-500': active || selected,
'text-slate-700 dark:text-slate-400': !active,
'bg-slate-100 dark:bg-slate-800/60': focus,
'text-blue-500 dark:text-sky-500': focus || selected,
'text-slate-700 dark:text-slate-400': !focus,
}
)}
>
@ -86,9 +93,9 @@ export function ThemeSwitcher(): JSX.Element {
{t.label}
</li>
)}
</Listbox.Option>
</ListboxOption>
))}
</Listbox.Options>
</ListboxOptions>
</Transition>
</Listbox>
</div>

View File

@ -326,7 +326,7 @@
},
"dependencies": {
"@docsearch/react": "^3.3.0",
"@headlessui/react": "^1.7.19",
"@headlessui/react": "^2.2.0",
"@heroicons/react": "^2.1.4",
"@markdoc/markdoc": "0.2.2",
"@monaco-editor/react": "^4.4.6",
@ -359,7 +359,7 @@
"next-seo": "^5.13.0",
"node-machine-id": "1.1.12",
"npm-run-path": "^4.0.1",
"preact": "10.6.4",
"preact": "10.25.4",
"react": "18.3.1",
"react-copy-to-clipboard": "^5.1.0",
"react-dom": "18.3.1",

121
pnpm-lock.yaml generated
View File

@ -16,8 +16,8 @@ importers:
specifier: ^3.3.0
version: 3.6.1(@algolia/client-search@5.5.2)(@types/react@18.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.2)
'@headlessui/react':
specifier: ^1.7.19
version: 1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
specifier: ^2.2.0
version: 2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@heroicons/react':
specifier: ^2.1.4
version: 2.1.5(react@18.3.1)
@ -115,8 +115,8 @@ importers:
specifier: ^4.0.1
version: 4.0.1
preact:
specifier: 10.6.4
version: 10.6.4
specifier: 10.25.4
version: 10.25.4
react:
specifier: 18.3.1
version: 18.3.1
@ -3698,6 +3698,12 @@ packages:
react: '>=16.8.0'
react-dom: '>=16.8.0'
'@floating-ui/react@0.26.28':
resolution: {integrity: sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==}
peerDependencies:
react: '>=16.8.0'
react-dom: '>=16.8.0'
'@floating-ui/react@0.26.6':
resolution: {integrity: sha512-FFDAuSlRwb8CY4/VvYio/wwk/0339B257yRpKwNOjcHWNYL/fgjl1KUvT3K6ZZ4WDbBWYc7Km4ITMuPZrS8omg==}
peerDependencies:
@ -3714,6 +3720,13 @@ packages:
react: ^16 || ^17 || ^18
react-dom: ^16 || ^17 || ^18
'@headlessui/react@2.2.0':
resolution: {integrity: sha512-RzCEg+LXsuI7mHiSomsu/gBJSjpupm6A1qIZ5sWjd7JhARNlMiSA4kKfJpCKwU9tE+zMRterhhrP74PvfJrpXQ==}
engines: {node: '>=10'}
peerDependencies:
react: ^18 || ^19 || ^19.0.0-rc
react-dom: ^18 || ^19 || ^19.0.0-rc
'@heroicons/react@2.1.5':
resolution: {integrity: sha512-FuzFN+BsHa+7OxbvAERtgBTNeZpUjgM/MIizfVkSCL2/edriN0Hx/DWRCR//aPYwO5QX/YlgLGXk+E3PcfZwjA==}
peerDependencies:
@ -5631,6 +5644,27 @@ packages:
'@popperjs/core@2.11.8':
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
'@react-aria/focus@3.19.0':
resolution: {integrity: sha512-hPF9EXoUQeQl1Y21/rbV2H4FdUR2v+4/I0/vB+8U3bT1CJ+1AFj1hc/rqx2DqEwDlEwOHN+E4+mRahQmlybq0A==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
'@react-aria/interactions@3.22.5':
resolution: {integrity: sha512-kMwiAD9E0TQp+XNnOs13yVJghiy8ET8L0cbkeuTgNI96sOAp/63EJ1FSrDf17iD8sdjt41LafwX/dKXW9nCcLQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
'@react-aria/ssr@3.9.7':
resolution: {integrity: sha512-GQygZaGlmYjmYM+tiNBA5C6acmiDWF52Nqd40bBp0Znk4M4hP+LTmI0lpI1BuKMw45T8RIhrAsICIfKwZvi2Gg==}
engines: {node: '>= 12'}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
'@react-aria/utils@3.26.0':
resolution: {integrity: sha512-LkZouGSjjQ0rEqo4XJosS4L3YC/zzQkfRM3KoqK6fUOmUJ9t0jQ09WjiF+uOoG9u+p30AVg3TrZRUWmoTS+koQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
'@react-spring/animated@9.6.1':
resolution: {integrity: sha512-ls/rJBrAqiAYozjLo5EPPLLOb1LM0lNVQcXODTC1SMtS6DbuBCPaKco5svFUQFMP2dso3O+qcC4k9FsKc0KxMQ==}
peerDependencies:
@ -5687,6 +5721,11 @@ packages:
'@react-spring/types@9.7.4':
resolution: {integrity: sha512-iQVztO09ZVfsletMiY+DpT/JRiBntdsdJ4uqk3UJFhrhS8mIC9ZOZbmfGSRs/kdbNPQkVyzucceDicQ/3Mlj9g==}
'@react-stately/utils@3.10.5':
resolution: {integrity: sha512-iMQSGcpaecghDIh3mZEpZfoFH3ExBwTtuBEcvZ2XnGzCgQjeYXcMdIUwAfVQLXFTdHUHGF6Gu6/dFrYsCzySBQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
'@react-three/drei@9.112.0':
resolution: {integrity: sha512-te+4tcNiRv3QizD04cg25oX51uUMVG5Y3iUaIX8tKi8aW3j7UM6XCFSKVYNOiT6P+d5h/ruSd5naX7oFvp3QOQ==}
peerDependencies:
@ -5723,6 +5762,11 @@ packages:
react-native:
optional: true
'@react-types/shared@3.26.0':
resolution: {integrity: sha512-6FuPqvhmjjlpEDLTiYx29IJCbCNWPlsyO+ZUmCUXzhUv2ttShOXfw8CmeHWHftT/b2KweAWuzqSlfeXPR76jpw==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
'@reduxjs/toolkit@1.9.0':
resolution: {integrity: sha512-ak11IrjYcUXRqlhNPwnz6AcvA2ynJTu8PzDbbqQw4a3xR4KZtgiqbNblQD+10CRbfK4+5C79SOyxnT9dhBqFnA==}
peerDependencies:
@ -8675,6 +8719,10 @@ packages:
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
engines: {node: '>=0.8'}
clsx@2.1.1:
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
engines: {node: '>=6'}
cluster-key-slot@1.1.2:
resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==}
engines: {node: '>=0.10.0'}
@ -14503,8 +14551,8 @@ packages:
potpack@1.0.2:
resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==}
preact@10.6.4:
resolution: {integrity: sha512-WyosM7pxGcndU8hY0OQlLd54tOU+qmG45QXj2dAYrL11HoyU/EzOSTlpJsirbBr1QW7lICxSsVJJmcmUglovHQ==}
preact@10.25.4:
resolution: {integrity: sha512-jLdZDb+Q+odkHJ+MpW/9U5cODzqnB+fy2EiHSZES7ldV5LK7yjlVzTp7R8Xy6W6y75kfK8iWYtFVH7lvjwrCMA==}
prelude-ls@1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
@ -20539,6 +20587,14 @@ snapshots:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
'@floating-ui/react@0.26.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@floating-ui/utils': 0.2.8
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
tabbable: 6.2.0
'@floating-ui/react@0.26.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@ -20556,6 +20612,15 @@ snapshots:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
'@headlessui/react@2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@floating-ui/react': 0.26.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@react-aria/focus': 3.19.0(react@18.3.1)
'@react-aria/interactions': 3.22.5(react@18.3.1)
'@tanstack/react-virtual': 3.10.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
'@heroicons/react@2.1.5(react@18.3.1)':
dependencies:
react: 18.3.1
@ -23358,6 +23423,37 @@ snapshots:
'@popperjs/core@2.11.8': {}
'@react-aria/focus@3.19.0(react@18.3.1)':
dependencies:
'@react-aria/interactions': 3.22.5(react@18.3.1)
'@react-aria/utils': 3.26.0(react@18.3.1)
'@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
clsx: 2.1.1
react: 18.3.1
'@react-aria/interactions@3.22.5(react@18.3.1)':
dependencies:
'@react-aria/ssr': 3.9.7(react@18.3.1)
'@react-aria/utils': 3.26.0(react@18.3.1)
'@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
react: 18.3.1
'@react-aria/ssr@3.9.7(react@18.3.1)':
dependencies:
'@swc/helpers': 0.5.11
react: 18.3.1
'@react-aria/utils@3.26.0(react@18.3.1)':
dependencies:
'@react-aria/ssr': 3.9.7(react@18.3.1)
'@react-stately/utils': 3.10.5(react@18.3.1)
'@react-types/shared': 3.26.0(react@18.3.1)
'@swc/helpers': 0.5.11
clsx: 2.1.1
react: 18.3.1
'@react-spring/animated@9.6.1(react@18.3.1)':
dependencies:
'@react-spring/shared': 9.6.1(react@18.3.1)
@ -23425,6 +23521,11 @@ snapshots:
'@react-spring/types@9.7.4': {}
'@react-stately/utils@3.10.5(react@18.3.1)':
dependencies:
'@swc/helpers': 0.5.11
react: 18.3.1
'@react-three/drei@9.112.0(@react-three/fiber@8.17.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(three@0.166.1))(@types/react@18.3.1)(@types/three@0.166.0)(immer@9.0.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(three@0.166.1)':
dependencies:
'@babel/runtime': 7.25.6
@ -23479,6 +23580,10 @@ snapshots:
optionalDependencies:
react-dom: 18.3.1(react@18.3.1)
'@react-types/shared@3.26.0(react@18.3.1)':
dependencies:
react: 18.3.1
'@reduxjs/toolkit@1.9.0(react-redux@8.0.5(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1))(react@18.3.1)':
dependencies:
immer: 9.0.21
@ -27174,6 +27279,8 @@ snapshots:
clone@1.0.4: {}
clsx@2.1.1: {}
cluster-key-slot@1.1.2: {}
co@4.6.0: {}
@ -34582,7 +34689,7 @@ snapshots:
potpack@1.0.2: {}
preact@10.6.4: {}
preact@10.25.4: {}
prelude-ls@1.2.1: {}