Skip to content

Commit 45aabaa

Browse files
authored
feat(action-menu, combobox, dropdown, input-date-picker, popover): allow logical placements for flipPlacements property. #8825 (#9490)
**Related Issue:** #8825 ## Summary - Allow logical placements in the `flipPlacements` array property. - This allows placement options such as `leading`, `leading-start`, `trailing`, etc. Not any `auto` options. - Updates tests
1 parent d0fba56 commit 45aabaa

File tree

8 files changed

+53
-45
lines changed

8 files changed

+53
-45
lines changed

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

+12-12
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { Alignment, Appearance, CollapseDirection, FlipContext, IconType, Kind,
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 { EffectivePlacement, LogicalPlacement, MenuPlacement, OverlayPositioning, ReferenceElement } from "./utils/floating-ui";
12+
import { FlipPlacement, LogicalPlacement, MenuPlacement, OverlayPositioning, ReferenceElement } from "./utils/floating-ui";
1313
import { ActionBarMessages } from "./components/action-bar/assets/action-bar/t9n";
1414
import { Columns } from "./components/action-group/interfaces";
1515
import { ActionGroupMessages } from "./components/action-group/assets/action-group/t9n";
@@ -100,7 +100,7 @@ export { Alignment, Appearance, CollapseDirection, FlipContext, IconType, Kind,
100100
export { RequestedItem } from "./components/accordion/interfaces";
101101
export { RequestedItem as RequestedItem1 } from "./components/accordion-item/interfaces";
102102
export { ActionMessages } from "./components/action/assets/action/t9n";
103-
export { EffectivePlacement, LogicalPlacement, MenuPlacement, OverlayPositioning, ReferenceElement } from "./utils/floating-ui";
103+
export { FlipPlacement, LogicalPlacement, MenuPlacement, OverlayPositioning, ReferenceElement } from "./utils/floating-ui";
104104
export { ActionBarMessages } from "./components/action-bar/assets/action-bar/t9n";
105105
export { Columns } from "./components/action-group/interfaces";
106106
export { ActionGroupMessages } from "./components/action-group/assets/action-group/t9n";
@@ -430,7 +430,7 @@ export namespace Components {
430430
/**
431431
* Defines the available placements that can be used when a flip occurs.
432432
*/
433-
"flipPlacements": EffectivePlacement[];
433+
"flipPlacements": FlipPlacement[];
434434
/**
435435
* Specifies the text string for the component.
436436
*/
@@ -1231,7 +1231,7 @@ export namespace Components {
12311231
/**
12321232
* Defines the available placements that can be used when a flip occurs.
12331233
*/
1234-
"flipPlacements": EffectivePlacement[];
1234+
"flipPlacements": FlipPlacement[];
12351235
/**
12361236
* The `id` of the form that will be associated with the component. When not set, the component will be associated with its ancestor form element, if any.
12371237
*/
@@ -1629,7 +1629,7 @@ export namespace Components {
16291629
/**
16301630
* Defines the available placements that can be used when a flip occurs.
16311631
*/
1632-
"flipPlacements": EffectivePlacement[];
1632+
"flipPlacements": FlipPlacement[];
16331633
/**
16341634
* Specifies the maximum number of `calcite-dropdown-item`s to display before showing a scroller. Value must be greater than `0`, and does not include `groupTitle`'s from `calcite-dropdown-group`.
16351635
*/
@@ -2251,7 +2251,7 @@ export namespace Components {
22512251
/**
22522252
* Defines the available placements that can be used when a flip occurs.
22532253
*/
2254-
"flipPlacements": EffectivePlacement[];
2254+
"flipPlacements": FlipPlacement[];
22552255
/**
22562256
* When `true`, prevents focus trapping.
22572257
*/
@@ -3838,7 +3838,7 @@ export namespace Components {
38383838
/**
38393839
* Defines the available placements that can be used when a flip occurs.
38403840
*/
3841-
"flipPlacements": EffectivePlacement[];
3841+
"flipPlacements": FlipPlacement[];
38423842
/**
38433843
* When `true`, prevents focus trapping.
38443844
*/
@@ -8124,7 +8124,7 @@ declare namespace LocalJSX {
81248124
/**
81258125
* Defines the available placements that can be used when a flip occurs.
81268126
*/
8127-
"flipPlacements"?: EffectivePlacement[];
8127+
"flipPlacements"?: FlipPlacement[];
81288128
/**
81298129
* Specifies the text string for the component.
81308130
*/
@@ -8986,7 +8986,7 @@ declare namespace LocalJSX {
89868986
/**
89878987
* Defines the available placements that can be used when a flip occurs.
89888988
*/
8989-
"flipPlacements"?: EffectivePlacement[];
8989+
"flipPlacements"?: FlipPlacement[];
89908990
/**
89918991
* The `id` of the form that will be associated with the component. When not set, the component will be associated with its ancestor form element, if any.
89928992
*/
@@ -9427,7 +9427,7 @@ declare namespace LocalJSX {
94279427
/**
94289428
* Defines the available placements that can be used when a flip occurs.
94299429
*/
9430-
"flipPlacements"?: EffectivePlacement[];
9430+
"flipPlacements"?: FlipPlacement[];
94319431
/**
94329432
* Specifies the maximum number of `calcite-dropdown-item`s to display before showing a scroller. Value must be greater than `0`, and does not include `groupTitle`'s from `calcite-dropdown-group`.
94339433
*/
@@ -10065,7 +10065,7 @@ declare namespace LocalJSX {
1006510065
/**
1006610066
* Defines the available placements that can be used when a flip occurs.
1006710067
*/
10068-
"flipPlacements"?: EffectivePlacement[];
10068+
"flipPlacements"?: FlipPlacement[];
1006910069
/**
1007010070
* When `true`, prevents focus trapping.
1007110071
*/
@@ -11749,7 +11749,7 @@ declare namespace LocalJSX {
1174911749
/**
1175011750
* Defines the available placements that can be used when a flip occurs.
1175111751
*/
11752-
"flipPlacements"?: EffectivePlacement[];
11752+
"flipPlacements"?: FlipPlacement[];
1175311753
/**
1175411754
* When `true`, prevents focus trapping.
1175511755
*/

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
import { Fragment, VNode } from "@stencil/core/internal";
1313
import { getRoundRobinIndex } from "../../utils/array";
1414
import { focusElement, toAriaBoolean } from "../../utils/dom";
15-
import { EffectivePlacement, LogicalPlacement, OverlayPositioning } from "../../utils/floating-ui";
15+
import { FlipPlacement, LogicalPlacement, OverlayPositioning } from "../../utils/floating-ui";
1616
import { guid } from "../../utils/guid";
1717
import { isActivationKey } from "../../utils/key";
1818
import {
@@ -82,7 +82,7 @@ export class ActionMenu implements LoadableComponent {
8282
/**
8383
* Defines the available placements that can be used when a flip occurs.
8484
*/
85-
@Prop() flipPlacements: EffectivePlacement[];
85+
@Prop() flipPlacements: FlipPlacement[];
8686

8787
/**
8888
* Specifies the text string for the component.

packages/calcite-components/src/components/combobox/combobox.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ import {
2020
connectFloatingUI,
2121
defaultMenuPlacement,
2222
disconnectFloatingUI,
23-
EffectivePlacement,
24-
filterComputedPlacements,
23+
filterValidFlipPlacements,
24+
FlipPlacement,
2525
FloatingCSS,
2626
FloatingUIComponent,
2727
LogicalPlacement,
@@ -283,7 +283,7 @@ export class Combobox
283283
/**
284284
* Defines the available placements that can be used when a flip occurs.
285285
*/
286-
@Prop() flipPlacements: EffectivePlacement[];
286+
@Prop() flipPlacements: FlipPlacement[];
287287

288288
/**
289289
* Made into a prop for testing purposes only
@@ -523,7 +523,7 @@ export class Combobox
523523

524524
placement: LogicalPlacement = defaultMenuPlacement;
525525

526-
filteredFlipPlacements: EffectivePlacement[];
526+
filteredFlipPlacements: FlipPlacement[];
527527

528528
internalValueChangeFlag = false;
529529

@@ -629,7 +629,7 @@ export class Combobox
629629
const { el, flipPlacements } = this;
630630

631631
this.filteredFlipPlacements = flipPlacements
632-
? filterComputedPlacements(flipPlacements, el)
632+
? filterValidFlipPlacements(flipPlacements, el)
633633
: null;
634634
};
635635

packages/calcite-components/src/components/dropdown/dropdown.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import {
1616
connectFloatingUI,
1717
defaultMenuPlacement,
1818
disconnectFloatingUI,
19-
EffectivePlacement,
20-
filterComputedPlacements,
19+
filterValidFlipPlacements,
20+
FlipPlacement,
2121
FloatingCSS,
2222
FloatingUIComponent,
2323
MenuPlacement,
@@ -107,7 +107,7 @@ export class Dropdown
107107
/**
108108
* Defines the available placements that can be used when a flip occurs.
109109
*/
110-
@Prop() flipPlacements: EffectivePlacement[];
110+
@Prop() flipPlacements: FlipPlacement[];
111111

112112
@Watch("flipPlacements")
113113
flipPlacementsHandler(): void {
@@ -421,7 +421,7 @@ export class Dropdown
421421

422422
@Element() el: HTMLCalciteDropdownElement;
423423

424-
filteredFlipPlacements: EffectivePlacement[];
424+
filteredFlipPlacements: FlipPlacement[];
425425

426426
private items: HTMLCalciteDropdownItemElement[] = [];
427427

@@ -466,7 +466,7 @@ export class Dropdown
466466
const { el, flipPlacements } = this;
467467

468468
this.filteredFlipPlacements = flipPlacements
469-
? filterComputedPlacements(flipPlacements, el)
469+
? filterValidFlipPlacements(flipPlacements, el)
470470
: null;
471471
};
472472

packages/calcite-components/src/components/input-date-picker/input-date-picker.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ import {
2828
connectFloatingUI,
2929
defaultMenuPlacement,
3030
disconnectFloatingUI,
31-
EffectivePlacement,
32-
filterComputedPlacements,
31+
filterValidFlipPlacements,
3332
FloatingCSS,
3433
FloatingUIComponent,
34+
FlipPlacement,
3535
MenuPlacement,
3636
OverlayPositioning,
3737
reposition,
@@ -201,7 +201,7 @@ export class InputDatePicker
201201
/**
202202
* Defines the available placements that can be used when a flip occurs.
203203
*/
204-
@Prop() flipPlacements: EffectivePlacement[];
204+
@Prop() flipPlacements: FlipPlacement[];
205205

206206
@Watch("flipPlacements")
207207
flipPlacementsHandler(): void {
@@ -720,7 +720,7 @@ export class InputDatePicker
720720

721721
private dialogId = `date-picker-dialog--${guid()}`;
722722

723-
filteredFlipPlacements: EffectivePlacement[];
723+
filteredFlipPlacements: FlipPlacement[];
724724

725725
private focusOnOpen = false;
726726

@@ -814,7 +814,7 @@ export class InputDatePicker
814814
const { el, flipPlacements } = this;
815815

816816
this.filteredFlipPlacements = flipPlacements
817-
? filterComputedPlacements(flipPlacements, el)
817+
? filterValidFlipPlacements(flipPlacements, el)
818818
: null;
819819
};
820820

packages/calcite-components/src/components/popover/popover.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import {
1616
connectFloatingUI,
1717
defaultOffsetDistance,
1818
disconnectFloatingUI,
19-
EffectivePlacement,
20-
filterComputedPlacements,
19+
filterValidFlipPlacements,
20+
FlipPlacement,
2121
FloatingCSS,
2222
FloatingLayout,
2323
FloatingUIComponent,
@@ -121,7 +121,7 @@ export class Popover
121121
/**
122122
* Defines the available placements that can be used when a flip occurs.
123123
*/
124-
@Prop() flipPlacements: EffectivePlacement[];
124+
@Prop() flipPlacements: FlipPlacement[];
125125

126126
@Watch("flipPlacements")
127127
flipPlacementsHandler(): void {
@@ -253,7 +253,7 @@ export class Popover
253253
this.updateFocusTrapElements(),
254254
);
255255

256-
filteredFlipPlacements: EffectivePlacement[];
256+
filteredFlipPlacements: FlipPlacement[];
257257

258258
@State() effectiveLocale = "";
259259

@@ -409,7 +409,7 @@ export class Popover
409409
const { el, flipPlacements } = this;
410410

411411
this.filteredFlipPlacements = flipPlacements
412-
? filterComputedPlacements(flipPlacements, el)
412+
? filterValidFlipPlacements(flipPlacements, el)
413413
: null;
414414
};
415415

packages/calcite-components/src/utils/floating-ui.spec.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ const {
77
connectFloatingUI,
88
defaultOffsetDistance,
99
disconnectFloatingUI,
10-
effectivePlacements,
11-
filterComputedPlacements,
10+
flipPlacements,
11+
filterValidFlipPlacements,
1212
getEffectivePlacement,
1313
placements,
1414
positionFloatingUI,
@@ -197,8 +197,8 @@ it("should have correct value for defaultOffsetDistance", () => {
197197
expect(defaultOffsetDistance).toBe(6);
198198
});
199199

200-
it("should filter computed placements", () => {
201-
expect(new Set(filterComputedPlacements([...placements], document.createElement("div")))).toEqual(
202-
new Set(effectivePlacements),
200+
it("should filter valid placements", () => {
201+
expect(new Set(filterValidFlipPlacements([...placements], document.createElement("div")))).toEqual(
202+
new Set(flipPlacements),
203203
);
204204
});

packages/calcite-components/src/utils/floating-ui.ts

+14-6
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export const positionFloatingUI =
9191
overlayPositioning: Strategy;
9292
placement: LogicalPlacement;
9393
flipDisabled?: boolean;
94-
flipPlacements?: EffectivePlacement[];
94+
flipPlacements?: FlipPlacement[];
9595
offsetDistance?: number;
9696
offsetSkidding?: number;
9797
arrowEl?: SVGElement;
@@ -117,7 +117,7 @@ export const positionFloatingUI =
117117
middleware: getMiddleware({
118118
placement,
119119
flipDisabled,
120-
flipPlacements,
120+
flipPlacements: flipPlacements?.map((placement) => getEffectivePlacement(floatingEl, placement)),
121121
offsetDistance,
122122
offsetSkidding,
123123
arrowEl,
@@ -244,7 +244,9 @@ export const menuEffectivePlacements: EffectivePlacement[] = [
244244
"bottom-end",
245245
];
246246

247-
export const flipPlacements: EffectivePlacement[] = [
247+
export type FlipPlacement = Exclude<LogicalPlacement, "auto" | "auto-start" | "auto-end">;
248+
249+
export const flipPlacements: FlipPlacement[] = [
248250
"top",
249251
"bottom",
250252
"right",
@@ -257,6 +259,12 @@ export const flipPlacements: EffectivePlacement[] = [
257259
"right-end",
258260
"left-start",
259261
"left-end",
262+
"leading",
263+
"trailing",
264+
"leading-start",
265+
"leading-end",
266+
"trailing-start",
267+
"trailing-end",
260268
];
261269

262270
export type MenuPlacement = Extract<
@@ -374,14 +382,14 @@ function getMiddleware({
374382
return [];
375383
}
376384

377-
export function filterComputedPlacements(placements: string[], el: HTMLElement): EffectivePlacement[] {
385+
export function filterValidFlipPlacements(placements: string[], el: HTMLElement): EffectivePlacement[] {
378386
const filteredPlacements = placements.filter((placement: EffectivePlacement) =>
379-
effectivePlacements.includes(placement),
387+
flipPlacements.includes(placement),
380388
) as EffectivePlacement[];
381389

382390
if (filteredPlacements.length !== placements.length) {
383391
console.warn(
384-
`${el.tagName}: Invalid value found in: flipPlacements. Try any of these: ${effectivePlacements
392+
`${el.tagName}: Invalid value found in: flipPlacements. Try any of these: ${flipPlacements
385393
.map((placement) => `"${placement}"`)
386394
.join(", ")
387395
.trim()}`,

0 commit comments

Comments
 (0)