From b025629671d641cdf54476f338bb7e25ed015aba Mon Sep 17 00:00:00 2001 From: Ryo Matsukawa <76232929+ryo-manba@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:33:43 +0900 Subject: [PATCH 1/3] fix(dropdown): correct initial animation direction --- packages/components/dropdown/package.json | 1 + .../components/dropdown/src/use-dropdown.ts | 24 +++++++-- .../dropdown/stories/dropdown.stories.tsx | 35 +++++++++++- pnpm-lock.yaml | 54 ++++--------------- 4 files changed, 66 insertions(+), 48 deletions(-) diff --git a/packages/components/dropdown/package.json b/packages/components/dropdown/package.json index de9882bb41..3f26c61da3 100644 --- a/packages/components/dropdown/package.json +++ b/packages/components/dropdown/package.json @@ -48,6 +48,7 @@ "@nextui-org/shared-utils": "workspace:*", "@react-aria/focus": "3.19.0", "@react-aria/menu": "3.16.0", + "@react-aria/overlays": "3.24.0", "@react-aria/utils": "3.26.0", "@react-stately/menu": "3.9.0", "@react-types/menu": "3.9.13" diff --git a/packages/components/dropdown/src/use-dropdown.ts b/packages/components/dropdown/src/use-dropdown.ts index 4deb06b42b..df74fed07b 100644 --- a/packages/components/dropdown/src/use-dropdown.ts +++ b/packages/components/dropdown/src/use-dropdown.ts @@ -9,11 +9,12 @@ import {useMenuTrigger} from "@react-aria/menu"; import {dropdown} from "@nextui-org/theme"; import {clsx} from "@nextui-org/shared-utils"; import {ReactRef, mergeRefs} from "@nextui-org/react-utils"; -import {ariaShouldCloseOnInteractOutside} from "@nextui-org/aria-utils"; +import {ariaShouldCloseOnInteractOutside, toReactAriaPlacement} from "@nextui-org/aria-utils"; import {useMemo, useRef} from "react"; import {mergeProps} from "@react-aria/utils"; import {MenuProps} from "@nextui-org/menu"; import {CollectionElement} from "@react-types/shared"; +import {useOverlayPosition} from "@react-aria/overlays"; interface Props extends HTMLNextUIProps<"div"> { /** @@ -77,6 +78,8 @@ const getCloseOnSelect = ( return props?.closeOnSelect; }; +const DEFAULT_PLACEMENT = "bottom"; + export function useDropdown(props: UseDropdownProps): UseDropdownReturn { const globalContext = useProviderContext(); @@ -89,13 +92,17 @@ export function useDropdown(props: UseDropdownProps): UseDropdownReturn { isDisabled, type = "menu", trigger = "press", - placement = "bottom", + placement: placementProp = DEFAULT_PLACEMENT, closeOnSelect = true, shouldBlockScroll = true, classNames: classNamesProp, disableAnimation = globalContext?.disableAnimation ?? false, onClose, className, + containerPadding = 12, + offset = 7, + crossOffset = 0, + shouldFlip = true, ...otherProps } = props; @@ -132,6 +139,17 @@ export function useDropdown(props: UseDropdownProps): UseDropdownReturn { [className], ); + const {placement} = useOverlayPosition({ + isOpen: state.isOpen, + targetRef: triggerRef, + overlayRef: popoverRef, + placement: toReactAriaPlacement(placementProp), + offset, + crossOffset, + shouldFlip, + containerPadding, + }); + const onMenuAction = (menuCloseOnSelect?: boolean) => { if (menuCloseOnSelect !== undefined && !menuCloseOnSelect) { return; @@ -146,7 +164,7 @@ export function useDropdown(props: UseDropdownProps): UseDropdownReturn { return { state, - placement, + placement: placement || DEFAULT_PLACEMENT, ref: popoverRef, disableAnimation, shouldBlockScroll, diff --git a/packages/components/dropdown/stories/dropdown.stories.tsx b/packages/components/dropdown/stories/dropdown.stories.tsx index 0c26be0ad1..b5b45ead99 100644 --- a/packages/components/dropdown/stories/dropdown.stories.tsx +++ b/packages/components/dropdown/stories/dropdown.stories.tsx @@ -137,10 +137,15 @@ const items = [ }, ]; -const Template = ({color, variant, ...args}: DropdownProps & DropdownMenuProps) => ( +const Template = ({ + color, + variant, + label = "Trigger", + ...args +}: DropdownProps & DropdownMenuProps & {label: string}) => ( - + New file @@ -782,3 +787,29 @@ export const ItemCloseOnSelect = { ...defaultProps, }, }; + +export const WithFallbackPlacements = { + args: { + ...defaultProps, + }, + render: (args) => ( +
+
+