Skip to content

Commit ee76ae6

Browse files
committed
[core] Refactor data passing
1 parent 38f77b6 commit ee76ae6

25 files changed

+335
-1164
lines changed

docs/reference/generated/menu-positioner.json

+9-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"props": {
55
"align": {
66
"type": "'start' | 'center' | 'end'",
7+
"default": "'center'",
78
"description": "How to align the popup relative to the specified side."
89
},
910
"alignOffset": {
@@ -13,6 +14,7 @@
1314
},
1415
"side": {
1516
"type": "'bottom' | 'inline-end' | 'inline-start' | 'left' | 'right' | 'top'",
17+
"default": "'bottom'",
1618
"description": "Which side of the anchor element to align the popup against.\nMay automatically change to avoid collisions."
1719
},
1820
"sideOffset": {
@@ -42,21 +44,26 @@
4244
"sticky": {
4345
"type": "boolean",
4446
"default": "false",
45-
"description": "Whether to maintain the menu in the viewport after\nthe anchor element is scrolled out of view."
47+
"description": "Whether to maintain the popup in the viewport after\nthe anchor element was scrolled out of view."
4648
},
4749
"positionMethod": {
4850
"type": "'absolute' | 'fixed'",
4951
"default": "'absolute'",
5052
"description": "Determines which CSS `position` property to use."
5153
},
54+
"trackAnchor": {
55+
"type": "boolean",
56+
"default": "true",
57+
"description": "Whether the popup tracks any layout shift of its positioning anchor."
58+
},
5259
"className": {
5360
"type": "string | (state) => string",
5461
"description": "CSS class applied to the element, or a function that\nreturns a class based on the component’s state."
5562
},
5663
"keepMounted": {
5764
"type": "boolean",
5865
"default": "false",
59-
"description": "Whether to keep the HTML element in the DOM while the menu is hidden."
66+
"description": "Whether to keep the popup mounted in the DOM while it's hidden."
6067
},
6168
"render": {
6269
"type": "React.ReactElement | (props, state) => React.ReactElement",

docs/reference/generated/popover-positioner.json

+7-2
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,26 @@
4444
"sticky": {
4545
"type": "boolean",
4646
"default": "false",
47-
"description": "Whether to maintain the popup in the viewport after\nthe anchor element is scrolled out of view."
47+
"description": "Whether to maintain the popup in the viewport after\nthe anchor element was scrolled out of view."
4848
},
4949
"positionMethod": {
5050
"type": "'absolute' | 'fixed'",
5151
"default": "'absolute'",
5252
"description": "Determines which CSS `position` property to use."
5353
},
54+
"trackAnchor": {
55+
"type": "boolean",
56+
"default": "true",
57+
"description": "Whether the popup tracks any layout shift of its positioning anchor."
58+
},
5459
"className": {
5560
"type": "string | (state) => string",
5661
"description": "CSS class applied to the element, or a function that\nreturns a class based on the component’s state."
5762
},
5863
"keepMounted": {
5964
"type": "boolean",
6065
"default": "false",
61-
"description": "Whether to keep the HTML element in the DOM while the popover is hidden."
66+
"description": "Whether to keep the popup mounted in the DOM while it's hidden."
6267
},
6368
"render": {
6469
"type": "React.ReactElement | (props, state) => React.ReactElement",

docs/reference/generated/preview-card-positioner.json

+7-2
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,26 @@
4444
"sticky": {
4545
"type": "boolean",
4646
"default": "false",
47-
"description": "Whether to maintain the popup in the viewport after\nthe anchor element is scrolled out of view."
47+
"description": "Whether to maintain the popup in the viewport after\nthe anchor element was scrolled out of view."
4848
},
4949
"positionMethod": {
5050
"type": "'absolute' | 'fixed'",
5151
"default": "'absolute'",
5252
"description": "Determines which CSS `position` property to use."
5353
},
54+
"trackAnchor": {
55+
"type": "boolean",
56+
"default": "true",
57+
"description": "Whether the popup tracks any layout shift of its positioning anchor."
58+
},
5459
"className": {
5560
"type": "string | (state) => string",
5661
"description": "CSS class applied to the element, or a function that\nreturns a class based on the component’s state."
5762
},
5863
"keepMounted": {
5964
"type": "boolean",
6065
"default": "false",
61-
"description": "Whether to keep the HTML element in the DOM while the preview card is hidden."
66+
"description": "Whether to keep the popup mounted in the DOM while it's hidden."
6267
},
6368
"render": {
6469
"type": "React.ReactElement | (props, state) => React.ReactElement",

docs/reference/generated/select-positioner.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"props": {
55
"align": {
66
"type": "'start' | 'center' | 'end'",
7-
"default": "'start'",
7+
"default": "'center'",
88
"description": "How to align the popup relative to the specified side."
99
},
1010
"alignOffset": {
@@ -44,17 +44,17 @@
4444
"sticky": {
4545
"type": "boolean",
4646
"default": "false",
47-
"description": "Whether to maintain the select menu in the viewport after\nthe anchor element is scrolled out of view."
47+
"description": "Whether to maintain the popup in the viewport after\nthe anchor element was scrolled out of view."
4848
},
4949
"positionMethod": {
5050
"type": "'absolute' | 'fixed'",
5151
"default": "'absolute'",
52-
"description": "The CSS position method for positioning the Select popup element."
52+
"description": "Determines which CSS `position` property to use."
5353
},
5454
"trackAnchor": {
5555
"type": "boolean",
5656
"default": "true",
57-
"description": "Whether the select popup continuously tracks its anchor after the initial positioning upon mount."
57+
"description": "Whether the popup tracks any layout shift of its positioning anchor."
5858
},
5959
"className": {
6060
"type": "string | (state) => string",

docs/reference/generated/tooltip-positioner.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,19 @@
5151
"default": "'absolute'",
5252
"description": "Determines which CSS `position` property to use."
5353
},
54+
"trackAnchor": {
55+
"type": "boolean",
56+
"default": "true",
57+
"description": "Whether the popup tracks any layout shift of its positioning anchor."
58+
},
5459
"className": {
5560
"type": "string | (state) => string",
5661
"description": "CSS class applied to the element, or a function that\nreturns a class based on the component’s state."
5762
},
5863
"keepMounted": {
5964
"type": "boolean",
6065
"default": "false",
61-
"description": "Whether to keep the HTML element in the DOM while the tooltip is hidden."
66+
"description": "Whether to keep the popup mounted in the DOM while it's hidden."
6267
},
6368
"render": {
6469
"type": "React.ReactElement | (props, state) => React.ReactElement",

docs/src/app/(private)/experiments/anchor-positioning.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export default function AnchorPositioning() {
3737
positionerStyles,
3838
arrowStyles,
3939
arrowRef,
40-
renderedSide,
40+
side: renderedSide,
4141
arrowUncentered,
4242
} = useAnchorPositioning({
4343
side,

packages/react/src/dialog/root/DialogRoot.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as React from 'react';
33
import PropTypes from 'prop-types';
44
import { DialogRootContext, useOptionalDialogRootContext } from './DialogRootContext';
55
import { DialogContext } from '../utils/DialogContext';
6-
import { type CommonParameters, useDialogRoot } from './useDialogRoot';
6+
import { type SharedParameters, useDialogRoot } from './useDialogRoot';
77
import { PortalContext } from '../../portal/PortalContext';
88

99
/**
@@ -50,7 +50,7 @@ const DialogRoot = function DialogRoot(props: DialogRoot.Props) {
5050
};
5151

5252
namespace DialogRoot {
53-
export interface Props extends CommonParameters {
53+
export interface Props extends SharedParameters {
5454
children?: React.ReactNode;
5555
}
5656
}

packages/react/src/dialog/root/useDialogRoot.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
translateOpenChangeReason,
2222
} from '../../utils/translateOpenChangeReason';
2323

24-
export function useDialogRoot(parameters: useDialogRoot.Parameters): useDialogRoot.ReturnValue {
24+
export function useDialogRoot(params: useDialogRoot.Parameters): useDialogRoot.ReturnValue {
2525
const {
2626
defaultOpen,
2727
dismissible,
@@ -30,7 +30,7 @@ export function useDialogRoot(parameters: useDialogRoot.Parameters): useDialogRo
3030
onNestedDialogOpen,
3131
onOpenChange: onOpenChangeParameter,
3232
open: openParam,
33-
} = parameters;
33+
} = params;
3434

3535
const [open, setOpenUnwrapped] = useControlled({
3636
controlled: openParam,
@@ -167,7 +167,7 @@ export function useDialogRoot(parameters: useDialogRoot.Parameters): useDialogRo
167167
]);
168168
}
169169

170-
export interface CommonParameters {
170+
export interface SharedParameters {
171171
/**
172172
* Whether the dialog is currently open.
173173
*/
@@ -200,7 +200,7 @@ export interface CommonParameters {
200200
}
201201

202202
export namespace useDialogRoot {
203-
export interface Parameters extends RequiredExcept<CommonParameters, 'open' | 'onOpenChange'> {
203+
export interface Parameters extends RequiredExcept<SharedParameters, 'open' | 'onOpenChange'> {
204204
/**
205205
* Callback to invoke when a nested dialog is opened.
206206
*/

packages/react/src/menu/positioner/MenuPositioner.tsx

+18-17
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,18 @@
11
'use client';
22
import * as React from 'react';
33
import PropTypes from 'prop-types';
4-
import {
5-
FloatingNode,
6-
useFloatingNodeId,
7-
useFloatingParentNodeId,
8-
useFloatingTree,
9-
} from '@floating-ui/react';
4+
import { FloatingNode, useFloatingNodeId, useFloatingParentNodeId } from '@floating-ui/react';
105
import { MenuPositionerContext } from './MenuPositionerContext';
116
import { useMenuRootContext } from '../root/MenuRootContext';
127
import type { Align, Side } from '../../utils/useAnchorPositioning';
138
import { useComponentRenderer } from '../../utils/useComponentRenderer';
149
import { useForkRef } from '../../utils/useForkRef';
1510
import { useMenuPositioner } from './useMenuPositioner';
16-
import { HTMLElementType } from '../../utils/proptypes';
1711
import { BaseUIComponentProps } from '../../utils/types';
1812
import { popupStateMapping } from '../../utils/popupStateMapping';
1913
import { CompositeList } from '../../composite/list/CompositeList';
2014
import { InternalBackdrop } from '../../utils/InternalBackdrop';
15+
import { HTMLElementType, refType } from '../../utils/proptypes';
2116

2217
/**
2318
* Positions the menu popup against the trigger.
@@ -43,6 +38,7 @@ const MenuPositioner = React.forwardRef(function MenuPositioner(
4338
collisionPadding = 5,
4439
arrowPadding = 5,
4540
sticky = false,
41+
trackAnchor = true,
4642
...otherProps
4743
} = props;
4844

@@ -54,12 +50,9 @@ const MenuPositioner = React.forwardRef(function MenuPositioner(
5450
itemLabels,
5551
mounted,
5652
nested,
57-
setOpen,
5853
modal,
5954
} = useMenuRootContext();
6055

61-
const { events: menuEvents } = useFloatingTree()!;
62-
6356
const nodeId = useFloatingNodeId();
6457
const parentNodeId = useFloatingParentNodeId();
6558

@@ -88,8 +81,8 @@ const MenuPositioner = React.forwardRef(function MenuPositioner(
8881
sticky,
8982
nodeId,
9083
parentNodeId,
91-
menuEvents,
92-
setOpen,
84+
keepMounted,
85+
trackAnchor,
9386
});
9487

9588
const state: MenuPositioner.State = React.useMemo(
@@ -110,15 +103,15 @@ const MenuPositioner = React.forwardRef(function MenuPositioner(
110103
arrowRef: positioner.arrowRef,
111104
arrowUncentered: positioner.arrowUncentered,
112105
arrowStyles: positioner.arrowStyles,
113-
floatingContext: positioner.floatingContext,
106+
floatingContext: positioner.context,
114107
}),
115108
[
116109
positioner.side,
117110
positioner.align,
118111
positioner.arrowRef,
119112
positioner.arrowUncentered,
120113
positioner.arrowStyles,
121-
positioner.floatingContext,
114+
positioner.context,
122115
],
123116
);
124117

@@ -175,6 +168,7 @@ MenuPositioner.propTypes /* remove-proptypes */ = {
175168
// └─────────────────────────────────────────────────────────────────────┘
176169
/**
177170
* How to align the popup relative to the specified side.
171+
* @default 'center'
178172
*/
179173
align: PropTypes.oneOf(['center', 'end', 'start']),
180174
/**
@@ -188,6 +182,7 @@ MenuPositioner.propTypes /* remove-proptypes */ = {
188182
*/
189183
anchor: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([
190184
HTMLElementType,
185+
refType,
191186
PropTypes.object,
192187
PropTypes.func,
193188
]),
@@ -236,7 +231,7 @@ MenuPositioner.propTypes /* remove-proptypes */ = {
236231
}),
237232
]),
238233
/**
239-
* Whether to keep the HTML element in the DOM while the menu is hidden.
234+
* Whether to keep the popup mounted in the DOM while it's hidden.
240235
* @default false
241236
*/
242237
keepMounted: PropTypes.bool,
@@ -255,6 +250,7 @@ MenuPositioner.propTypes /* remove-proptypes */ = {
255250
/**
256251
* Which side of the anchor element to align the popup against.
257252
* May automatically change to avoid collisions.
253+
* @default 'bottom'
258254
*/
259255
side: PropTypes.oneOf(['bottom', 'inline-end', 'inline-start', 'left', 'right', 'top']),
260256
/**
@@ -263,11 +259,16 @@ MenuPositioner.propTypes /* remove-proptypes */ = {
263259
*/
264260
sideOffset: PropTypes.number,
265261
/**
266-
* Whether to maintain the menu in the viewport after
267-
* the anchor element is scrolled out of view.
262+
* Whether to maintain the popup in the viewport after
263+
* the anchor element was scrolled out of view.
268264
* @default false
269265
*/
270266
sticky: PropTypes.bool,
267+
/**
268+
* Whether the popup tracks any layout shift of its positioning anchor.
269+
* @default true
270+
*/
271+
trackAnchor: PropTypes.bool,
271272
} as any;
272273

273274
export { MenuPositioner };

0 commit comments

Comments
 (0)