Skip to content

Commit 714b889

Browse files
authored
feat(action-bar, action-pad, block, flow-item, panel): add overlayPositioning prop for built-in menus (#8633)
**Related Issue:** #8620 ## Summary This allows users to specify `overlayPositioning` to help escape scrolling containers for underlying menus. **Note**: this adds a new helper (`delegatesToFloatingUiOwningComponent`) to shallowly test if a component has a floating-ui-owning component wired up.
1 parent 1ae60f7 commit 714b889

File tree

13 files changed

+371
-9
lines changed

13 files changed

+371
-9
lines changed

packages/calcite-components/src/components.d.ts

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import { Alignment, Appearance, Columns, FlipContext, Kind, Layout, LogicalFlowP
99
import { RequestedItem } from "./components/accordion/interfaces";
1010
import { RequestedItem as RequestedItem1 } from "./components/accordion-item/interfaces";
1111
import { ActionMessages } from "./components/action/assets/action/t9n";
12-
import { ActionBarMessages } from "./components/action-bar/assets/action-bar/t9n";
1312
import { EffectivePlacement, LogicalPlacement, MenuPlacement, OverlayPositioning, ReferenceElement } from "./utils/floating-ui";
13+
import { ActionBarMessages } from "./components/action-bar/assets/action-bar/t9n";
1414
import { ActionGroupMessages } from "./components/action-group/assets/action-group/t9n";
1515
import { ActionPadMessages } from "./components/action-pad/assets/action-pad/t9n";
1616
import { AlertDuration, Sync } from "./components/alert/interfaces";
@@ -95,8 +95,8 @@ export { Alignment, Appearance, Columns, FlipContext, Kind, Layout, LogicalFlowP
9595
export { RequestedItem } from "./components/accordion/interfaces";
9696
export { RequestedItem as RequestedItem1 } from "./components/accordion-item/interfaces";
9797
export { ActionMessages } from "./components/action/assets/action/t9n";
98-
export { ActionBarMessages } from "./components/action-bar/assets/action-bar/t9n";
9998
export { EffectivePlacement, LogicalPlacement, MenuPlacement, OverlayPositioning, ReferenceElement } from "./utils/floating-ui";
99+
export { ActionBarMessages } from "./components/action-bar/assets/action-bar/t9n";
100100
export { ActionGroupMessages } from "./components/action-group/assets/action-group/t9n";
101101
export { ActionPadMessages } from "./components/action-pad/assets/action-pad/t9n";
102102
export { AlertDuration, Sync } from "./components/alert/interfaces";
@@ -344,6 +344,10 @@ export namespace Components {
344344
* Disables automatically overflowing `calcite-action`s that won't fit into menus.
345345
*/
346346
"overflowActionsDisabled": boolean;
347+
/**
348+
* Determines the type of positioning to use for the overlaid content. Using `"absolute"` will work for most cases. The component will be positioned inside of overflowing parent containers and will affect the container's layout. `"fixed"` should be used to escape an overflowing parent container, or when the reference element's `position` CSS property is `"fixed"`.
349+
*/
350+
"overlayPositioning": OverlayPositioning;
347351
/**
348352
* Arranges the component depending on the element's `dir` property.
349353
*/
@@ -463,6 +467,10 @@ export namespace Components {
463467
* Made into a prop for testing purposes only
464468
*/
465469
"messages": ActionPadMessages;
470+
/**
471+
* Determines the type of positioning to use for the overlaid content. Using `"absolute"` will work for most cases. The component will be positioned inside of overflowing parent containers and will affect the container's layout. `"fixed"` should be used to escape an overflowing parent container, or when the reference element's `position` CSS property is `"fixed"`.
472+
*/
473+
"overlayPositioning": OverlayPositioning;
466474
/**
467475
* Arranges the component depending on the element's `dir` property.
468476
*/
@@ -604,6 +612,10 @@ export namespace Components {
604612
* When `true`, expands the component and its contents.
605613
*/
606614
"open": boolean;
615+
/**
616+
* Determines the type of positioning to use for the overlaid content. Using `"absolute"` will work for most cases. The component will be positioned inside of overflowing parent containers and will affect the container's layout. `"fixed"` should be used to escape an overflowing parent container, or when the reference element's `position` CSS property is `"fixed"`.
617+
*/
618+
"overlayPositioning": OverlayPositioning;
607619
/**
608620
* Sets focus on the component's first tabbable element.
609621
*/
@@ -1724,6 +1736,10 @@ export namespace Components {
17241736
* Made into a prop for testing purposes only
17251737
*/
17261738
"messages": FlowItemMessages;
1739+
/**
1740+
* Determines the type of positioning to use for the overlaid content. Using `"absolute"` will work for most cases. The component will be positioned inside of overflowing parent containers and will affect the container's layout. `"fixed"` should be used to escape an overflowing parent container, or when the reference element's `position` CSS property is `"fixed"`.
1741+
*/
1742+
"overlayPositioning": OverlayPositioning;
17271743
/**
17281744
* Scrolls the component's content to a specified set of coordinates.
17291745
* @example myCalciteFlowItem.scrollContentTo({ left: 0, // Specifies the number of pixels along the X axis to scroll the window or element. top: 0, // Specifies the number of pixels along the Y axis to scroll the window or element behavior: "auto" // Specifies whether the scrolling should animate smoothly (smooth), or happen instantly in a single jump (auto, the default value). });
@@ -3433,6 +3449,10 @@ export namespace Components {
34333449
* Made into a prop for testing purposes only
34343450
*/
34353451
"messages": PanelMessages;
3452+
/**
3453+
* Determines the type of positioning to use for the overlaid content. Using `"absolute"` will work for most cases. The component will be positioned inside of overflowing parent containers and will affect the container's layout. `"fixed"` should be used to escape an overflowing parent container, or when the reference element's `position` CSS property is `"fixed"`.
3454+
*/
3455+
"overlayPositioning": OverlayPositioning;
34363456
/**
34373457
* Scrolls the component's content to a specified set of coordinates.
34383458
* @example myCalciteFlowItem.scrollContentTo({ left: 0, // Specifies the number of pixels along the X axis to scroll the window or element. top: 0, // Specifies the number of pixels along the Y axis to scroll the window or element behavior: "auto" // Specifies whether the scrolling should animate smoothly (smooth), or happen instantly in a single jump (auto, the default value). });
@@ -7567,6 +7587,10 @@ declare namespace LocalJSX {
75677587
* Disables automatically overflowing `calcite-action`s that won't fit into menus.
75687588
*/
75697589
"overflowActionsDisabled"?: boolean;
7590+
/**
7591+
* Determines the type of positioning to use for the overlaid content. Using `"absolute"` will work for most cases. The component will be positioned inside of overflowing parent containers and will affect the container's layout. `"fixed"` should be used to escape an overflowing parent container, or when the reference element's `position` CSS property is `"fixed"`.
7592+
*/
7593+
"overlayPositioning"?: OverlayPositioning;
75707594
/**
75717595
* Arranges the component depending on the element's `dir` property.
75727596
*/
@@ -7682,6 +7706,10 @@ declare namespace LocalJSX {
76827706
* Fires when the `expanded` property is toggled.
76837707
*/
76847708
"onCalciteActionPadToggle"?: (event: CalciteActionPadCustomEvent<void>) => void;
7709+
/**
7710+
* Determines the type of positioning to use for the overlaid content. Using `"absolute"` will work for most cases. The component will be positioned inside of overflowing parent containers and will affect the container's layout. `"fixed"` should be used to escape an overflowing parent container, or when the reference element's `position` CSS property is `"fixed"`.
7711+
*/
7712+
"overlayPositioning"?: OverlayPositioning;
76857713
/**
76867714
* Arranges the component depending on the element's `dir` property.
76877715
*/
@@ -7860,6 +7888,10 @@ declare namespace LocalJSX {
78607888
* When `true`, expands the component and its contents.
78617889
*/
78627890
"open"?: boolean;
7891+
/**
7892+
* Determines the type of positioning to use for the overlaid content. Using `"absolute"` will work for most cases. The component will be positioned inside of overflowing parent containers and will affect the container's layout. `"fixed"` should be used to escape an overflowing parent container, or when the reference element's `position` CSS property is `"fixed"`.
7893+
*/
7894+
"overlayPositioning"?: OverlayPositioning;
78637895
/**
78647896
* Displays a status-related indicator icon.
78657897
*/
@@ -9053,6 +9085,10 @@ declare namespace LocalJSX {
90539085
* Fires when the collapse button is clicked.
90549086
*/
90559087
"onCalciteFlowItemToggle"?: (event: CalciteFlowItemCustomEvent<void>) => void;
9088+
/**
9089+
* Determines the type of positioning to use for the overlaid content. Using `"absolute"` will work for most cases. The component will be positioned inside of overflowing parent containers and will affect the container's layout. `"fixed"` should be used to escape an overflowing parent container, or when the reference element's `position` CSS property is `"fixed"`.
9090+
*/
9091+
"overlayPositioning"?: OverlayPositioning;
90569092
/**
90579093
* When `true`, displays a back button in the component's header.
90589094
*/
@@ -10863,6 +10899,10 @@ declare namespace LocalJSX {
1086310899
* Fires when the collapse button is clicked.
1086410900
*/
1086510901
"onCalcitePanelToggle"?: (event: CalcitePanelCustomEvent<void>) => void;
10902+
/**
10903+
* Determines the type of positioning to use for the overlaid content. Using `"absolute"` will work for most cases. The component will be positioned inside of overflowing parent containers and will affect the container's layout. `"fixed"` should be used to escape an overflowing parent container, or when the reference element's `position` CSS property is `"fixed"`.
10904+
*/
10905+
"overlayPositioning"?: OverlayPositioning;
1086610906
}
1086710907
/**
1086810908
* @deprecated Use the `list` component instead.

packages/calcite-components/src/components/action-bar/action-bar.e2e.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
import { newE2EPage } from "@stencil/core/testing";
22
import { html } from "../../../support/formatting";
3-
import { accessible, defaults, focusable, hidden, reflects, renders, slots, t9n } from "../../tests/commonTests";
3+
import {
4+
accessible,
5+
defaults,
6+
delegatesToFloatingUiOwningComponent,
7+
focusable,
8+
hidden,
9+
reflects,
10+
renders,
11+
slots,
12+
t9n,
13+
} from "../../tests/commonTests";
414
import { CSS, SLOTS } from "./resources";
515
import { overflowActionsDebounceInMs } from "./utils";
616
import { getFocusedElementProp } from "../../tests/utils";
@@ -32,6 +42,10 @@ describe("calcite-action-bar", () => {
3242
propertyName: "layout",
3343
defaultValue: "vertical",
3444
},
45+
{
46+
propertyName: "overlayPositioning",
47+
defaultValue: "absolute",
48+
},
3549
]);
3650
});
3751

@@ -45,9 +59,22 @@ describe("calcite-action-bar", () => {
4559
propertyName: "expanded",
4660
value: true,
4761
},
62+
{
63+
propertyName: "overlayPositioning",
64+
value: "fixed",
65+
},
4866
]);
4967
});
5068

69+
describe("delegates to floating-ui-owner component", () => {
70+
delegatesToFloatingUiOwningComponent(
71+
html`<calcite-action-bar>
72+
<calcite-action id="plus" slot="menu-actions" text="Add" icon="plus"></calcite-action>
73+
</calcite-action-bar>`,
74+
"calcite-action-group",
75+
);
76+
});
77+
5178
describe("expand functionality", () => {
5279
it("should not modify actions within an action-menu", async () => {
5380
const page = await newE2EPage({

packages/calcite-components/src/components/action-bar/action-bar.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import {
4848
overflowActionsDebounceInMs,
4949
queryActions,
5050
} from "./utils";
51+
import { OverlayPositioning } from "../../utils/floating-ui";
5152

5253
/**
5354
* @slot - A slot for adding `calcite-action`s that will appear at the top of the component.
@@ -123,6 +124,16 @@ export class ActionBar
123124
this.overflowActions();
124125
}
125126

127+
/**
128+
* Determines the type of positioning to use for the overlaid content.
129+
*
130+
* Using `"absolute"` will work for most cases. The component will be positioned inside of overflowing parent containers and will affect the container's layout.
131+
*
132+
* `"fixed"` should be used to escape an overflowing parent container, or when the reference element's `position` CSS property is `"fixed"`.
133+
*
134+
*/
135+
@Prop({ reflect: true }) overlayPositioning: OverlayPositioning = "absolute";
136+
126137
/**
127138
* Arranges the component depending on the element's `dir` property.
128139
*/
@@ -391,6 +402,7 @@ export class ActionBar
391402
layout,
392403
messages,
393404
actionsEndGroupLabel,
405+
overlayPositioning,
394406
} = this;
395407

396408
const expandToggleNode = !expandDisabled ? (
@@ -414,6 +426,7 @@ export class ActionBar
414426
hidden={this.expandDisabled && !(this.hasActionsEnd || this.hasBottomActions)}
415427
label={actionsEndGroupLabel}
416428
layout={layout}
429+
overlayPositioning={overlayPositioning}
417430
scale={scale}
418431
>
419432
<slot name={SLOTS.actionsEnd} onSlotchange={this.handleActionsEndSlotChange} />

packages/calcite-components/src/components/action-menu/action-menu.e2e.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import { newE2EPage } from "@stencil/core/testing";
22
import { html } from "../../../support/formatting";
3-
import { accessible, defaults, focusable, hidden, reflects, renders, slots } from "../../tests/commonTests";
3+
import {
4+
accessible,
5+
defaults,
6+
delegatesToFloatingUiOwningComponent,
7+
focusable,
8+
hidden,
9+
reflects,
10+
renders,
11+
slots,
12+
} from "../../tests/commonTests";
413
import { TOOLTIP_OPEN_DELAY_MS } from "../tooltip/resources";
514
import { CSS, SLOTS, activeAttr } from "./resources";
615

@@ -84,6 +93,15 @@ describe("calcite-action-menu", () => {
8493
]);
8594
});
8695

96+
describe("delegates to floating-ui-owner component", () => {
97+
delegatesToFloatingUiOwningComponent(
98+
html`<calcite-action-menu>
99+
<calcite-action text="Plus" icon="plus" text-enabled></calcite-action>
100+
</calcite-action-menu>`,
101+
"calcite-popover",
102+
);
103+
});
104+
87105
it("should emit 'calciteActionMenuOpen' event", async () => {
88106
const page = await newE2EPage({
89107
html: `<calcite-action-menu>

packages/calcite-components/src/components/action-pad/action-pad.e2e.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
import { newE2EPage } from "@stencil/core/testing";
2-
import { accessible, defaults, focusable, hidden, reflects, renders, slots, t9n } from "../../tests/commonTests";
2+
import {
3+
accessible,
4+
defaults,
5+
delegatesToFloatingUiOwningComponent,
6+
focusable,
7+
hidden,
8+
reflects,
9+
renders,
10+
slots,
11+
t9n,
12+
} from "../../tests/commonTests";
313
import { CSS, SLOTS } from "./resources";
414
import { html } from "../../../support/formatting";
515

@@ -26,6 +36,10 @@ describe("calcite-action-pad", () => {
2636
propertyName: "layout",
2737
defaultValue: "vertical",
2838
},
39+
{
40+
propertyName: "overlayPositioning",
41+
defaultValue: "absolute",
42+
},
2943
{
3044
propertyName: "scale",
3145
defaultValue: undefined,
@@ -47,9 +61,22 @@ describe("calcite-action-pad", () => {
4761
propertyName: "layout",
4862
value: "horizontal",
4963
},
64+
{
65+
propertyName: "overlayPositioning",
66+
value: "fixed",
67+
},
5068
]);
5169
});
5270

71+
describe("delegates to floating-ui-owner component", () => {
72+
delegatesToFloatingUiOwningComponent(
73+
html`<calcite-action-pad>
74+
<calcite-action id="plus" slot="menu-actions" text="Add" icon="plus"></calcite-action>
75+
</calcite-action-pad>`,
76+
"calcite-action-group",
77+
);
78+
});
79+
5380
describe("expand functionality", () => {
5481
it("should be expandable by default", async () => {
5582
const page = await newE2EPage();

packages/calcite-components/src/components/action-pad/action-pad.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { Layout, Position, Scale } from "../interfaces";
3636
import { ActionPadMessages } from "./assets/action-pad/t9n";
3737
import { CSS, SLOTS } from "./resources";
3838
import { createObserver } from "../../utils/observers";
39+
import { OverlayPositioning } from "../../utils/floating-ui";
3940

4041
/**
4142
* @slot - A slot for adding `calcite-action`s to the component.
@@ -117,6 +118,16 @@ export class ActionPad
117118
/* wired up by t9n util */
118119
}
119120

121+
/**
122+
* Determines the type of positioning to use for the overlaid content.
123+
*
124+
* Using `"absolute"` will work for most cases. The component will be positioned inside of overflowing parent containers and will affect the container's layout.
125+
*
126+
* `"fixed"` should be used to escape an overflowing parent container, or when the reference element's `position` CSS property is `"fixed"`.
127+
*
128+
*/
129+
@Prop({ reflect: true }) overlayPositioning: OverlayPositioning = "absolute";
130+
120131
// --------------------------------------------------------------------------
121132
//
122133
// Events
@@ -265,6 +276,7 @@ export class ActionPad
265276
scale,
266277
layout,
267278
actionsEndGroupLabel,
279+
overlayPositioning,
268280
} = this;
269281

270282
const expandToggleNode = !expandDisabled ? (
@@ -287,6 +299,7 @@ export class ActionPad
287299
class={CSS.actionGroupEnd}
288300
label={actionsEndGroupLabel}
289301
layout={layout}
302+
overlayPositioning={overlayPositioning}
290303
scale={scale}
291304
>
292305
<slot name={SLOTS.expandTooltip} onSlotchange={this.handleTooltipSlotChange} />

0 commit comments

Comments
 (0)