diff --git a/packages/fiori/bundle.esm.js b/packages/fiori/bundle.esm.js index 3c1c7f9df6ff..22a617506423 100644 --- a/packages/fiori/bundle.esm.js +++ b/packages/fiori/bundle.esm.js @@ -7,6 +7,7 @@ import "./dist/Assets.js"; import "./dist/features/CoPilotAnimation.js"; // FIORI components +import FlexibleColumnLayout from "./dist/FlexibleColumnLayout.js"; import ProductSwitch from "./dist/ProductSwitch.js"; import ProductSwitchItem from "./dist/ProductSwitchItem.js"; import ShellBar from "./dist/ShellBar.js"; diff --git a/packages/fiori/src/FlexibleColumnLayout.hbs b/packages/fiori/src/FlexibleColumnLayout.hbs new file mode 100644 index 000000000000..0624fb6b7a33 --- /dev/null +++ b/packages/fiori/src/FlexibleColumnLayout.hbs @@ -0,0 +1,52 @@ +
OneColumn
TwoColumnsStartExpanded
TwoColumnsMidExpanded
ThreeColumnsMidExpanded
ThreeColumnsEndExpanded
ThreeColumnsStartExpandedEndHidden
ThreeColumnsMidExpandedEndHidden
MidColumnFullScreen
EndColumnFullScreen
TwoColumnsStartExpanded
means the layout will display up to two columns
+ * in 67%/33% proportion.
+ * @type {FCLLayout}
+ * @defaultvalue "OneColumn"
+ * @public
+ */
+ layout: {
+ type: FCLLayout,
+ defaultValue: FCLLayout.OneColumn,
+ },
+
+ /**
+ * Defines the visibility of the arrows,
+ * used for expanding and shrinking the columns.
+ *
+ * @type {boolean}
+ * @defaultvalue false
+ * @public
+ */
+ noArrows: {
+ type: Boolean,
+ },
+
+ /**
+ * Defines the component width in px.
+ *
+ * @type {Float}
+ * @defaultvalue 0
+ * @private
+ */
+ _width: {
+ type: Float,
+ defaultValue: 0,
+ },
+
+ /**
+ * Defines the effective columns layout,
+ * based on both the layout
property and the screen size.
+ * Example: [67%, "33%, 0"], [25%, 50%, 25%], etc.
+ *
+ * @type {Object}
+ * @defaultvalue undefined
+ * @private
+ */
+ _columnLayout: {
+ type: Object,
+ defaultValue: undefined,
+ },
+
+ /**
+ * Defines the visible columns count - 1, 2 or 3.
+ *
+ * @type {Integer}
+ * @defaultvalue 1
+ * @private
+ */
+ _visibleColumns: {
+ type: Integer,
+ defaultValue: 0,
+ },
+ },
+ slots: /** @lends sap.ui.webcomponents.fiori.FlexibleColumnLayout.prototype */ {
+ /**
+ * Defines the content in the start column.
+ * @type {HTMLElement}
+ * @slot
+ * @public
+ */
+ startColumn: {
+ type: HTMLElement,
+ },
+
+ /**
+ * Defines the content in the middle column.
+ * @type {HTMLElement}
+ * @slot
+ * @public
+ */
+ midColumn: {
+ type: HTMLElement,
+ },
+
+ /**
+ * Defines the content in the end column.
+ * @type {HTMLElement}
+ * @slot
+ * @public
+ */
+ endColumn: {
+ type: HTMLElement,
+ },
+ },
+ events: /** @lends sap.ui.webcomponents.fiori.FlexibleColumnLayout.prototype */ {
+ /**
+ * Fired when the layout changes via user interaction by clicking the arrows
+ * or by changing the component size due to resizing.
+ *
+ * @param {FCLLayout} layout the current layout
+ * @param {Array} columnLayout the effective column layout, f.e [67%, 33%, 0]
+ * @param {boolean} startColumnVisible indicates if the start column is currently visible
+ * @param {boolean} midColumnVisible indicates if the middle column is currently visible
+ * @param {boolean} endColumnVisible indicates if the end column is currently visible
+ * @param {boolean} arrowsUsed indicates if the layout is changed via the arrows
+ * @param {boolean} resize indicates if the layout is changed via resizing
+ * @event sap.ui.webcomponents.fiori.FlexibleColumnLayout#layout-change
+ * @public
+ */
+ "layout-change": {
+ detail: {
+ layout: { type: FCLLayout },
+ columnLayout: { type: Array },
+ startColumnVisible: { type: Boolean },
+ midColumnVisible: { type: Boolean },
+ endColumnVisible: { type: Boolean },
+ arrowsUsed: { type: Boolean },
+ resize: { type: Boolean },
+ },
+ },
+ },
+};
+
+/**
+ * @class
+ *
+ * FlexibleColumnLayout
implements the master-detail-detail paradigm by displaying up to three pages in separate columns.
+ * There are several possible layouts that can be changed either with the component API, or by pressing the arrows, displayed between the columns.
+ *
+ * FlexibleColumnLayout
automatically displays the maximum possible number of columns based on layout
property and the window size.
+ * The component would display 1 column for window size smaller than 900px, up to two columns between 900px and 1280px,
+ * and 3 columns for sizes bigger than 1280px.
+ *
+ * import @ui5/webcomponents-fiori/dist/FlexibleColumnLayout.js";
+ *
+ * @constructor
+ * @author SAP SE
+ * @alias sap.ui.webcomponents.fiori.FlexibleColumnLayout
+ * @extends UI5Element
+ * @tagname ui5-flexible-column-layout
+ * @public
+ * @since 1.0.0-rc.8
+ */
+class FlexibleColumnLayout extends UI5Element {
+ constructor() {
+ super();
+
+ this._prevLayout = null;
+ this.initialRendering = true;
+ this._handleResize = this.handleResize.bind(this);
+ this.i18nBundle = getI18nBundle("@ui5/webcomponents-fiori");
+ }
+
+ static get metadata() {
+ return metadata;
+ }
+
+ static get render() {
+ return litRender;
+ }
+
+ static get styles() {
+ return FlexibleColumnLayoutCss;
+ }
+
+ static get template() {
+ return FlexibleColumnLayoutTemplate;
+ }
+
+ static async onDefine() {
+ await Promise.all([
+ Button.define(),
+ fetchI18nBundle("@ui5/webcomponents-fiori"),
+ ]);
+ }
+
+ static get BREAKPOINTS() {
+ return {
+ "M": 960,
+ "L": 1280,
+ };
+ }
+
+ static get MEDIA() {
+ return {
+ PHONE: "phone",
+ TABLET: "tablet",
+ DESKTOP: "desktop",
+ };
+ }
+
+ onEnterDOM() {
+ ResizeHandler.register(this, this._handleResize);
+ }
+
+ onExitDOM() {
+ ResizeHandler.deregister(this, this._handleResize);
+ }
+
+ onAfterRendering() {
+ if (this.initialRendering) {
+ this.handleInitialRendering();
+ return;
+ }
+
+ this.syncLayout();
+ }
+
+ handleInitialRendering() {
+ this._prevLayout = this.layout;
+ this.updateLayout();
+ this.initialRendering = false;
+ }
+
+ handleResize() {
+ if (this.initialRendering) {
+ return;
+ }
+
+ // store the previous layout
+ const prevLayoutHash = this.columnLayout.join();
+
+ // update the column layout, based on the current width
+ this.updateLayout();
+
+ // fire layout-change if the column layout changed
+ if (prevLayoutHash !== this.columnLayout.join()) {
+ this.fireLayoutChange(false, true);
+ }
+ }
+
+ startArrowClick() {
+ this.arrowClick({ start: true, end: false });
+ }
+
+ endArrowClick() {
+ this.arrowClick({ start: false, end: true });
+ }
+
+ arrowClick({ start, end }) {
+ // update public property
+ this.layout = this.nextLayout(this.layout, { start, end });
+
+ // update layout
+ this.updateLayout();
+
+ // fire layout-change
+ this.fireLayoutChange(true, false);
+ }
+
+ updateLayout() {
+ this._width = this.widthDOM;
+ this._columnLayout = this.nextColumnLayout(this.layout);
+ this._visibleColumns = this.calcVisibleColumns(this._columnLayout);
+ this.toggleColumns();
+ }
+
+ syncLayout() {
+ if (this._prevLayout !== this.layout) {
+ this.updateLayout();
+ this._prevLayout = this.layout;
+ }
+ }
+
+ toggleColumns() {
+ const toggleStartColumn = this.startColumnWidth === 0 ? "add" : "remove";
+ this.startColumnDOM.classList[toggleStartColumn](".ui5-fcl-column--hidden");
+
+ const toggleMidColumn = this.startColumnWidth === 0 ? "add" : "remove";
+ this.midColumnDOM.classList[toggleMidColumn](".ui5-fcl-column--hidden");
+
+ const toggleEndColumn = this.startColumnWidth === 0 ? "add" : "remove";
+ this.endColumnDOM.classList[toggleEndColumn](".ui5-fcl-column--hidden");
+ }
+
+ nextLayout(layout, arrowsInfo = {}) {
+ if (arrowsInfo.start) {
+ return getNextLayoutByStartArrow()[layout];
+ }
+
+ if (arrowsInfo.end) {
+ return getNextLayoutByEndArrow()[layout];
+ }
+ }
+
+ nextColumnLayout(layout) {
+ return getLayoutsByMedia()[this.media][layout].layout;
+ }
+
+ calcVisibleColumns(colLayot) {
+ return colLayot.filter(col => col !== 0).length;
+ }
+
+ fireLayoutChange(arrowUsed, resize) {
+ this.fireEvent("layout-change", {
+ layout: this.layout,
+ columnLayout: this._columnLayout,
+ startColumnVisible: this.startColumnVisible,
+ midColumnVisible: this.midColumnVisible,
+ endColumnVisible: this.endColumnVisible,
+ arrowUsed,
+ resize,
+ });
+ }
+
+ /**
+ * Returns the current column layout, based on both the layout
property and the screen size.
+ * start
column is visible.
+ * @readonly
+ * @defaultvalue true
+ * @type { boolean }
+ * @public
+ */
+ get startColumnVisible() {
+ if (this._columnLayout) {
+ return this._columnLayout[0] !== 0;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns if the middle
column is visible.
+ * @readonly
+ * @type { boolean }
+ * @defaultvalue false
+ * @public
+ */
+ get midColumnVisible() {
+ if (this._columnLayout) {
+ return this._columnLayout[1] !== 0;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns if the end
column is visible.
+ * @readonly
+ * @type { boolean }
+ * @defaultvalue false
+ * @public
+ */
+ get endColumnVisible() {
+ if (this._columnLayout) {
+ return this._columnLayout[2] !== 0;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the number of currently visible columns.
+ * @readonly
+ * @type { Integer }
+ * @defaultvalue 1
+ * @public
+ */
+ get visibleColumns() {
+ return this._visibleColumns;
+ }
+
+ get classes() {
+ return {
+ columns: {
+ start: {
+ "ui5-fcl-column": true,
+ "ui5-fcl-column--start": true,
+ },
+ middle: {
+ "ui5-fcl-column": true,
+ "ui5-fcl-column--middle": true,
+ },
+ end: {
+ "ui5-fcl-column": true,
+ "ui5-fcl-column--end": true,
+ },
+ },
+ };
+ }
+
+ get styles() {
+ return {
+ columns: {
+ start: {
+ width: this.startColumnWidth,
+ },
+ middle: {
+ width: this.midColumnWidth,
+ },
+ end: {
+ width: this.endColumnWidth,
+ },
+ },
+ arrowsContainer: {
+ start: {
+ display: this.showStartSeparator ? "flex" : "none",
+ },
+ end: {
+ display: this.showEndSeparator ? "flex" : "none",
+ },
+ },
+ arrows: {
+ start: {
+ display: this.showStartArrow ? "inline-block" : "none",
+ transform: this.startArrowDirection === "mirror" ? "rotate(180deg)" : "",
+ },
+ end: {
+ display: this.showEndArrow ? "inline-block" : "none",
+ transform: this.endArrowDirection === "mirror" ? "rotate(180deg)" : "",
+ },
+ },
+ };
+ }
+
+ get startColumnWidth() {
+ return this._columnLayout ? this._columnLayout[0] : "100%";
+ }
+
+ get midColumnWidth() {
+ return this._columnLayout ? this._columnLayout[1] : 0;
+ }
+
+ get endColumnWidth() {
+ return this._columnLayout ? this._columnLayout[2] : 0;
+ }
+
+ get showStartSeparator() {
+ return this.effectiveArrowsInfo[0].separator || this.startArrowVisibility;
+ }
+
+ get showEndSeparator() {
+ return this.effectiveArrowsInfo[1].separator || this.endArrowVisibility;
+ }
+
+ get showStartArrow() {
+ return this.noArrows ? false : this.startArrowVisibility;
+ }
+
+ get showEndArrow() {
+ return this.noArrows ? false : this.endArrowVisibility;
+ }
+
+ get startArrowVisibility() {
+ return this.effectiveArrowsInfo[0].visible;
+ }
+
+ get endArrowVisibility() {
+ return this.effectiveArrowsInfo[1].visible;
+ }
+
+ get startArrowDirection() {
+ return this.effectiveArrowsInfo[0].dir;
+ }
+
+ get endArrowDirection() {
+ return this.effectiveArrowsInfo[1].dir;
+ }
+
+ get effectiveArrowsInfo() {
+ return getLayoutsByMedia()[this.media][this.layout].arrows;
+ }
+
+ get media() {
+ if (this._width <= FlexibleColumnLayout.BREAKPOINTS.M) {
+ return FlexibleColumnLayout.MEDIA.PHONE;
+ }
+
+ if (this._width <= FlexibleColumnLayout.BREAKPOINTS.L) {
+ return FlexibleColumnLayout.MEDIA.TABLET;
+ }
+
+ return FlexibleColumnLayout.MEDIA.DESKTOP;
+ }
+
+ get widthDOM() {
+ return this.getBoundingClientRect().width;
+ }
+
+ get startColumnDOM() {
+ return this.shadowRoot.querySelector(".ui5-fcl-column--start");
+ }
+
+ get midColumnDOM() {
+ return this.shadowRoot.querySelector(".ui5-fcl-column--middle");
+ }
+
+ get endColumnDOM() {
+ return this.shadowRoot.querySelector(".ui5-fcl-column--end");
+ }
+
+ get accStartColumnText() {
+ return this.i18nBundle.getText(FCL_START_COLUMN_TXT);
+ }
+
+ get accMiddleColumnText() {
+ return this.i18nBundle.getText(FCL_MIDDLE_COLUMN_TXT);
+ }
+
+ get accEndColumnText() {
+ return this.i18nBundle.getText(FCL_END_COLUMN_TXT);
+ }
+}
+
+FlexibleColumnLayout.define();
+
+export default FlexibleColumnLayout;
diff --git a/packages/fiori/src/fcl-utils/FCLLayout.js b/packages/fiori/src/fcl-utils/FCLLayout.js
new file mode 100644
index 000000000000..fb6c5397d088
--- /dev/null
+++ b/packages/fiori/src/fcl-utils/FCLLayout.js
@@ -0,0 +1,246 @@
+const getLayoutsByMedia = () => {
+ return {
+ desktop: {
+ "OneColumn": {
+ layout: ["100%", 0, 0],
+ arrows: [
+ { visible: false, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ "TwoColumnsStartExpanded": {
+ layout: ["67%", "33%", 0],
+ arrows: [
+ { visible: true, dir: "mirror" },
+ { visible: false, dir: null },
+ ],
+ },
+ "TwoColumnsMidExpanded": {
+ layout: ["33%", "67%", 0],
+ arrows: [
+ { visible: true, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ "ThreeColumnsStartExpanded": {
+ layout: ["25%", "50%", "25%"],
+ arrows: [
+ { visible: true, dir: null },
+ { visible: true, dir: null },
+ ],
+ },
+ "ThreeColumnsMidExpanded": {
+ layout: ["25%", "50%", "25%"],
+ arrows: [
+ { visible: true, dir: null },
+ { visible: true, dir: null },
+ ],
+ },
+ "ThreeColumnsEndExpanded": {
+ layout: ["25%", "25%", "50%"],
+ arrows: [
+ { visible: false, dir: null, separator: true },
+ { visible: true, dir: "mirror" },
+ ],
+ },
+ "ThreeColumnsStartExpandedEndHidden": {
+ layout: ["67%", "33%", 0],
+ arrows: [
+ { visible: true, dir: "mirror" },
+ { visible: false, dir: null },
+ ],
+ },
+ "ThreeColumnsMidExpandedEndHidden": {
+ layout: ["33%", "67%", 0],
+ arrows: [
+ { visible: true, dir: null },
+ { visible: true, dir: null },
+ ],
+ },
+ "MidColumnFullScreen": {
+ layout: [0, "100%", 0],
+ arrows: [
+ { visible: false, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ "EndColumnFullScreen": {
+ layout: [0, 0, "100%"],
+ arrows: [
+ { visible: false, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ },
+ tablet: {
+ "OneColumn": {
+ layout: ["100%", 0, 0],
+ arrows: [
+ { visible: false, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ "TwoColumnsStartExpanded": {
+ layout: ["67%", "33%", 0],
+ arrows: [
+ { visible: true, dir: "mirror" },
+ { visible: false, dir: null },
+ ],
+ },
+ "TwoColumnsMidExpanded": {
+ layout: ["33%", "67%", 0],
+ arrows: [
+ { visible: true, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ "ThreeColumnsStartExpanded": {
+ layout: ["67%", "33%", 0],
+ arrows: [
+ { visible: true, dir: "mirror" },
+ { visible: false, dir: null },
+ ],
+ },
+ "ThreeColumnsMidExpanded": {
+ layout: [0, "67%", "33%"],
+ arrows: [
+ { visible: true, dir: null },
+ { visible: true, dir: null },
+ ],
+ },
+ "ThreeColumnsEndExpanded": {
+ layout: [0, "33%", "67%"],
+ arrows: [
+ { visible: false, dir: null },
+ { visible: true, dir: "mirror" },
+ ],
+ },
+ "ThreeColumnsStartExpandedEndHidden": {
+ layout: ["67%", "33%", 0],
+ arrows: [
+ { visible: true, dir: "mirror" },
+ { visible: false, dir: null },
+ ],
+ },
+ "ThreeColumnsMidExpandedEndHidden": {
+ layout: ["33%", "67%", 0],
+ arrows: [
+ { visible: true, dir: null },
+ { visible: true, dir: null },
+ ],
+ },
+ "MidColumnFullScreen": {
+ layout: [0, "100%", 0],
+ arrows: [
+ { visible: false, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ "EndColumnFullScreen": {
+ layout: [0, 0, "100%"],
+ arrows: [
+ { visible: false, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ },
+ phone: {
+ "OneColumn": {
+ layout: ["100%", 0, 0],
+ arrows: [
+ { visible: false, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ "TwoColumnsStartExpanded": {
+ layout: [0, "100%", 0],
+ arrows: [
+ { visible: false, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ "TwoColumnsMidExpanded": {
+ layout: [0, "100%", 0],
+ arrows: [
+ { visible: false, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ "ThreeColumnsStartExpanded": {
+ layout: [0, 0, "100%"],
+ arrows: [
+ { visible: false, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ "ThreeColumnsMidExpanded": {
+ layout: [0, 0, "100%"],
+ arrows: [
+ { visible: false, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ "ThreeColumnsEndExpanded": {
+ layout: [0, 0, "100%"],
+ arrows: [
+ { visible: false, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ "ThreeColumnsStartExpandedEndHidden": {
+ layout: [0, 0, "100%"],
+ arrows: [
+ { visible: false, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ "ThreeColumnsMidExpandedEndHidden": {
+ layout: [0, 0, "100%"],
+ arrows: [
+ { visible: false, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ "MidColumnFullScreen": {
+ layout: [0, "100%", 0],
+ arrows: [
+ { visible: false, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ "EndColumnFullScreen": {
+ layout: [0, 0, "100%"],
+ arrows: [
+ { visible: false, dir: null },
+ { visible: false, dir: null },
+ ],
+ },
+ },
+ };
+};
+
+const getNextLayoutByStartArrow = () => {
+ return {
+ "TwoColumnsStartExpanded": "TwoColumnsMidExpanded",
+ "TwoColumnsMidExpanded": "TwoColumnsStartExpanded",
+ "ThreeColumnsMidExpanded": "ThreeColumnsMidExpandedEndHidden",
+ "ThreeColumnsEndExpanded": "ThreeColumnsStartExpandedEndHidden",
+ "ThreeColumnsStartExpandedEndHidden": "ThreeColumnsMidExpandedEndHidden",
+ "ThreeColumnsMidExpandedEndHidden": "ThreeColumnsStartExpandedEndHidden",
+ };
+};
+
+const getNextLayoutByEndArrow = () => {
+ return {
+ "ThreeColumnsMidExpanded": "ThreeColumnsEndExpanded",
+ "ThreeColumnsEndExpanded": "ThreeColumnsMidExpanded",
+ "ThreeColumnsStartExpandedEndHidden": "ThreeColumnsMidExpanded",
+ "ThreeColumnsMidExpandedEndHidden": "ThreeColumnsMidExpanded",
+ };
+};
+
+export {
+ getLayoutsByMedia,
+ getNextLayoutByStartArrow,
+ getNextLayoutByEndArrow,
+};
diff --git a/packages/fiori/src/i18n/messagebundle.properties b/packages/fiori/src/i18n/messagebundle.properties
index 8215c96b335c..c18daa4c2ed2 100644
--- a/packages/fiori/src/i18n/messagebundle.properties
+++ b/packages/fiori/src/i18n/messagebundle.properties
@@ -1,6 +1,15 @@
#This is the resource bundle for the UI5 Web Components
#__ldi.translation.uuid=95d47730-48a4-4d6d-92f6-61f8c9d8f274
+#XTXT: Text for the FlexibleColumnLayout start column
+FCL_START_COLUMN_TXT=First column
+
+#XTXT: Text for the FlexibleColumnLayout mid column
+FCL_MIDDLE_COLUMN_TXT=Middle column
+
+#XTXT: Text for the FlexibleColumnLayout end column
+FCL_END_COLUMN_TXT=Last column
+
#XTXT: Text for the NotificationListGroupItem
NOTIFICATION_LIST_ITEM_TXT=Notification
diff --git a/packages/fiori/src/themes/FlexibleColumnLayout.css b/packages/fiori/src/themes/FlexibleColumnLayout.css
new file mode 100644
index 000000000000..0b661c18bce5
--- /dev/null
+++ b/packages/fiori/src/themes/FlexibleColumnLayout.css
@@ -0,0 +1,102 @@
+@import "./InvisibleTextStyles.css";
+
+:host(:not([hidden])) {
+ display: block;
+ background: var(--_ui5_fcl_solid_bg);
+}
+
+.ui5-fcl-root {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+}
+
+/* columns */
+.ui5-fcl-column {
+ background: inherit;
+ box-sizing: border-box;
+ transition: width 560ms cubic-bezier(0.1, 0, 0.05, 1), visibility 560ms ease-in;
+ will-change: width;
+ overflow-y: auto;
+}
+
+:host([_visible-columns="2"]) .ui5-fcl-column--start {
+ border-right: var(--_ui5_fcl_column_border);
+}
+
+:host([_visible-columns="3"]) .ui5-fcl-column--start {
+ border-right: var(--_ui5_fcl_column_border);
+}
+
+:host([_visible-columns="2"]) .ui5-fcl-column--middle {
+ border-left: var(--_ui5_fcl_column_border)
+}
+
+:host([_visible-columns="3"]) .ui5-fcl-column--middle {
+ border-left: var(--_ui5_fcl_column_border)
+}
+
+:host([_visible-columns="3"]) .ui5-fcl-column--middle {
+ border-right: var(--_ui5_fcl_column_border)
+}
+
+:host([_visible-columns="3"]) .ui5-fcl-column--end {
+ border-left: var(--_ui5_fcl_column_border);
+}
+
+.ui5-fcl-column--hidden {
+ height: 0;
+ width: 0;
+ position: absolute;
+ visibility: hidden;
+}
+
+/* arrow */
+.ui5-fcl-arrow-container {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 1rem;
+ background-color: var(--sapShell_Background);
+}
+
+.ui5-fcl-arrow {
+ position: relative;
+ width: 1.5rem;
+ height: 1.5rem;
+ min-width: 1.5rem;
+ will-change: transform;
+ overflow: visible;
+ z-index: 1;
+}
+
+/* arrow decoration */
+.ui5-fcl-arrow:before {
+ background-image: var(--_ui5_fcl_decoration_top);
+ background-position-y: -0.3125rem;
+ bottom: 100%;
+}
+
+.ui5-fcl-arrow:after {
+ background-image: var(--_ui5_fcl_decoration_bottom);
+ background-position-y: 0.3125rem;
+ top: 100%;
+}
+
+.ui5-fcl-arrow:before,
+.ui5-fcl-arrow:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ height: 4rem;
+ width: 100%;
+ transition: all 0.1s ease-in;
+ background-repeat: no-repeat;
+ background-size: 0.0625rem 100%;
+ background-position-x: calc(50% - 0.03125rem);
+}
+
+.ui5-fcl-arrow:hover:before,
+.ui5-fcl-arrow:hover:after {
+ height: 7rem;
+}
\ No newline at end of file
diff --git a/packages/fiori/src/themes/base/FlexibleColumnLayout-parameters.css b/packages/fiori/src/themes/base/FlexibleColumnLayout-parameters.css
new file mode 100644
index 000000000000..1e4852190795
--- /dev/null
+++ b/packages/fiori/src/themes/base/FlexibleColumnLayout-parameters.css
@@ -0,0 +1,6 @@
+:root {
+ --_ui5_fcl_solid_bg: var(--sapShell_Background);
+ --_ui5_fcl_column_border: none;
+ --_ui5_fcl_decoration_top: linear-gradient(to top, var(--sapHighlightColor), #f3f4f5);
+ --_ui5_fcl_decoration_bottom: linear-gradient(to bottom, var(--sapHighlightColor), #f3f4f5);
+}
\ No newline at end of file
diff --git a/packages/fiori/src/themes/sap_belize/parameters-bundle.css b/packages/fiori/src/themes/sap_belize/parameters-bundle.css
index bb852676b2ec..c8fd179b1929 100644
--- a/packages/fiori/src/themes/sap_belize/parameters-bundle.css
+++ b/packages/fiori/src/themes/sap_belize/parameters-bundle.css
@@ -1,2 +1,3 @@
+@import "../base/FlexibleColumnLayout-parameters.css";
@import "../base/ProductSwitchItem-parameters.css";
@import "../base/UploadCollection-parameters.css";
\ No newline at end of file
diff --git a/packages/fiori/src/themes/sap_belize_hcb/FlexibleColumnLayout-parameters.css b/packages/fiori/src/themes/sap_belize_hcb/FlexibleColumnLayout-parameters.css
new file mode 100644
index 000000000000..59233058fe7c
--- /dev/null
+++ b/packages/fiori/src/themes/sap_belize_hcb/FlexibleColumnLayout-parameters.css
@@ -0,0 +1,6 @@
+:root {
+ --_ui5_fcl_solid_bg: var(--sapBackgroundColor);
+ --_ui5_fcl_column_border: solid 0.0625rem var(--sapGroup_ContentBorderColor);
+ --_ui5_fcl_decoration_top: linear-gradient(to top, var(--sapObjectHeader_BorderColor), #000);
+ --_ui5_fcl_decoration_bottom: linear-gradient(to bottom, var(--sapObjectHeader_BorderColor), #000);
+}
\ No newline at end of file
diff --git a/packages/fiori/src/themes/sap_belize_hcb/parameters-bundle.css b/packages/fiori/src/themes/sap_belize_hcb/parameters-bundle.css
index 97855c33e4b4..6babe5296a03 100644
--- a/packages/fiori/src/themes/sap_belize_hcb/parameters-bundle.css
+++ b/packages/fiori/src/themes/sap_belize_hcb/parameters-bundle.css
@@ -1,2 +1,3 @@
+@import "./FlexibleColumnLayout-parameters.css";
@import "./ProductSwitchItem-parameters.css";
@import "./UploadCollection-parameters.css";
\ No newline at end of file
diff --git a/packages/fiori/src/themes/sap_belize_hcw/FlexibleColumnLayout-parameters.css b/packages/fiori/src/themes/sap_belize_hcw/FlexibleColumnLayout-parameters.css
new file mode 100644
index 000000000000..f3e4b26212ba
--- /dev/null
+++ b/packages/fiori/src/themes/sap_belize_hcw/FlexibleColumnLayout-parameters.css
@@ -0,0 +1,6 @@
+:root {
+ --_ui5_fcl_solid_bg: var(--sapBackgroundColor);
+ --_ui5_fcl_column_border: solid 0.0625rem var(--sapGroup_ContentBorderColor);
+ --_ui5_fcl_decoration_top: linear-gradient(to top, var(--sapObjectHeader_BorderColor), #fff);
+ --_ui5_fcl_decoration_bottom: linear-gradient(to bottom, var(--sapObjectHeader_BorderColor), #fff);
+}
\ No newline at end of file
diff --git a/packages/fiori/src/themes/sap_belize_hcw/parameters-bundle.css b/packages/fiori/src/themes/sap_belize_hcw/parameters-bundle.css
index 97855c33e4b4..6babe5296a03 100644
--- a/packages/fiori/src/themes/sap_belize_hcw/parameters-bundle.css
+++ b/packages/fiori/src/themes/sap_belize_hcw/parameters-bundle.css
@@ -1,2 +1,3 @@
+@import "./FlexibleColumnLayout-parameters.css";
@import "./ProductSwitchItem-parameters.css";
@import "./UploadCollection-parameters.css";
\ No newline at end of file
diff --git a/packages/fiori/src/themes/sap_fiori_3/parameters-bundle.css b/packages/fiori/src/themes/sap_fiori_3/parameters-bundle.css
index bb852676b2ec..c8fd179b1929 100644
--- a/packages/fiori/src/themes/sap_fiori_3/parameters-bundle.css
+++ b/packages/fiori/src/themes/sap_fiori_3/parameters-bundle.css
@@ -1,2 +1,3 @@
+@import "../base/FlexibleColumnLayout-parameters.css";
@import "../base/ProductSwitchItem-parameters.css";
@import "../base/UploadCollection-parameters.css";
\ No newline at end of file
diff --git a/packages/fiori/src/themes/sap_fiori_3_dark/FlexibleColumnLayout-parameters.css b/packages/fiori/src/themes/sap_fiori_3_dark/FlexibleColumnLayout-parameters.css
new file mode 100644
index 000000000000..d8eafc04f01b
--- /dev/null
+++ b/packages/fiori/src/themes/sap_fiori_3_dark/FlexibleColumnLayout-parameters.css
@@ -0,0 +1,6 @@
+:root {
+ --_ui5_fcl_solid_bg: var(--sapShell_Background);
+ --_ui5_fcl_column_border: none;
+ --_ui5_fcl_decoration_top: linear-gradient(to top, var(--sapHighlightColor), #272f37);
+ --_ui5_fcl_decoration_bottom: linear-gradient(to bottom, var(--sapHighlightColor), #272f37);
+}
\ No newline at end of file
diff --git a/packages/fiori/src/themes/sap_fiori_3_dark/parameters-bundle.css b/packages/fiori/src/themes/sap_fiori_3_dark/parameters-bundle.css
index bb852676b2ec..f51cd989bb52 100644
--- a/packages/fiori/src/themes/sap_fiori_3_dark/parameters-bundle.css
+++ b/packages/fiori/src/themes/sap_fiori_3_dark/parameters-bundle.css
@@ -1,2 +1,3 @@
+@import "./FlexibleColumnLayout-parameters.css";
@import "../base/ProductSwitchItem-parameters.css";
@import "../base/UploadCollection-parameters.css";
\ No newline at end of file
diff --git a/packages/fiori/src/types/FCLLayout.js b/packages/fiori/src/types/FCLLayout.js
new file mode 100644
index 000000000000..e93bb9c12dc9
--- /dev/null
+++ b/packages/fiori/src/types/FCLLayout.js
@@ -0,0 +1,134 @@
+import DataType from "@ui5/webcomponents-base/dist/types/DataType.js";
+
+/**
+ * Different types of FCLLayout.
+ * @lends sap.ui.webcomponents.fiori.types.FCLLayout.prototype
+ * @public
+ */
+const FCLLayouts = {
+ /**
+ * The layout will display 1 column.
+ * @public
+ * @type {OneColumn}
+ */
+ OneColumn: "OneColumn",
+
+ /**
+ *
+ * Desktop: 67/33/- Start (expanded) and Mid columns are displayed
+ * Tablet: 67/33/- Start (expanded) and Mid columns are displayed
+ * Phone: -/100/- only the Mid column is displayed
+ *
+ * Use to display both a master and a detail page when the user should focus on the master page.
+ *
+ * @type {TwoColumnsStartExpanded}
+ * @public
+ */
+ TwoColumnsStartExpanded: "TwoColumnsStartExpanded",
+
+ /**
+ * Desktop: 33/67/- Start and Mid (expanded) columns are displayed
+ * Tablet: 33/67/- Start and Mid (expanded) columns are displayed
+ * Phone: -/100/- only the Mid column is displayed
+ *
+ * Use to display both a master and a detail page when the user should focus on the detail page.
+ *
+ * @type {TwoColumnsMidExpanded}
+ * @public
+ */
+ TwoColumnsMidExpanded: "TwoColumnsMidExpanded",
+
+ /**
+ * Desktop: 25/50/25 Start, Mid (expanded) and End columns are displayed
+ * Tablet: 0/67/33 Mid (expanded) and End columns are displayed, Start is accessible by a layout arrow
+ * Phone: -/-/100 only the End column is displayed
+ *
+ * Use to display all three pages (master, detail, detail-detail) when the user should focus on the detail.
+ *
+ * @type {ThreeColumnsMidExpanded}
+ * @public
+ */
+ ThreeColumnsMidExpanded: "ThreeColumnsMidExpanded",
+
+ /**
+ * Desktop: 25/25/50 Start, Mid and End (expanded) columns are displayed
+ * Tablet: 0/33/67 Mid and End (expanded) columns are displayed, Start is accessible by layout arrows
+ * Phone: -/-/100 (only the End column is displayed)
+ *
+ * Use to display all three pages (master, detail, detail-detail) when the user should focus on the detail-detail.
+ *
+ * @public
+ * @type ThreeColumnsEndExpanded
+ */
+ ThreeColumnsEndExpanded: "ThreeColumnsEndExpanded",
+
+ /**
+ * Desktop: 67/33/0 Start (expanded) and Mid columns are displayed, End is accessible by layout arrows
+ * Tablet: 67/33/0 Start (expanded) and Mid columns are displayed, End is accessible by layout arrows
+ * Phone: -/-/100 only the End column is displayed
+ *
+ * Use to display the master and detail pages when the user should focus on the master.
+ * The detail-detail is still loaded and easily accessible with layout arrows.
+ *
+ * @public
+ * @type ThreeColumnsStartExpandedEndHidden
+ */
+ ThreeColumnsStartExpandedEndHidden: "ThreeColumnsStartExpandedEndHidden",
+
+ /**
+ * Desktop: 33/67/0 Start and Mid (expanded) columns are displayed, End is accessible by a layout arrow
+ * Tablet: 33/67/0 Start and Mid (expanded) columns are displayed, End is accessible by a layout arrow
+ * Phone: -/-/100 only the End column is displayed
+ *
+ * Use to display the master and detail pages when the user should focus on the detail.
+ * The detail-detail is still loaded and easily accessible with a layout arrow.
+ *
+ * @public
+ * @type ThreeColumnsMidExpandedEndHidden
+ */
+ ThreeColumnsMidExpandedEndHidden: "ThreeColumnsMidExpandedEndHidden",
+
+ /**
+ * Desktop: -/100/- only the Mid column is displayed
+ * Tablet: -/100/- only the Mid column is displayed
+ * Phone: -/100/- only the Mid column is displayed
+ *
+ * Use to display a detail page only, when the user should focus entirely on it.
+ *
+ * @public
+ * @type MidColumnFullScreen
+ */
+ MidColumnFullScreen: "MidColumnFullScreen",
+
+ /**
+ * Desktop: -/-/100 only the End column is displayed
+ * Tablet: -/-/100 only the End column is displayed
+ * Phone: -/-/100 only the End column is displayed
+ *
+ * Use to display a detail-detail page only, when the user should focus entirely on it.
+ *
+ * @public
+ * @type EndColumnFullScreen
+ */
+ EndColumnFullScreen: "EndColumnFullScreen",
+};
+
+/**
+ * The number of columns of ui5-flexible-collcolumn-layout
.
+ *
+ * @class
+ * @constructor
+ * @author SAP SE
+ * @alias sap.ui.webcomponents.fiori.types.FCLLayout
+ * @public
+ * @enum {string}
+ */
+class FCLLayout extends DataType {
+ static isValid(value) {
+ return !!FCLLayouts[value];
+ }
+}
+
+FCLLayout.generataTypeAcessors(FCLLayouts);
+
+export default FCLLayout;
diff --git a/packages/fiori/test/pages/FCL.html b/packages/fiori/test/pages/FCL.html
new file mode 100644
index 000000000000..01deca1ae08e
--- /dev/null
+++ b/packages/fiori/test/pages/FCL.html
@@ -0,0 +1,788 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
++ + + + + +++ + ++ + ++ +++ + +++ +Edit ++ + + + +++++ +Edit ++ + + + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod..." +
+