@@ -43,12 +53,12 @@ function groupedItemsLayout(this: Form) {
aria-labelledby={groupItemInfo.accessibleNameRef}
aria-label={groupItemInfo.accessibleName}
>
- { groupItem.headerText &&
+ {groupItem.headerText &&
}
- { this.accessibleMode === "Edit" ?
+ {this.accessibleMode === "Edit" ?
@@ -64,29 +74,37 @@ function groupedItemsLayout(this: Form) {
}
function standaloneItemsLayout(this: Form) {
- return (
- this.accessibleMode === "Edit" ?
-
- { standaloneItemsLayoutContent.call(this) }
+ const column =
;
+
+ return
{column}
;
}
function standaloneItemsLayoutContent(this: Form) {
return this.itemsInfo.map(itemInfo => {
const item = itemInfo.item;
return (
-
);
});
}
diff --git a/packages/main/src/form-utils/FormUtils.ts b/packages/main/src/form-utils/FormUtils.ts
new file mode 100644
index 000000000000..6c5d69b13a50
--- /dev/null
+++ b/packages/main/src/form-utils/FormUtils.ts
@@ -0,0 +1,71 @@
+import type { IFormItem } from "../Form.js";
+
+const breakpoints = ["S", "M", "L", "XL"] as const;
+type Breakpoint = typeof breakpoints[number];
+const MAX_FORM_ITEM_CELLS = 12;
+const DEFAULT_FORM_ITEM_LAYOUT = "4fr 8fr 0fr";
+const DEFAULT_FORM_ITEM_LAYOUT_S = "1fr";
+
+function getFormItemLayoutValue(breakpoint: Breakpoint, labelSpan: number | undefined = 0, emptySpan: number | undefined = 0): string {
+ if (isValidFormItemLayout(labelSpan, emptySpan)) {
+ return labelSpan === MAX_FORM_ITEM_CELLS ? `1fr` : `${labelSpan}fr ${MAX_FORM_ITEM_CELLS - (labelSpan + emptySpan)}fr ${emptySpan}fr`;
+ }
+
+ // eslint-disable-next-line
+ console.warn(`Form :: invalid usage of emptySpan and/or labelSpan in ${breakpoint} size. The labelSpan must be <=12 and when emptySpace is used - their combined values must not exceed 11.`);
+ return breakpoint === "S" ? DEFAULT_FORM_ITEM_LAYOUT_S : DEFAULT_FORM_ITEM_LAYOUT;
+}
+
+function isValidFormItemLayout(labelSpan: number, emptySpan: number) {
+ return emptySpan === 0 ? labelSpan <= MAX_FORM_ITEM_CELLS : labelSpan + emptySpan <= MAX_FORM_ITEM_CELLS - 1;
+}
+
+function getGroupsColSpan(cols: number, groups: number, index: number, group: IFormItem, breakpoint: Breakpoint): number {
+ // Case 0: column span is set from outside.
+ if (group.columnSpan) {
+ return group.columnSpan;
+ }
+
+ const colSpanForBreakpoint = group.colSpan?.split(" ").find((bp: string) => bp.startsWith(breakpoint));
+
+ if (colSpanForBreakpoint) {
+ const value = parseInt(colSpanForBreakpoint.slice(breakpoint.length));
+
+ return value;
+ }
+
+ // CASE 1: The number of available columns match the number of groups, or only 1 column is available - each group takes 1 column.
+ // For example: 1 column - 1 group, 2 columns - 2 groups, 3 columns - 3 groups, 4columns - 4 groups
+ if (cols === 1 || cols <= groups) {
+ return 1;
+ }
+
+ // CASE 2: The number of available columns IS multiple of the number of groups.
+ // For example: 2 column - 1 group, 3 columns - 1 groups, 4 columns - 1 group, 4 columns - 2 groups
+ if (cols % groups === 0) {
+ return cols / groups;
+ }
+
+ // CASE 3: The number of available columns IS NOT multiple of the number of groups.
+ const MIN_COL_SPAN = 1;
+ const delta = cols - groups;
+
+ // 7 cols & 4 groups => 2, 2, 2, 1
+ if (delta <= groups) {
+ return index < delta ? MIN_COL_SPAN + 1 : MIN_COL_SPAN;
+ }
+
+ // 7 cols & 3 groups => 3, 2, 2
+ return index === 0 ? MIN_COL_SPAN + (delta - groups) + 1 : MIN_COL_SPAN + 1;
+}
+
+export {
+ getFormItemLayoutValue,
+ getGroupsColSpan,
+ DEFAULT_FORM_ITEM_LAYOUT,
+ DEFAULT_FORM_ITEM_LAYOUT_S,
+};
+
+export type {
+ Breakpoint,
+};
diff --git a/packages/main/src/themes/Form.css b/packages/main/src/themes/Form.css
index d8e987cec5fb..4824f1c4ed84 100644
--- a/packages/main/src/themes/Form.css
+++ b/packages/main/src/themes/Form.css
@@ -30,7 +30,7 @@
}
.ui5-form-group-layout {
- display: grid;
+ display: block;
column-gap: 1rem;
}
@@ -51,5 +51,7 @@
}
dl {
- all: unset;
+ padding: 0;
+ margin: 0;
+ border: 0 transparent;
}
\ No newline at end of file
diff --git a/packages/main/src/themes/FormItem.css b/packages/main/src/themes/FormItem.css
index ab65c77c8736..f1ba4e9970e5 100644
--- a/packages/main/src/themes/FormItem.css
+++ b/packages/main/src/themes/FormItem.css
@@ -3,28 +3,8 @@
width: 100%;
}
-:host([column-span="1"]) {
- grid-column: span 1;
-}
-
-:host([column-span="2"]) {
- grid-column: span 2;
-}
-
-:host([column-span="3"]) {
- grid-column: span 3;
-}
-
-:host([column-span="4"]) {
- grid-column: span 4;
-}
-
-:host([column-span="5"]) {
- grid-column: span 5;
-}
-
-:host([column-span="6"]) {
- grid-column: span 6;
+:host {
+ break-inside: avoid;
}
.ui5-form-item-root {
@@ -68,34 +48,8 @@
width: 100%;
}
-@container (max-width: 600px) {
- :host {
- order: var(--ui5-form-item-order-S, unset);
- }
-}
-
-/* M - 1 column by default, up to 2 columns */
-@container (width > 600px) and (width <= 1024px) {
- :host {
- order: var(--ui5-form-item-order-M, unset);
- }
-
-}
-
-/* L - 2 columns by default, up to 3 columns */
-@container (width > 1024px) and (width <= 1440px) {
- :host {
- order: var(--ui5-form-item-order-L, unset);
- }
-}
-
-/* XL - 3 columns by default, up to 6 */
-@container (min-width: 1441px) {
- :host {
- order: var(--ui5-form-item-order-Xl, unset);
- }
-}
-
dd {
- all: unset;
+ padding: 0;
+ margin: 0;
+ border: 0 transparent;
}
\ No newline at end of file
diff --git a/packages/main/src/themes/FormItemSpan.css b/packages/main/src/themes/FormItemSpan.css
index 8d01d50d09ec..6e79c531fe6a 100644
--- a/packages/main/src/themes/FormItemSpan.css
+++ b/packages/main/src/themes/FormItemSpan.css
@@ -17,8 +17,8 @@
--ui5-form-item-layout: var(--ui5-form-item-layout-S);
}
- :host([label-span-s="12"]) .ui5-form-item,
- :host([label-span-s="12"]) .ui5-form-group {
+ :host(:is([label-span~="S12"], :not([label-span*="S"]))) .ui5-form-item,
+ :host(:is([label-span~="S12"], :not([label-span*="S"]))) .ui5-form-group {
--ui5-form-item-label-justify: var(--ui5-form-item-label-justify-internal);
--ui5-form-item-label-padding: var(--ui5-form-item-label-padding-internal);
}
@@ -30,8 +30,8 @@
--ui5-form-item-layout: var(--ui5-form-item-layout-M);
}
- :host([label-span-m="12"]) .ui5-form-item,
- :host([label-span-m="12"]) .ui5-form-group {
+ :host([label-span~="M12"]) .ui5-form-item,
+ :host([label-span~="M12"]) .ui5-form-group {
--ui5-form-item-label-justify: var(--ui5-form-item-label-justify-internal);
--ui5-form-item-label-padding: var(--ui5-form-item-label-padding-internal);
}
@@ -43,8 +43,8 @@
--ui5-form-item-layout: var(--ui5-form-item-layout-L);
}
- :host([label-span-l="12"]) .ui5-form-item,
- :host([label-span-l="12"]) .ui5-form-group {
+ :host([label-span~="L12"]) .ui5-form-item,
+ :host([label-span~="L12"]) .ui5-form-group {
--ui5-form-item-label-justify: var(--ui5-form-item-label-justify-internal);
--ui5-form-item-label-padding: var(--ui5-form-item-label-padding-internal);
}
@@ -56,9 +56,9 @@
--ui5-form-item-layout: var(--ui5-form-item-layout-XL);
}
- :host([label-span-xl="12"]) .ui5-form-item,
- :host([label-span-xl="12"]) .ui5-form-group {
+ :host([label-span~="XL12"]) .ui5-form-item,
+ :host([label-span~="XL12"]) .ui5-form-group {
--ui5-form-item-label-justify: var(--ui5-form-item-label-justify-internal);
--ui5-form-item-label-padding: var(--ui5-form-item-label-padding-internal);
}
-}
+}
\ No newline at end of file
diff --git a/packages/main/src/themes/FormLayout.css b/packages/main/src/themes/FormLayout.css
index 9280b7b969fa..7db96c63c0c7 100644
--- a/packages/main/src/themes/FormLayout.css
+++ b/packages/main/src/themes/FormLayout.css
@@ -1,43 +1,46 @@
-/*
-* The Form layout is divided into one or more columns.
+/*
+* The Form layout is divided into one or more columns.
* XL - max. 6 columns, L - max. 3 columns, M - max. 2 columns and S - 1 column.
*/
-/*
+/*
* S max-width: 600px - container padding 24px
*/
/* S - 1 column */
@container (max-width: 599px) {
.ui5-form-layout {
- grid-template-columns: 1fr;
+ grid-template-columns: repeat(var(--ui5-form-columns-s), 1fr);
}
::slotted(*) {
justify-self: start;
}
- ::slotted(:nth-child(2n)){
+
+ ::slotted(:nth-child(2n)) {
margin-bottom: 0.5rem;
}
+
+ .ui5-form-column {
+ grid-column: span var(--ui5-form-column-span-s, 1);
+ }
+
+ .ui5-form-group-layout {
+ column-count: var(--ui5-form-column-span-s, 1)
+ }
}
/* M - 1 column by default, up to 2 columns */
@container (min-width: 600px) and (max-width: 1023px) {
.ui5-form-layout {
- grid-template-columns: 1fr;
- }
- :host([columns-m="1"]) .ui5-form-layout {
- grid-template-columns: 1fr;
- }
- :host([columns-m="2"]) .ui5-form-layout {
- grid-template-columns: repeat(2, 1fr);
+ grid-template-columns: repeat(var(--ui5-form-columns-m), 1fr);
}
- .ui5-form-column-spanM-2 {
- grid-column: span 2;
+ .ui5-form-column {
+ grid-column: span var(--ui5-form-column-span-m, 1);
}
- .ui5-form-column-spanM-2 .ui5-form-group-layout {
- grid-template-columns: repeat(2, 1fr);
+ .ui5-form-group-layout {
+ column-count: var(--ui5-form-column-span-m, 1)
}
}
@@ -45,115 +48,29 @@
@container (min-width: 1024px) and (max-width: 1439px) {
.ui5-form-layout {
- grid-template-columns: repeat(2, 1fr);
- }
- .ui5-form-column {
- grid-template-columns: 1fr;
+ grid-template-columns: repeat(var(--ui5-form-columns-l), 1fr);
}
- :host([columns-l="1"]) .ui5-form-layout {
- grid-template-columns: 1fr;
- }
- :host([columns-l="2"]) .ui5-form-layout {
- grid-template-columns: repeat(2, 1fr);
- }
- :host([columns-l="3"]) .ui5-form-layout {
- grid-template-columns: repeat(3, 1fr);
- }
-
- .ui5-form-column-spanL-2 {
- grid-column: span 2;
- }
- .ui5-form-column-spanL-2 .ui5-form-group-layout {
- grid-template-columns: repeat(2, 1fr);
+ .ui5-form-column {
+ grid-column: span var(--ui5-form-column-span-l, 1);
}
- .ui5-form-column-spanL-3 {
- grid-column: span 3;
- }
- .ui5-form-column-spanL-3 .ui5-form-group-layout {
- grid-template-columns: repeat(3, 1fr);
+ .ui5-form-group-layout {
+ column-count: var(--ui5-form-column-span-l, 1)
}
}
/* XL - 3 columns by default, up to 6 */
@container (min-width: 1440px) {
.ui5-form-layout {
- grid-template-columns: repeat(3, 1fr);
- }
-
- :host([columns-xl="1"]) .ui5-form-layout {
- grid-template-columns: 1fr;
- }
- :host([columns-xl="2"]) .ui5-form-layout {
- grid-template-columns: repeat(2, 1fr);
- }
- :host([columns-xl="3"]) .ui5-form-layout {
- grid-template-columns: repeat(3, 1fr);
- }
- :host([columns-xl="4"]) .ui5-form-layout {
- grid-template-columns: repeat(4, 1fr);
- }
- :host([columns-xl="5"]) .ui5-form-layout {
- grid-template-columns: repeat(5, 1fr);
- }
- :host([columns-xl="6"]) .ui5-form-layout {
- grid-template-columns: repeat(6, 1fr);
+ grid-template-columns: repeat(var(--ui5-form-columns-xl), 1fr);
}
- .ui5-form-column-spanXL-2 {
- grid-column: span 2;
- }
- .ui5-form-column-spanXL-2 .ui5-form-group-layout {
- grid-template-columns: repeat(2, 1fr);
- }
-
- .ui5-form-column-spanXL-3 {
- grid-column: span 3;
- }
- .ui5-form-column-spanXL-3 .ui5-form-group-layout {
- grid-template-columns: repeat(3, 1fr);
- }
-
- .ui5-form-column-spanXL-4 {
- grid-column: span 4;
- }
- .ui5-form-column-spanXL-4 .ui5-form-group-layout {
- grid-template-columns: repeat(4, 1fr);
-
- }
-
- .ui5-form-column-spanXL-5 {
- grid-column: span 5;
- }
- .ui5-form-column-spanXL-5 .ui5-form-group-layout {
- grid-template-columns: repeat(5, 1fr);
-
+ .ui5-form-column {
+ grid-column: span var(--ui5-form-column-span-xl, 1);
}
- .ui5-form-column-spanXL-6 {
- grid-column: span 6;
- }
- .ui5-form-column-spanXL-6 .ui5-form-group-layout {
- grid-template-columns: repeat(6, 1fr);
+ .ui5-form-group-layout {
+ column-count: var(--ui5-form-column-span-xl, 1)
}
-}
-
-.ui5-form-item-span-2 {
- grid-column: span 2;
-}
-
-.ui5-form-item-span-3 {
- grid-column: span 3;
-}
-
-.ui5-form-item-span-4 {
- grid-column: span 4;
-}
-
-.ui5-form-item-span-5 {
- grid-column: span 5;
-}
-.ui5-form-item-span-6 {
- grid-column: span 6;
-}
+}
\ No newline at end of file
diff --git a/packages/main/test/pages/form/FormComparison.html b/packages/main/test/pages/form/FormComparison.html
new file mode 100644
index 000000000000..36512dcece3c
--- /dev/null
+++ b/packages/main/test/pages/form/FormComparison.html
@@ -0,0 +1,522 @@
+
+
+
+
+
+
+
Form Comparison - UI5 Web Components vs OpenUI5
+
+
+
+
+
+
+
+
+
+
+
+
Form Comparison: UI5 Web Components vs OpenUI5
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/main/test/pages/form/FormComparison2.html b/packages/main/test/pages/form/FormComparison2.html
new file mode 100644
index 000000000000..180df3823f0c
--- /dev/null
+++ b/packages/main/test/pages/form/FormComparison2.html
@@ -0,0 +1,572 @@
+
+
+
+
+
+
Form Comparison: single group vs flat items
+
+
+
+
+
+
+
+
+
+
+
+
+
+ layout="S1 M1 L2 XL3" (default) — label-span default
+
+
+
+ single ui5-form-group
+
+
+
+ Name:
+ Red Point Stores
+
+
+ ZIP Code/City:
+ 411 Maintown
+
+
+ Street:
+ Main St 1618
+
+
+ Country:
+ Germany
+
+
+ WebSite:
+ sap.com
+
+
+ Delivery address:
+ Newtown
+
+
+
+
+
+
+ flat ui5-form-item (no group)
+
+
+ Name:
+ Red Point Stores
+
+
+ ZIP Code/City:
+ 411 Maintown
+
+
+ Street:
+ Main St 1618
+
+
+ Country:
+ Germany
+
+
+ WebSite:
+ sap.com
+
+
+ Delivery address:
+ Newtown
+
+
+
+
+
+
+
+
+
+ layout="S1 M2 L3 XL4" — label-span default
+
+
+
+ single ui5-form-group
+
+
+
+ Name:
+ Red Point Stores
+
+
+ ZIP Code/City:
+ 411 Maintown
+
+
+ Street:
+ Main St 1618
+
+
+ Country:
+ Germany
+
+
+ WebSite:
+ sap.com
+
+
+ Delivery address:
+ Newtown
+
+
+
+
+
+
+ flat ui5-form-item (no group)
+
+
+ Name:
+ Red Point Stores
+
+
+ ZIP Code/City:
+ 411 Maintown
+
+
+ Street:
+ Main St 1618
+
+
+ Country:
+ Germany
+
+
+ WebSite:
+ sap.com
+
+
+ Delivery address:
+ Newtown
+
+
+
+
+
+
+
+
+
+ layout="S1 M2 L3 XL6" — label-span default
+
+
+
+ single ui5-form-group
+
+
+
+ Name:
+ Red Point Stores
+
+
+ ZIP Code/City:
+ 411 Maintown
+
+
+ Street:
+ Main St 1618
+
+
+ Country:
+ Germany
+
+
+ WebSite:
+ sap.com
+
+
+ Twitter:
+ @sap
+
+
+ Email:
+ john.smith@sap.com
+
+
+ Tel:
+ +49 6227 747474
+
+
+
+
+
+
+ flat ui5-form-item (no group)
+
+
+ Name:
+ Red Point Stores
+
+
+ ZIP Code/City:
+ 411 Maintown
+
+
+ Street:
+ Main St 1618
+
+
+ Country:
+ Germany
+
+
+ WebSite:
+ sap.com
+
+
+ Twitter:
+ @sap
+
+
+ Email:
+ john.smith@sap.com
+
+
+ Tel:
+ +49 6227 747474
+
+
+
+
+
+
+
+
+
+ layout="S1 M2 L3 XL4" — label-span="S12 M12 L12 XL12" (labels on top)
+
+
+
+ single ui5-form-group
+
+
+
+ Name:
+ Red Point Stores
+
+
+ ZIP Code/City:
+ 411 Maintown
+
+
+ Street:
+ Main St 1618
+
+
+ Country:
+ Germany
+
+
+ WebSite:
+ sap.com
+
+
+ Delivery address:
+ Newtown
+
+
+
+
+
+
+ flat ui5-form-item (no group)
+
+
+ Name:
+ Red Point Stores
+
+
+ ZIP Code/City:
+ 411 Maintown
+
+
+ Street:
+ Main St 1618
+
+
+ Country:
+ Germany
+
+
+ WebSite:
+ sap.com
+
+
+ Delivery address:
+ Newtown
+
+
+
+
+
+
+
+
+
+ layout="S1 M2 L3 XL4" — accessible-mode="Edit"
+
+
+
+ single ui5-form-group
+
+
+
+ Name:
+
+
+
+ ZIP Code/City:
+
+
+
+
+ Street:
+
+
+
+
+ Country:
+
+ Australia
+ Germany
+ England
+
+
+
+ WebSite:
+
+
+
+ Delivery address:
+
+
+
+
+
+
+
+ flat ui5-form-item (no group)
+
+
+ Name:
+
+
+
+ ZIP Code/City:
+
+
+
+
+ Street:
+
+
+
+
+ Country:
+
+ Australia
+ Germany
+ England
+
+
+
+ WebSite:
+
+
+
+ Delivery address:
+
+
+
+
+
+
+
+
+
+
+ layout="S1 M2 L3 XL4" — item-spacing="Large"
+
+
+
+ single ui5-form-group
+
+
+
+ Name:
+ Red Point Stores
+
+
+ ZIP Code/City:
+ 411 Maintown
+
+
+ Street:
+ Main St 1618
+
+
+ Country:
+ Germany
+
+
+ WebSite:
+ sap.com
+
+
+ Delivery address:
+ Newtown
+
+
+
+
+
+
+ flat ui5-form-item (no group)
+
+
+ Name:
+ Red Point Stores
+
+
+ ZIP Code/City:
+ 411 Maintown
+
+
+ Street:
+ Main St 1618
+
+
+ Country:
+ Germany
+
+
+ WebSite:
+ sap.com
+
+
+ Delivery address:
+ Newtown
+
+
+
+
+
+
+
+
+
+ layout="S1 M2 L3 XL4" — empty-span="L3 XL3"
+
+
+
+ single ui5-form-group
+
+
+
+ Name:
+ Red Point Stores
+
+
+ ZIP Code/City:
+ 411 Maintown
+
+
+ Street:
+ Main St 1618
+
+
+ Country:
+ Germany
+
+
+ WebSite:
+ sap.com
+
+
+ Delivery address:
+ Newtown
+
+
+
+
+
+
+ flat ui5-form-item (no group)
+
+
+ Name:
+ Red Point Stores
+
+
+ ZIP Code/City:
+ 411 Maintown
+
+
+ Street:
+ Main St 1618
+
+
+ Country:
+ Germany
+
+
+ WebSite:
+ sap.com
+
+
+ Delivery address:
+ Newtown
+
+
+
+
+
+
+
+
+
+
+