mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
fix(popover): correct initial animation direction to match fallback placement (#4460)
* fix(popover): correct initial animation direction to match fallback placement * fix: type error * chore: add changeset
This commit is contained in:
parent
4f0ef5818b
commit
fb46df2430
5
.changeset/witty-goats-trade.md
Normal file
5
.changeset/witty-goats-trade.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@nextui-org/popover": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix initial animation direction to match fallback placement (#4290)
|
||||||
@ -14,7 +14,7 @@ import {
|
|||||||
PropGetter,
|
PropGetter,
|
||||||
useProviderContext,
|
useProviderContext,
|
||||||
} from "@nextui-org/system";
|
} from "@nextui-org/system";
|
||||||
import {getArrowPlacement, getShouldUseAxisPlacement} from "@nextui-org/aria-utils";
|
import {getArrowPlacement} from "@nextui-org/aria-utils";
|
||||||
import {popover} from "@nextui-org/theme";
|
import {popover} from "@nextui-org/theme";
|
||||||
import {mergeProps, mergeRefs} from "@react-aria/utils";
|
import {mergeProps, mergeRefs} from "@react-aria/utils";
|
||||||
import {clsx, dataAttr, objectToDeps} from "@nextui-org/shared-utils";
|
import {clsx, dataAttr, objectToDeps} from "@nextui-org/shared-utils";
|
||||||
@ -81,6 +81,8 @@ export interface Props extends HTMLNextUIProps<"div"> {
|
|||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEFAULT_PLACEMENT = "top";
|
||||||
|
|
||||||
export type UsePopoverProps = Props &
|
export type UsePopoverProps = Props &
|
||||||
Omit<ReactAriaPopoverProps, "triggerRef" | "popoverRef"> &
|
Omit<ReactAriaPopoverProps, "triggerRef" | "popoverRef"> &
|
||||||
OverlayTriggerProps &
|
OverlayTriggerProps &
|
||||||
@ -110,7 +112,7 @@ export function usePopover(originalProps: UsePopoverProps) {
|
|||||||
portalContainer,
|
portalContainer,
|
||||||
updatePositionDeps,
|
updatePositionDeps,
|
||||||
dialogProps: dialogPropsProp,
|
dialogProps: dialogPropsProp,
|
||||||
placement: placementProp = "top",
|
placement: placementProp = DEFAULT_PLACEMENT,
|
||||||
triggerType = "dialog",
|
triggerType = "dialog",
|
||||||
showArrow = false,
|
showArrow = false,
|
||||||
offset = 7,
|
offset = 7,
|
||||||
@ -150,11 +152,7 @@ export function usePopover(originalProps: UsePopoverProps) {
|
|||||||
|
|
||||||
const state = stateProp || innerState;
|
const state = stateProp || innerState;
|
||||||
|
|
||||||
const {
|
const {popoverProps, underlayProps, placement} = useReactAriaPopover(
|
||||||
popoverProps,
|
|
||||||
underlayProps,
|
|
||||||
placement: ariaPlacement,
|
|
||||||
} = useReactAriaPopover(
|
|
||||||
{
|
{
|
||||||
triggerRef,
|
triggerRef,
|
||||||
isNonModal,
|
isNonModal,
|
||||||
@ -208,7 +206,7 @@ export function usePopover(originalProps: UsePopoverProps) {
|
|||||||
"data-focus": dataAttr(isFocused),
|
"data-focus": dataAttr(isFocused),
|
||||||
"data-arrow": dataAttr(showArrow),
|
"data-arrow": dataAttr(showArrow),
|
||||||
"data-focus-visible": dataAttr(isFocusVisible),
|
"data-focus-visible": dataAttr(isFocusVisible),
|
||||||
"data-placement": getArrowPlacement(ariaPlacement || "top", placementProp),
|
"data-placement": getArrowPlacement(placement || DEFAULT_PLACEMENT, placementProp),
|
||||||
...mergeProps(focusProps, dialogPropsProp, props),
|
...mergeProps(focusProps, dialogPropsProp, props),
|
||||||
className: slots.base({class: clsx(baseStyles)}),
|
className: slots.base({class: clsx(baseStyles)}),
|
||||||
style: {
|
style: {
|
||||||
@ -222,18 +220,10 @@ export function usePopover(originalProps: UsePopoverProps) {
|
|||||||
"data-slot": "content",
|
"data-slot": "content",
|
||||||
"data-open": dataAttr(state.isOpen),
|
"data-open": dataAttr(state.isOpen),
|
||||||
"data-arrow": dataAttr(showArrow),
|
"data-arrow": dataAttr(showArrow),
|
||||||
"data-placement": getArrowPlacement(ariaPlacement || "top", placementProp),
|
"data-placement": getArrowPlacement(placement || DEFAULT_PLACEMENT, placementProp),
|
||||||
className: slots.content({class: clsx(classNames?.content, props.className)}),
|
className: slots.content({class: clsx(classNames?.content, props.className)}),
|
||||||
}),
|
}),
|
||||||
[slots, state.isOpen, showArrow, ariaPlacement, placementProp, classNames],
|
[slots, state.isOpen, showArrow, placement, placementProp, classNames],
|
||||||
);
|
|
||||||
|
|
||||||
const placement = useMemo(
|
|
||||||
() =>
|
|
||||||
getShouldUseAxisPlacement(ariaPlacement || "top", placementProp)
|
|
||||||
? ariaPlacement || placementProp
|
|
||||||
: placementProp,
|
|
||||||
[ariaPlacement, placementProp],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const onPress = useCallback(
|
const onPress = useCallback(
|
||||||
@ -317,7 +307,7 @@ export function usePopover(originalProps: UsePopoverProps) {
|
|||||||
classNames,
|
classNames,
|
||||||
showArrow,
|
showArrow,
|
||||||
triggerRef,
|
triggerRef,
|
||||||
placement,
|
placement: placement || DEFAULT_PLACEMENT,
|
||||||
isNonModal,
|
isNonModal,
|
||||||
popoverRef: domRef,
|
popoverRef: domRef,
|
||||||
portalContainer,
|
portalContainer,
|
||||||
|
|||||||
@ -127,11 +127,11 @@ const content = (
|
|||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
);
|
);
|
||||||
|
|
||||||
const Template = (args: PopoverProps) => {
|
const Template = ({label = "Open Popover", ...args}: PopoverProps & {label: string}) => {
|
||||||
return (
|
return (
|
||||||
<Popover {...args}>
|
<Popover {...args}>
|
||||||
<PopoverTrigger>
|
<PopoverTrigger>
|
||||||
<Button>Open Popover</Button>
|
<Button>{label}</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
{content}
|
{content}
|
||||||
</Popover>
|
</Popover>
|
||||||
@ -581,6 +581,32 @@ export const CustomMotion = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
export const WithShouldBlockScroll = {
|
export const WithShouldBlockScroll = {
|
||||||
render: (args) => {
|
render: (args) => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user