Skip to content

Commit

Permalink
fix(dropdown): correct initial animation direction to match fallback …
Browse files Browse the repository at this point in the history
…placement (#4288)

* fix(dropdown): correct initial animation direction

* chore: add changeset

* fix: typo
  • Loading branch information
ryo-manba authored Dec 10, 2024
1 parent 1485eca commit aa5ea19
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 48 deletions.
5 changes: 5 additions & 0 deletions .changeset/cyan-dodos-glow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nextui-org/dropdown": patch
---

Fix initial animation direction to match fallback placement (#4251)
1 change: 1 addition & 0 deletions packages/components/dropdown/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
24 changes: 21 additions & 3 deletions packages/components/dropdown/src/use-dropdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"> {
/**
Expand Down Expand Up @@ -77,6 +78,8 @@ const getCloseOnSelect = <T extends object>(
return props?.closeOnSelect;
};

const DEFAULT_PLACEMENT = "bottom";

export function useDropdown(props: UseDropdownProps): UseDropdownReturn {
const globalContext = useProviderContext();

Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -146,7 +164,7 @@ export function useDropdown(props: UseDropdownProps): UseDropdownReturn {

return {
state,
placement,
placement: placement || DEFAULT_PLACEMENT,
ref: popoverRef,
disableAnimation,
shouldBlockScroll,
Expand Down
35 changes: 33 additions & 2 deletions packages/components/dropdown/stories/dropdown.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,15 @@ const items = [
},
];

const Template = ({color, variant, ...args}: DropdownProps & DropdownMenuProps) => (
const Template = ({
color,
variant,
label = "Trigger",
...args
}: DropdownProps & DropdownMenuProps & {label: string}) => (
<Dropdown {...args}>
<DropdownTrigger>
<Button>Trigger</Button>
<Button>{label}</Button>
</DropdownTrigger>
<DropdownMenu aria-label="Actions" color={color} variant={variant}>
<DropdownItem key="new">New file</DropdownItem>
Expand Down Expand Up @@ -782,3 +787,29 @@ export const ItemCloseOnSelect = {
...defaultProps,
},
};

export const WithFallbackPlacements = {
args: {
...defaultProps,
},
render: (args) => (
<div className="relative h-screen w-screen">
<div className="absolute top-0 left-0 p-8 flex gap-4">
<Template {...args} label="placement: top" placement="top" />
<Template {...args} label="placement: bottom" placement="bottom" />
</div>
<div className="absolute bottom-0 left-0 p-8 flex gap-4">
<Template {...args} label="placement: bottom" placement="bottom" />
<Template {...args} label="placement: top" placement="top" />
</div>
<div className="absolute left-0 top-1/2 -translate-y-1/2 p-8 flex flex-col gap-4">
<Template {...args} label="placement: left" placement="left" />
<Template {...args} label="placement: right" placement="right" />
</div>
<div className="absolute right-0 top-1/2 -translate-y-1/2 p-8 flex flex-col gap-4">
<Template {...args} label="placement: right" placement="right" />
<Template {...args} label="placement: left" placement="left" />
</div>
</div>
),
};
54 changes: 11 additions & 43 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit aa5ea19

Please sign in to comment.