@vaadin/form-layout 24.7.0-rc1 → 24.8.0-alpha2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,22 +3,17 @@
3
3
  * Copyright (c) 2017 - 2025 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { isElementHidden } from '@vaadin/a11y-base/src/focus-utils.js';
7
- import { ResizeMixin } from '@vaadin/component-base/src/resize-mixin.js';
8
-
9
- function isValidCSSLength(value) {
10
- // Check if the value is a valid CSS length and not `inherit` or `normal`,
11
- // which are also valid values for `word-spacing`, see:
12
- // https://drafts.csswg.org/css-text-3/#word-spacing-property
13
- return CSS.supports('word-spacing', value) && !['inherit', 'normal'].includes(value);
14
- }
6
+ import { SlotStylesMixin } from '@vaadin/component-base/src/slot-styles-mixin.js';
7
+ import { AutoResponsiveLayout } from './layouts/auto-responsive-layout.js';
8
+ import { ResponsiveStepsLayout } from './layouts/responsive-steps-layout.js';
9
+ import { formLayoutSlotStyles } from './vaadin-form-layout-styles.js';
15
10
 
16
11
  /**
17
12
  * @polymerMixin
18
- * @mixes ResizeMixin
13
+ * @mixes SlotStylesMixin
19
14
  */
20
15
  export const FormLayoutMixin = (superClass) =>
