diff --git a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
index 4ad728b59e2b..6ce59ab366c0 100644
--- a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
+++ b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
@@ -6251,6 +6251,55 @@ Map {
"autoAlign": Object {
"type": "bool",
},
+ "autoAlignBoundary": Object {
+ "args": Array [
+ Array [
+ Object {
+ "args": Array [
+ Array [
+ "clippingAncestors",
+ ],
+ ],
+ "type": "oneOf",
+ },
+ Object {
+ "type": "elementType",
+ },
+ Object {
+ "args": Array [
+ Object {
+ "type": "elementType",
+ },
+ ],
+ "type": "arrayOf",
+ },
+ Object {
+ "args": Array [
+ Object {
+ "height": Object {
+ "isRequired": true,
+ "type": "number",
+ },
+ "width": Object {
+ "isRequired": true,
+ "type": "number",
+ },
+ "x": Object {
+ "isRequired": true,
+ "type": "number",
+ },
+ "y": Object {
+ "isRequired": true,
+ "type": "number",
+ },
+ },
+ ],
+ "type": "exact",
+ },
+ ],
+ ],
+ "type": "oneOfType",
+ },
"caret": Object {
"type": "bool",
},
diff --git a/packages/react/src/components/Popover/Popover.stories.js b/packages/react/src/components/Popover/Popover.stories.js
index 7007f18b6678..95f41d398bc6 100644
--- a/packages/react/src/components/Popover/Popover.stories.js
+++ b/packages/react/src/components/Popover/Popover.stories.js
@@ -270,6 +270,136 @@ export const ExperimentalAutoAlign = () => {
);
};
+export const ExperimentalAutoAlignBoundary = () => {
+ const [open, setOpen] = useState(true);
+ const ref = useRef();
+ const [boundary, setBoundary] = useState();
+
+ useEffect(() => {
+ ref?.current?.scrollIntoView({ block: 'center', inline: 'center' });
+ });
+
+ return (
+
+
+
+
+
+ {
+ setOpen(!open);
+ }}
+ />
+
+
+
+
This popover uses autoAlign
+
+ Scroll the container up, down, left or right to observe how the
+ popover will automatically change its position in attempt to
+ stay within the viewport. This works on initial render in
+ addition to on scroll.
+
+
+
+
+
+
+
+ );
+};
+
+export const Test = () => {
+ const [open, setOpen] = useState();
+ const align = document?.dir === 'rtl' ? 'bottom-right' : 'bottom-left';
+ const alignTwo = document?.dir === 'rtl' ? 'bottom-left' : 'bottom-right';
+ return (
+
+
+
+
+
+
+
+
+
+
+
{
+ if (match(evt, keys.Escape)) {
+ setOpen(false);
+ }
+ }}
+ isTabTip
+ onRequestClose={() => setOpen(false)}>
+ {
+ setOpen(!open);
+ }}>
+
+
+
+
+
+
+
+
+
+ Edit columns
+
+
+
+
+
+
+
+ );
+};
+
export const TabTipExperimentalAutoAlign = () => {
const [open, setOpen] = useState(true);
const ref = useRef();
diff --git a/packages/react/src/components/Popover/index.tsx b/packages/react/src/components/Popover/index.tsx
index 44f5061555d3..36e59ea3c1a3 100644
--- a/packages/react/src/components/Popover/index.tsx
+++ b/packages/react/src/components/Popover/index.tsx
@@ -28,6 +28,7 @@ import {
autoUpdate,
arrow,
offset,
+ type Boundary,
} from '@floating-ui/react';
import { hide } from '@floating-ui/dom';
import { useFeatureFlag } from '../FeatureFlags';
@@ -102,6 +103,11 @@ interface PopoverBaseProps {
*/
autoAlign?: boolean;
+ /**
+ * Specify a bounding element to be used for autoAlign calculations. The viewport is used by default. This prop is currently experimental and is subject to future changes.
+ */
+ autoAlignBoundary?: Boundary;
+
/**
* Specify whether a caret should be rendered
*/
@@ -165,6 +171,7 @@ export const Popover: PopoverComponent = React.forwardRef(
align: initialAlign = isTabTip ? 'bottom-start' : 'bottom',
as: BaseComponent = 'span' as E,
autoAlign = false,
+ autoAlignBoundary,
caret = isTabTip ? false : true,
className: customClassName,
children,
@@ -292,6 +299,7 @@ export const Popover: PopoverComponent = React.forwardRef(
fallbackStrategy: 'initialPlacement',
fallbackAxisSideDirection: 'start',
+ boundary: autoAlignBoundary,
}),
arrow({
element: caretRef,
@@ -476,7 +484,7 @@ export const Popover: PopoverComponent = React.forwardRef(
);
}
-);
+) as PopoverComponent;
// Note: this displayName is temporarily set so that Storybook ArgTable
// correctly displays the name of this component
@@ -546,6 +554,21 @@ Popover.propTypes = {
*/
autoAlign: PropTypes.bool,
+ /**
+ * Specify a bounding element to be used for autoAlign calculations. The viewport is used by default. This prop is currently experimental and is subject to future changes.
+ */
+ autoAlignBoundary: PropTypes.oneOfType([
+ PropTypes.oneOf(['clippingAncestors']),
+ PropTypes.elementType,
+ PropTypes.arrayOf(PropTypes.elementType),
+ PropTypes.exact({
+ x: PropTypes.number.isRequired,
+ y: PropTypes.number.isRequired,
+ width: PropTypes.number.isRequired,
+ height: PropTypes.number.isRequired,
+ }),
+ ]) as PropTypes.Validator,
+
/**
* Specify whether a caret should be rendered
*/