From e31a3ceba8fedcb3fbaada4290dfd849d5631e59 Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Mon, 9 Sep 2024 11:41:12 -0700 Subject: [PATCH 1/9] feat(action-group, block, panel): add 'placement' and 'flipPlacements' properties. #7516 --- .../calcite-components/src/components.d.ts | 48 +++++++++++++++++ .../action-group/action-group.e2e.ts | 52 ++++++++++++++++++- .../components/action-group/action-group.tsx | 31 +++++++++-- .../src/components/block/block.e2e.ts | 35 +++++++++++++ .../src/components/block/block.tsx | 26 +++++++++- .../src/components/panel/panel.e2e.ts | 34 ++++++++++++ .../src/components/panel/panel.tsx | 18 +++++-- 7 files changed, 232 insertions(+), 12 deletions(-) diff --git a/packages/calcite-components/src/components.d.ts b/packages/calcite-components/src/components.d.ts index 718aac02da7..424aff1e7c2 100644 --- a/packages/calcite-components/src/components.d.ts +++ b/packages/calcite-components/src/components.d.ts @@ -395,6 +395,10 @@ export namespace Components { * When `true`, the component is expanded. */ "expanded": boolean; + /** + * Defines the available placements that can be used when a flip occurs. + */ + "flipPlacements": FlipPlacement[]; /** * Accessible name for the component. */ @@ -420,6 +424,10 @@ export namespace Components { * 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"`. */ "overlayPositioning": OverlayPositioning; + /** + * Determines where the action menu will be positioned. + */ + "placement": LogicalPlacement; /** * Specifies the size of the `calcite-action-menu`. */ @@ -626,6 +634,10 @@ export namespace Components { * When `true`, displays a drag handle in the header. */ "dragHandle": boolean; + /** + * Defines the available placements that can be used when a flip occurs. + */ + "flipPlacements": FlipPlacement[]; /** * The component header text. */ @@ -666,6 +678,10 @@ export namespace Components { * 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"`. */ "overlayPositioning": OverlayPositioning; + /** + * Determines where the action menu will be positioned. + */ + "placement": LogicalPlacement; /** * Sets focus on the component's first tabbable element. */ @@ -3858,6 +3874,10 @@ export namespace Components { * When `true`, interaction is prevented and the component is displayed with lower opacity. */ "disabled": boolean; + /** + * Defines the available placements that can be used when a flip occurs. + */ + "flipPlacements": FlipPlacement[]; /** * The component header text. */ @@ -3886,6 +3906,10 @@ export namespace Components { * 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"`. */ "overlayPositioning": OverlayPositioning; + /** + * Determines where the action menu will be positioned. + */ + "placement": LogicalPlacement; /** * Specifies the size of the component. */ @@ -8321,6 +8345,10 @@ declare namespace LocalJSX { * When `true`, the component is expanded. */ "expanded"?: boolean; + /** + * Defines the available placements that can be used when a flip occurs. + */ + "flipPlacements"?: FlipPlacement[]; /** * Accessible name for the component. */ @@ -8346,6 +8374,10 @@ declare namespace LocalJSX { * 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"`. */ "overlayPositioning"?: OverlayPositioning; + /** + * Determines where the action menu will be positioned. + */ + "placement"?: LogicalPlacement; /** * Specifies the size of the `calcite-action-menu`. */ @@ -8559,6 +8591,10 @@ declare namespace LocalJSX { * When `true`, displays a drag handle in the header. */ "dragHandle"?: boolean; + /** + * Defines the available placements that can be used when a flip occurs. + */ + "flipPlacements"?: FlipPlacement[]; /** * The component header text. */ @@ -8620,6 +8656,10 @@ declare namespace LocalJSX { * 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"`. */ "overlayPositioning"?: OverlayPositioning; + /** + * Determines where the action menu will be positioned. + */ + "placement"?: LogicalPlacement; /** * Displays a status-related indicator icon. * @deprecated Use `icon-start` instead. @@ -11980,6 +12020,10 @@ declare namespace LocalJSX { * When `true`, interaction is prevented and the component is displayed with lower opacity. */ "disabled"?: boolean; + /** + * Defines the available placements that can be used when a flip occurs. + */ + "flipPlacements"?: FlipPlacement[]; /** * The component header text. */ @@ -12020,6 +12064,10 @@ declare namespace LocalJSX { * 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"`. */ "overlayPositioning"?: OverlayPositioning; + /** + * Determines where the action menu will be positioned. + */ + "placement"?: LogicalPlacement; /** * Specifies the size of the component. */ diff --git a/packages/calcite-components/src/components/action-group/action-group.e2e.ts b/packages/calcite-components/src/components/action-group/action-group.e2e.ts index 288761da844..17b04f95f21 100755 --- a/packages/calcite-components/src/components/action-group/action-group.e2e.ts +++ b/packages/calcite-components/src/components/action-group/action-group.e2e.ts @@ -1,5 +1,15 @@ import { newE2EPage } from "@stencil/core/testing"; -import { accessible, defaults, focusable, hidden, renders, slots, t9n, themed } from "../../tests/commonTests"; +import { + accessible, + defaults, + focusable, + hidden, + reflects, + renders, + slots, + t9n, + themed, +} from "../../tests/commonTests"; import { html } from "../../../support/formatting"; import { CSS, SLOTS } from "./resources"; @@ -19,6 +29,23 @@ describe("calcite-action-group", () => { propertyName: "overlayPositioning", defaultValue: "absolute", }, + { + propertyName: "placement", + defaultValue: undefined, + }, + { + propertyName: "flipPlacements", + defaultValue: undefined, + }, + ]); + }); + + describe("reflects", () => { + reflects("calcite-action-group", [ + { + propertyName: "placement", + value: "bottom", + }, ]); }); @@ -42,6 +69,29 @@ describe("calcite-action-group", () => { slots("calcite-action-group", SLOTS); }); + it("sets placement and flipPlacements on internal calcite-action-menu", async () => { + const page = await newE2EPage({ + html: html` + + + + + `, + }); + await page.waitForChanges(); + + const flipPlacements = ["top", "bottom"]; + + const actionGroup = await page.find("calcite-action-group"); + actionGroup.setProperty("flipPlacements", flipPlacements); + await page.waitForChanges(); + + const actionMenu = await page.find("calcite-action-group >>> calcite-action-menu"); + + expect(await actionMenu.getProperty("placement")).toBe("top"); + expect(await actionMenu.getProperty("flipPlacements")).toEqual(flipPlacements); + }); + it("should honor scale of expand icon", async () => { const page = await newE2EPage({ html: actionGroupHTML }); const menu = await page.find(`calcite-action-group >>> calcite-action-menu`); diff --git a/packages/calcite-components/src/components/action-group/action-group.tsx b/packages/calcite-components/src/components/action-group/action-group.tsx index 4d9f309e002..e03f0f9636e 100755 --- a/packages/calcite-components/src/components/action-group/action-group.tsx +++ b/packages/calcite-components/src/components/action-group/action-group.tsx @@ -21,7 +21,7 @@ import { } from "../../utils/t9n"; import { SLOTS as ACTION_MENU_SLOTS } from "../action-menu/resources"; import { Layout, Scale } from "../interfaces"; -import { OverlayPositioning } from "../../utils/floating-ui"; +import { FlipPlacement, LogicalPlacement, OverlayPositioning } from "../../utils/floating-ui"; import { slotChangeHasAssignedElement } from "../../utils/dom"; import { Columns } from "./interfaces"; import { ActionGroupMessages } from "./assets/action-group/t9n"; @@ -59,6 +59,11 @@ export class ActionGroup this.menuOpen = false; } + /** + * Defines the available placements that can be used when a flip occurs. + */ + @Prop() flipPlacements: FlipPlacement[]; + /** * Accessible name for the component. */ @@ -90,6 +95,11 @@ export class ActionGroup */ @Prop({ reflect: true }) overlayPositioning: OverlayPositioning = "absolute"; + /** + * Determines where the action menu will be positioned. + */ + @Prop({ reflect: true }) placement: LogicalPlacement; + /** * Specifies the size of the `calcite-action-menu`. */ @@ -178,19 +188,30 @@ export class ActionGroup // -------------------------------------------------------------------------- renderMenu(): VNode { - const { expanded, menuOpen, scale, layout, messages, overlayPositioning, hasMenuActions } = - this; + const { + expanded, + menuOpen, + scale, + layout, + messages, + overlayPositioning, + hasMenuActions, + flipPlacements, + placement, + } = this; return (