21
- class extends ResizeMixin(superClass) {
16
+ class extends SlotStylesMixin(superClass) {
22
17
  static get properties() {
23
18
  return {
24
19
  /**
@@ -77,100 +72,169 @@ export const FormLayoutMixin = (superClass) =>
77
72
  { minWidth: '40em', columns: 2 },
78
73
  ];
79
74
  },
80
- observer: '_responsiveStepsChanged',
75
+ observer: '__responsiveStepsChanged',
76
+ sync: true,
77
+ },
78
+
79
+ /**
80
+ * Enables the auto responsive mode in which the component automatically creates and adjusts
81
+ * columns based on the container's width. Columns have a fixed width defined by `columnWidth`
82
+ * and their number increases up to the limit set by `maxColumns`. The component dynamically
83
+ * adjusts the number of columns as the container size changes. When this mode is enabled,
84
+ * the `responsiveSteps` are ignored.
85
+ *
86
+ * By default, each field is placed on a new row. To organize fields into rows, there are
87
+ * two options:
88
+ *
89
+ * 1. Use `<vaadin-form-row>` to explicitly group fields into rows.
90
+ *
91
+ * 2. Enable the `autoRows` property to automatically arrange fields in available columns,
92
+ * wrapping to a new row when necessary. `<br>` elements can be used to force a new row.
93
+ *
94
+ * @attr {boolean} auto-responsive
95
+ */
96
+ autoResponsive: {
97
+ type: Boolean,
81
98
  sync: true,
99
+ value: false,
100
+ reflectToAttribute: true,
82
101
  },
83
102
 
84
103
  /**
85
- * Current number of columns in the layout
86
- * @private
104
+ * When `autoResponsive` is enabled, defines the width of each column.
105
+ * The value must be defined in CSS length units, e.g., `100px` or `13em`.
106
+ * The default value is `13em`.
107
+ *
108
+ * @attr {string} column-width
87
109
  */
88
- _columnCount: {
110
+ columnWidth: {
111
+ type: String,
112
+ sync: true,
113
+ value: '13em',
114
+ },
115
+
116
+ /**
117
+ * When `autoResponsive` is enabled, defines the maximum number of columns
118
+ * that the layout can create. The layout will create columns up to this
119
+ * limit based on the available container width. The default value is `10`.
120
+ *
121
+ * @attr {number} max-columns
122
+ */
123
+ maxColumns: {
89
124
  type: Number,
90
125
  sync: true,
126
+ value: 10,
91
127
  },
92
128
 
93
129
  /**
94
- * Indicates that labels are on top
95
- * @private
130
+ * When enabled with `autoResponsive`, distributes fields across columns
131
+ * by placing each field in the next available column and wrapping to
132
+ * the next row when the current row is full. `<br>` elements can be
133
+ * used to force a new row.
134
+ *
135
+ * @attr {boolean} auto-rows
96
136
  */
97
- _labelsOnTop: {
137
+ autoRows: {
98
138
  type: Boolean,
99
139
  sync: true,
140
+ value: false,
141
+ reflectToAttribute: true,
142
+ },
143
+
144
+ /**
145
+ * When enabled with `autoResponsive`, `<vaadin-form-item>` prefers positioning
146
+ * labels beside the fields. If the layout is too narrow to fit a single column
147
+ * with side labels, they revert to their default position above the fields.
148
+ *
149
+ * To customize the label width and the gap between the label and the field,
150
+ * use the following CSS properties:
151
+ *
152
+ * - `--vaadin-form-layout-label-width`
153
+ * - `--vaadin-form-layout-label-spacing`
154
+ *
155
+ * @attr {boolean} labels-aside
156
+ */
157
+ labelsAside: {
158
+ type: Boolean,
159
+ sync: true,
160
+ value: false,
161
+ reflectToAttribute: true,
162
+ },
163
+
164
+ /**
165
+ * When `autoResponsive` is enabled, specifies whether the columns should expand
166
+ * in width to evenly fill any remaining space after the layout has created as
167
+ * many fixed-width (`columnWidth`) columns as possible within the `maxColumns`
168
+ * limit. The default value is `false`.
169
+ *
170
+ * @attr {boolean} expand-columns
171
+ */
172
+ expandColumns: {
173
+ type: Boolean,
174
+ sync: true,
175
+ value: false,
176
+ reflectToAttribute: true,
177
+ },
178
+
179
+ /**
180
+ * When `autoResponsive` is enabled, specifies whether fields should stretch
181
+ * to take up all available space within columns. This setting also applies
182
+ * to fields inside `<vaadin-form-item>` elements. The default value is `false`.
183
+ *
184
+ * @attr {boolean} expand-fields
185
+ */
186
+ expandFields: {
187
+ type: Boolean,
188
+ sync: true,
189
+ value: false,
190
+ reflectToAttribute: true,
100
191
  },
101
192
  };
102
193
  }
103
194
 
104
195
  static get observers() {
105
- return ['_invokeUpdateLayout(_columnCount, _labelsOnTop)'];
196
+ return [
197
+ '__autoResponsiveLayoutPropsChanged(columnWidth, maxColumns, autoRows, labelsAside, expandColumns, expandFields)',
198
+ '__autoResponsiveChanged(autoResponsive)',
199
+ ];
106
200
  }
107
201
 
108
- /** @protected */
109
- connectedCallback() {
110
- super.connectedCallback();
202
+ constructor() {
203
+ super();
111
204
 
112
- // Set up an observer to update layout when new children are added or removed.
113
- this.__childrenObserver = new MutationObserver(() => this._updateLayout());
114
- this.__childrenObserver.observe(this, { childList: true });
205
+ /** @type {import('./layouts/abstract-layout.js').AbstractLayout} */
206
+ this.__currentLayout;
115
207
 
116
- // Set up an observer to update layout when children's attributes change.
117
- this.__childrenAttributesObserver = new MutationObserver((mutations) => {
118
- if (mutations.some((mutation) => mutation.target.parentElement === this)) {
119
- this._updateLayout();
120
- }
121
- });
122
- this.__childrenAttributesObserver.observe(this, {
123
- subtree: true,
124
- attributes: true,
125
- attributeFilter: ['colspan', 'data-colspan', 'hidden'],
126
- });
208
+ this.__autoResponsiveLayout = new AutoResponsiveLayout(this);
209
+ this.__responsiveStepsLayout = new ResponsiveStepsLayout(this);
210
+ }
127
211
 
128
- requestAnimationFrame(() => this._selectResponsiveStep());
129
- requestAnimationFrame(() => this._updateLayout());
212
+ /** @protected */
213
+ connectedCallback() {
214
+ super.connectedCallback();
215
+ this.__currentLayout.connect();
130
216
  }
131
217
 
132
218
  /** @protected */
133
219
  disconnectedCallback() {
134
220
  super.disconnectedCallback();
221
+ this.__currentLayout.disconnect();
222
+ }
135
223
 
136
- this.__childrenObserver.disconnect();
137
- this.__childrenAttributesObserver.disconnect();
224
+ /** @override */
225
+ get slotStyles() {
226
+ return [`${formLayoutSlotStyles}`.replace('vaadin-form-layout', this.localName)];
138
227
  }
139
228
 
140
- /** @private */
141
- _naturalNumberOrOne(n) {
142
- if (typeof n === 'number' && n >= 1 && n < Infinity) {
143
- return Math.floor(n);
144
- }
145
- return 1;
229
+ /** @protected */
230
+ _updateLayout() {
231
+ this.__currentLayout.updateLayout();
146
232
  }
147
233
 
148
234
  /** @private */
149
- _responsiveStepsChanged(responsiveSteps, oldResponsiveSteps) {
235
+ __responsiveStepsChanged(responsiveSteps, oldResponsiveSteps) {
150
236
  try {
151
- if (!Array.isArray(responsiveSteps)) {
152
- throw new Error('Invalid "responsiveSteps" type, an Array is required.');
153
- }
154
-
155
- if (responsiveSteps.length < 1) {
156
- throw new Error('Invalid empty "responsiveSteps" array, at least one item is required.');
157
- }
158
-
159
- responsiveSteps.forEach((step) => {
160
- if (this._naturalNumberOrOne(step.columns) !== step.columns) {
161
- throw new Error(`Invalid 'columns' value of ${step.columns}, a natural number is required.`);
162
- }
163
-
164
- if (step.minWidth !== undefined && !isValidCSSLength(step.minWidth)) {
165
- throw new Error(`Invalid 'minWidth' value of ${step.minWidth}, a valid CSS length required.`);
166
- }
167
-
168
- if (step.labelsPosition !== undefined && ['aside', 'top'].indexOf(step.labelsPosition) === -1) {
169
- throw new Error(
170
- `Invalid 'labelsPosition' value of ${step.labelsPosition}, 'aside' or 'top' string is required.`,
171
- );
172
- }
173
- });
237
+ this.__responsiveStepsLayout.setProps({ responsiveSteps });
174
238
  } catch (e) {
175
239
  if (oldResponsiveSteps && oldResponsiveSteps !== responsiveSteps) {
176
240
  console.warn(`${e.message} Using previously set 'responsiveSteps' instead.`);
@@ -184,147 +248,33 @@ export const FormLayoutMixin = (superClass) =>
184
248
  ];
185
249
  }
186
250
  }
187
-
188
- this._selectResponsiveStep();
189
251
  }
190
252
 
191
253
  /** @private */
192
- _selectResponsiveStep() {
193
- // Iterate through responsiveSteps and choose the step
194
- let selectedStep;
195
- const tmpStyleProp = 'background-position';
196
- this.responsiveSteps.forEach((step) => {
197
- // Convert minWidth to px units for comparison
198
- this.$.layout.style.setProperty(tmpStyleProp, step.minWidth);
199
- const stepMinWidthPx = parseFloat(getComputedStyle(this.$.layout).getPropertyValue(tmpStyleProp));
200
-
201
- // Compare step min-width with the host width, select the passed step
202
- if (stepMinWidthPx <= this.offsetWidth) {
203
- selectedStep = step;
204
- }
254
+ // eslint-disable-next-line @typescript-eslint/max-params
255
+ __autoResponsiveLayoutPropsChanged(columnWidth, maxColumns, autoRows, labelsAside, expandColumns, expandFields) {
256
+ this.__autoResponsiveLayout.setProps({
257
+ columnWidth,
258
+ maxColumns,
259
+ autoRows,
260
+ labelsAside,
261
+ expandColumns,
262
+ expandFields,
205
263
  });
206
- this.$.layout.style.removeProperty(tmpStyleProp);
207
-
208
- // Sometimes converting units is not possible, e.g, when element is
209
- // not connected. Then the `selectedStep` stays `undefined`.
210
- if (selectedStep) {
211
- // Apply the chosen responsive step's properties
212
- this._columnCount = selectedStep.columns;
213
- this._labelsOnTop = selectedStep.labelsPosition === 'top';
214
- }
215
264
  }
216
265
 
217
266
  /** @private */
218
- _invokeUpdateLayout() {
219
- this._updateLayout();
220
- }
221
-
222
- /**
223
- * Update the layout.
224
- * @protected
225
- */
226
- _updateLayout() {
227
- // Do not update layout when invisible
228
- if (isElementHidden(this)) {
229
- return;
267
+ __autoResponsiveChanged(autoResponsive) {
268
+ if (this.__currentLayout) {
269
+ this.__currentLayout.disconnect();
230
270
  }
231
271
 
232
- /*
233
- The item width formula:
234
-
235
- itemWidth = colspan / columnCount * 100% - columnSpacing
236
-
237
- We have to subtract columnSpacing, because the column spacing space is taken
238
- by item margins of 1/2 * spacing on both sides
239
- */
240
-
241
- const style = getComputedStyle(this);
242
- const columnSpacing = style.getPropertyValue('--vaadin-form-layout-column-spacing');
243
-
244
- const direction = style.direction;
245
- const marginStartProp = `margin-${direction === 'ltr' ? 'left' : 'right'}`;
246
- const marginEndProp = `margin-${direction === 'ltr' ? 'right' : 'left'}`;
247
-
248
- const containerWidth = this.offsetWidth;
249
-
250
- let col = 0;
251
- Array.from(this.children)
252
- .filter((child) => child.localName === 'br' || getComputedStyle(child).display !== 'none')
253
- .forEach((child, index, children) => {
254
- if (child.localName === 'br') {
255
- // Reset column count on line break
256
- col = 0;
257
- return;
258
- }
259
-
260
- const attrColspan = child.getAttribute('colspan') || child.getAttribute('data-colspan');
261
- let colspan;
262
- colspan = this._naturalNumberOrOne(parseFloat(attrColspan));
263
-
264
- // Never span further than the number of columns
265
- colspan = Math.min(colspan, this._columnCount);
266
-
267
- const childRatio = colspan / this._columnCount;
268
- child.style.width = `calc(${childRatio * 100}% - ${1 - childRatio} * ${columnSpacing})`;
269
-
270
- if (col + colspan > this._columnCount) {
271
- // Too big to fit on this row, let's wrap it
272
- col = 0;
273
- }
274
-
275
- // At the start edge
276
- if (col === 0) {
277
- child.style.setProperty(marginStartProp, '0px');
278
- } else {
279
- child.style.removeProperty(marginStartProp);
280
- }
281
-
282
- const nextIndex = index + 1;
283
- const nextLineBreak = nextIndex < children.length && children[nextIndex].localName === 'br';
284
-
285
- // At the end edge
286
- if (col + colspan === this._columnCount) {
287
- child.style.setProperty(marginEndProp, '0px');
288
- } else if (nextLineBreak) {
289
- const colspanRatio = (this._columnCount - col - colspan) / this._columnCount;
290
- child.style.setProperty(
291
- marginEndProp,
292
- `calc(${colspanRatio * containerWidth}px + ${colspanRatio} * ${columnSpacing})`,
293
- );
294
- } else {
295
- child.style.removeProperty(marginEndProp);
296
- }
297
-
298
- // Move the column counter
299
- col = (col + colspan) % this._columnCount;
300
-
301
- if (child.localName === 'vaadin-form-item') {
302
- if (this._labelsOnTop) {
303
- if (child.getAttribute('label-position') !== 'top') {
304
- child.__useLayoutLabelPosition = true;
305
- child.setAttribute('label-position', 'top');
306
- }
307
- } else if (child.__useLayoutLabelPosition) {
308
- delete child.__useLayoutLabelPosition;
309
- child.removeAttribute('label-position');
310
- }
311
- }
312
- });
313
- }
314
-
315
- /**
316
- * @protected
317
- * @override
318
- */
319
- _onResize(contentRect) {
320
- if (contentRect.width === 0 && contentRect.height === 0) {
321
- this.$.layout.style.opacity = '0';
322
- return;
272
+ if (autoResponsive) {
273
+ this.__currentLayout = this.__autoResponsiveLayout;
274
+ } else {
275
+ this.__currentLayout = this.__responsiveStepsLayout;
323
276
  }
324
277
 
325
- this._selectResponsiveStep();
326
- this._updateLayout();
327
-
328
- this.$.layout.style.opacity = '';
278
+ this.__currentLayout.connect();
329
279
  }
330
280
  };
@@ -22,7 +22,7 @@ export const formLayoutStyles = css`
22
22
  display: none !important;
23
23
  }
24
24
 
25
- #layout {
25
+ :host(:not([auto-responsive])) #layout {
26
26
  display: flex;
27
27
 
28
28
  align-items: baseline; /* default \`stretch\` is not appropriate */
@@ -30,7 +30,7 @@ export const formLayoutStyles = css`
30
30
  flex-wrap: wrap; /* the items should wrap */
31
31
  }
32
32
 
33
- #layout ::slotted(*) {
33
+ :host(:not([auto-responsive])) #layout ::slotted(*) {
34
34
  /* Items should neither grow nor shrink. */
35
35
  flex-grow: 0;
36
36
  flex-shrink: 0;
@@ -43,19 +43,167 @@ export const formLayoutStyles = css`
43
43
  #layout ::slotted(br) {
44
44
  display: none;
45
45
  }
46
+
47
+ :host([auto-responsive]) {
48
+ --_column-width-labels-above: var(--_column-width);
49
+ --_column-width-labels-aside: calc(
50
+ var(--_column-width) + var(--vaadin-form-layout-label-width) + var(--vaadin-form-layout-label-spacing)
51
+ );
52
+
53
+ display: flex;
54
+ min-width: var(--_column-width-labels-above);
55
+ }
56
+
57
+ :host([auto-responsive]) #layout {
58
+ /* By default, labels should be displayed above the fields */
59
+ --_form-item-labels-above: initial; /* true */
60
+ --_form-item-labels-aside: ' '; /* false */
61
+
62
+ /* CSS grid related properties */
63
+ --_grid-column-gap: var(--vaadin-form-layout-column-spacing);
64
+ --_grid-column-width: var(--_column-width-labels-above);
65
+ --_grid-column-max-total-gap: calc((var(--_max-columns) - 1) * var(--_grid-column-gap));
66
+ --_grid-column-max-total-width: calc(var(--_max-columns) * var(--_column-width-labels-above));
67
+ --_grid-repeat: var(--_grid-column-width);
68
+
69
+ display: grid;
70
+ grid-template-columns: repeat(auto-fill, var(--_grid-repeat));
71
+
72
+ /*
73
+ Auto-columns can be created when an item's colspan exceeds the rendered column count.
74
+ By setting auto-columns to 0, we exclude these columns from --_grid-rendered-column-count,
75
+ which is then used to cap the colspan.
76
+ */
77
+ grid-auto-columns: 0;
78
+
79
+ justify-items: start;
80
+ gap: var(--vaadin-form-layout-row-spacing) var(--_grid-column-gap);
81
+
82
+ /*
83
+ To prevent the layout from exceeding the column limit defined by --_max-columns,
84
+ its width needs to be constrained:
85
+
86
+ 1. "width" is used instead of "max-width" because, together with the default "flex: 0 1 auto",
87
+ it allows the layout to shrink to its minimum width inside <vaadin-horizontal-layout>, which
88
+ wouldn't work otherwise.
89
+
90
+ 2. "width" is used instead of "flex-basis" to make the layout expand to the maximum
91
+ number of columns inside <vaadin-overlay>, which creates a new stacking context
92
+ without a predefined width.
93
+ */
94
+ width: calc(var(--_grid-column-max-total-width) + var(--_grid-column-max-total-gap));
95
+
96
+ /*
97
+ Firefox requires min-width on both :host and #layout to allow the layout
98
+ to shrink below the value specified in the CSS width property above.
99
+ */
100
+ min-width: inherit;
101
+ }
102
+
103
+ :host([auto-responsive]) #layout::before {
104
+ background-position-y: var(--_column-width-labels-aside);
105
+ }
106
+
107
+ :host([auto-responsive]) #layout ::slotted(*) {
108
+ /* Make form items inherit label position from the layout */
109
+ --_form-item-labels-above: inherit;
110
+ --_form-item-labels-aside: inherit;
111
+
112
+ /* By default, place each child on a new row */
113
+ grid-column: 1 / span min(var(--_grid-colspan, 1), var(--_grid-rendered-column-count));
114
+ }
115
+
116
+ :host([auto-responsive][auto-rows]) #layout ::slotted(*) {
117
+ grid-column-start: var(--_grid-colstart, auto);
118
+ }
119
+
120
+ :host([auto-responsive][labels-aside]) #layout {
121
+ --_grid-column-max-total-width: calc(var(--_max-columns) * var(--_column-width-labels-aside));
122
+ }
123
+
124
+ :host([auto-responsive][labels-aside]) #layout[fits-labels-aside] {
125
+ --_form-item-labels-above: ' '; /* false */
126
+ --_form-item-labels-aside: initial; /* true */
127
+ --_grid-column-width: var(--_column-width-labels-aside);
128
+ }
129
+
130
+ :host([auto-responsive][expand-columns]) #layout {
131
+ /*
132
+ The "min" value in minmax ensures that once "maxColumns" is reached, the grid stops adding
133
+ new columns and instead expands the existing ones evenly to fill the available space.
134
+
135
+ The "max" value in minmax allows CSS grid columns to grow and evenly distribute any space
136
+ that remains when there isn't room for an additional column and "maxColumns" hasn't been
137
+ reached yet.
138
+ */
139
+ --_grid-repeat: minmax(
140
+ max(var(--_grid-column-width), calc((100% - var(--_grid-column-max-total-gap)) / var(--_max-columns))),
141
+ 1fr
142
+ );
143
+
144
+ /* Allow the layout to take up full available width of the parent element. */
145
+ flex-grow: 1;
146
+ }
147
+ `;
148
+
149
+ export const formLayoutSlotStyles = css`
150
+ /* Using :where to ensure user styles always take precedence */
151
+ :where(
152
+ vaadin-form-layout[auto-responsive] > *,
153
+ vaadin-form-layout[auto-responsive] vaadin-form-row > *,
154
+ vaadin-form-layout[auto-responsive] vaadin-form-item > *
155
+ ) {
156
+ box-sizing: border-box;
157
+ max-width: 100%;
158
+ }
159
+
160
+ :where(
161
+ vaadin-form-layout[auto-responsive][expand-fields] > *,
162
+ vaadin-form-layout[auto-responsive][expand-fields] vaadin-form-row > *,
163
+ vaadin-form-layout[auto-responsive][expand-fields] vaadin-form-item > *
164
+ ) {
165
+ min-width: 100%;
166
+ }
167
+ `;
168
+
169
+ export const formRowStyles = css`
170
+ :host {
171
+ display: contents;
172
+ }
173
+
174
+ :host([hidden]) {
175
+ display: none !important;
176
+ }
177
+
178
+ ::slotted(*) {
179
+ /* Make form items inherit label position from the layout */
180
+ --_form-item-labels-above: inherit;
181
+ --_form-item-labels-aside: inherit;
182
+
183
+ grid-column: auto / span min(var(--_grid-colspan, 1), var(--_grid-rendered-column-count));
184
+ }
185
+
186
+ ::slotted(:first-child) {
187
+ grid-column-start: 1;
188
+ }
46
189
  `;
47
190
 
48
191
  export const formItemStyles = css`
49
192
  :host {
193
+ /* By default, when auto-responsive mode is disabled, labels should be displayed beside the fields. */
194
+ --_form-item-labels-above: ' '; /* false */
195
+ --_form-item-labels-aside: initial; /* true */
196
+
50
197
  display: inline-flex;
51
- flex-direction: row;
52
- align-items: baseline;
198
+ align-items: var(--_form-item-labels-aside, baseline);
199
+ flex-flow: var(--_form-item-labels-above, column) nowrap;
200
+ justify-self: stretch;
53
201
  margin: calc(0.5 * var(--vaadin-form-item-row-spacing, var(--vaadin-form-layout-row-spacing, 1em))) 0;
54
202
  }
55
203
 
56
204
  :host([label-position='top']) {
57
- flex-direction: column;
58
- align-items: stretch;
205
+ --_form-item-labels-above: initial; /* true */
206
+ --_form-item-labels-aside: ' '; /* false */
59
207
  }
60
208
 
61
209
  :host([hidden]) {
@@ -63,14 +211,13 @@ export const formItemStyles = css`
63
211
  }
64
212
 
65
213
  #label {
66
- width: var(--vaadin-form-item-label-width, var(--vaadin-form-layout-label-width, 8em));
214
+ width: var(
215
+ --_form-item-labels-aside,
216
+ var(--vaadin-form-item-label-width, var(--vaadin-form-layout-label-width, 8em))
217
+ );
67
218
  flex: 0 0 auto;
68
219
  }
69
220
 
70
- :host([label-position='top']) #label {
71
- width: auto;
72
- }
73
-
74
221
  #spacing {
75
222
  width: var(--vaadin-form-item-label-spacing, var(--vaadin-form-layout-label-spacing, 1em));
76
223
  flex: 0 0 auto;