diff --git a/packages/fiori/src/FlexibleColumnLayout.ts b/packages/fiori/src/FlexibleColumnLayout.ts index 0a8f900b4dcd..684fdbba67d1 100644 --- a/packages/fiori/src/FlexibleColumnLayout.ts +++ b/packages/fiori/src/FlexibleColumnLayout.ts @@ -10,6 +10,8 @@ import { supportsTouch } from "@ui5/webcomponents-base/dist/Device.js"; import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; import AnimationMode from "@ui5/webcomponents-base/dist/types/AnimationMode.js"; import { getAnimationMode } from "@ui5/webcomponents-base/dist/config/AnimationMode.js"; +import Icon from "@ui5/webcomponents/dist/Icon.js"; +import Button from "@ui5/webcomponents/dist/Button.js"; import "@ui5/webcomponents-icons/dist/vertical-grip.js"; import { renderFinished } from "@ui5/webcomponents-base/dist/Render.js"; import { @@ -19,12 +21,15 @@ import { isRightShift, isHome, isEnd, + isEnter, + isSpace, } from "@ui5/webcomponents-base/dist/Keys.js"; import type { PassiveEventListenerObject, AriaLandmarkRole } from "@ui5/webcomponents-base"; import FCLLayout from "./types/FCLLayout.js"; import type { LayoutConfiguration } from "./fcl-utils/FCLLayout.js"; import { getLayoutsByMedia, + getNextLayoutByArrowPress, } from "./fcl-utils/FCLLayout.js"; // Texts @@ -167,6 +172,7 @@ type UserDefinedColumnLayouts = { renderer: jsxRenderer, styles: FlexibleColumnLayoutCss, template: FlexibleColumnLayoutTemplate, + dependencies: [Icon, Button], }) /** @@ -476,6 +482,9 @@ class FlexibleColumnLayout extends UI5Element { } onSeparatorPress(e: TouchEvent | MouseEvent) { + if (e.target as HTMLElement === this.startArrowDOM) { + return; + } const pressedSeparator = (e.target as HTMLElement).closest(".ui5-fcl-separator") as HTMLElement; if (pressedSeparator.classList.contains("ui5-fcl-separator-start") && !this.showStartSeparatorGrip) { return; @@ -654,11 +663,26 @@ class FlexibleColumnLayout extends UI5Element { return columnLayoutToAdjust; } - async _onkeydown(e: KeyboardEvent) { + _onArrowKeydown(e: KeyboardEvent) { + if (isEnter(e) || isSpace(e)) { + e.preventDefault(); + const focusedElement = e.target as HTMLElement; + if (focusedElement === this.startArrowDOM) { + this.switchLayoutOnArrowPress(); + } + } + } + + async _onSeparatorKeydown(e: KeyboardEvent) { + const separator = e.target as HTMLElement; + if (!separator.classList.contains("ui5-fcl-separator")) { + return; + } const stepSize = 2, bigStepSize = this._width, isRTL = this.effectiveDir === "rtl"; let step = 0; + if (isLeft(e)) { step = -stepSize * 10; } else if (isRight(e)) { @@ -679,7 +703,6 @@ class FlexibleColumnLayout extends UI5Element { return; } - const separator = e.target as HTMLElement; if (!this.separatorMovementSession) { this.separatorMovementSession = this.initSeparatorMovementSession(separator, 0, false); } @@ -693,7 +716,7 @@ class FlexibleColumnLayout extends UI5Element { separator.focus(); } - _onkeyup() { + _onSeparatorKeyUp() { if (this.separatorMovementSession) { this.onSeparatorMoveEnd(); } @@ -818,6 +841,30 @@ class FlexibleColumnLayout extends UI5Element { return FCLLayout.ThreeColumnsMidExpanded; } + if (moved({ + separator: "start", + from: FCLLayout.ThreeColumnsStartHiddenMidExpanded, + forward: true, + }) && !isTablet && Math.ceil(startColumnPxWidth) >= COLUMN_MIN_WIDTH) { + return FCLLayout.ThreeColumnsMidExpanded; + } + + if (moved({ + separator: "end", + from: FCLLayout.ThreeColumnsStartHiddenMidExpanded, + forward: false, + }) && newColumnWidths.mid < newColumnWidths.end) { + return FCLLayout.ThreeColumnsStartHiddenEndExpanded; + } + + if (moved({ + separator: "end", + from: FCLLayout.ThreeColumnsStartHiddenEndExpanded, + forward: true, + }) && newColumnWidths.mid >= newColumnWidths.end) { + return FCLLayout.ThreeColumnsStartHiddenMidExpanded; + } + if (moved({ separator: "end", from: FCLLayout.ThreeColumnsMidExpandedEndHidden, @@ -880,6 +927,14 @@ class FlexibleColumnLayout extends UI5Element { return fclLayoutBeforeMove; // no layout change } + switchLayoutOnArrowPress() { + const lastUsedLayout = this.layout as FCLLayout; + this.layout = getNextLayoutByArrowPress()[lastUsedLayout as keyof typeof getNextLayoutByArrowPress]; + if (this.layout !== lastUsedLayout) { + this.fireLayoutChange(true, false); + } + } + get _availableWidthForColumns() { let width = this._width; if (this.showStartSeparator) { @@ -982,6 +1037,10 @@ class FlexibleColumnLayout extends UI5Element { return this.disableResizing ? false : this.startSeparatorGripVisibility; } + get showStartSeparatorArrow() { + return this.disableResizing ? false : this.startSeparatorArrowVisibility; + } + get showEndSeparatorGrip() { return this.disableResizing ? false : this.endSeparatorGripVisibility; } @@ -994,6 +1053,18 @@ class FlexibleColumnLayout extends UI5Element { return this.effectiveSeparatorsInfo[1].gripVisible; } + get startSeparatorArrowVisibility() { + return this.effectiveSeparatorsInfo[0].arrowVisible; + } + + get startArrowDirection() { + return this.effectiveSeparatorsInfo[0].arrowDirection; + } + + get startArrowDOM() { + return this.shadowRoot!.querySelector(".ui5-fcl-arrow--start")!; + } + get effectiveSeparatorsInfo() { return this._effectiveLayoutsByMedia[this.media][this.effectiveLayout].separators; } diff --git a/packages/fiori/src/FlexibleColumnLayoutTemplate.tsx b/packages/fiori/src/FlexibleColumnLayoutTemplate.tsx index 8241bfa1d9b3..f71620202f74 100644 --- a/packages/fiori/src/FlexibleColumnLayoutTemplate.tsx +++ b/packages/fiori/src/FlexibleColumnLayoutTemplate.tsx @@ -2,6 +2,7 @@ import AnimationMode from "@ui5/webcomponents-base/dist/types/AnimationMode.js"; import { getAnimationMode } from "@ui5/webcomponents-base/dist/InitialConfiguration.js"; import verticalGrip from "@ui5/webcomponents-icons/dist/vertical-grip.js"; import Icon from "@ui5/webcomponents/dist/Icon.js"; +import Button from "@ui5/webcomponents/dist/Button.js"; import type FlexibleColumnLayout from "./FlexibleColumnLayout.js"; export default function FlexibleColumnLayoutTemplate(this: FlexibleColumnLayout) { @@ -31,9 +32,10 @@ export default function FlexibleColumnLayoutTemplate(this: FlexibleColumnLayout) tabindex={this.startSeparatorTabIndex} onMouseDown={this.onSeparatorPress} onTouchStart={this.onSeparatorPress} - onKeyDown={this._onkeydown} - onKeyUp={this._onkeyup} + onKeyDown={this._onSeparatorKeydown} + onKeyUp={this._onSeparatorKeyUp} > + { this.showStartSeparatorArrow && arrowStart.call(this) } { gripStart.call(this) } @@ -59,8 +61,8 @@ export default function FlexibleColumnLayoutTemplate(this: FlexibleColumnLayout) tabindex={this.endSeparatorTabIndex} onMouseDown={this.onSeparatorPress} onTouchStart={this.onSeparatorPress} - onKeyDown={this._onkeydown} - onKeyUp={this._onkeyup} + onKeyDown={this._onSeparatorKeydown} + onKeyUp={this._onSeparatorKeyUp} > { gripEnd.call(this) } @@ -82,6 +84,18 @@ export default function FlexibleColumnLayoutTemplate(this: FlexibleColumnLayout) ); } +function arrowStart(this: FlexibleColumnLayout) { + return ( +