Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor!: use CSS gap for row and column spacing #8638

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion packages/form-layout/src/vaadin-form-item-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,13 @@ export const FormItemMixin = (superClass) =>
const spacing = getComputedStyle(this).getPropertyValue('--vaadin-form-item-row-spacing');
if (spacing !== '' && parseInt(spacing) !== 0) {
console.warn(
'`--vaadin-form-item-row-spacing` is deprecated since 24.7. Use `--vaadin-form-layout-row-spacing` on <vaadin-form-layout> instead.',
`
--vaadin-form-item-row-spacing is deprecated since 24.7. Instead you should now:
1. Use --vaadin-form-layout-row-spacing on the <vaadin-form-layout> component to control the gap between rows
2. Use standard CSS margin on <vaadin-form-layout> to control the spacing around the form layout itself
`
.trim()
.replace(/\s{2,}/gu, '\n'),
);
itemRowSpacingDeprecationNotified = true;
}
Expand Down
23 changes: 3 additions & 20 deletions packages/form-layout/src/vaadin-form-layout-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,10 +282,6 @@ export const FormLayoutMixin = (superClass) =>
const style = getComputedStyle(this);
const columnSpacing = style.getPropertyValue('--vaadin-form-layout-column-spacing');

const direction = style.direction;
const marginStartProp = `margin-${direction === 'ltr' ? 'left' : 'right'}`;
const marginEndProp = `margin-${direction === 'ltr' ? 'right' : 'left'}`;

const containerWidth = this.offsetWidth;

let col = 0;
Expand Down Expand Up @@ -313,27 +309,14 @@ export const FormLayoutMixin = (superClass) =>
col = 0;
}

// At the start edge
if (col === 0) {
child.style.setProperty(marginStartProp, '0px');
} else {
child.style.removeProperty(marginStartProp);
}

const nextIndex = index + 1;
const nextLineBreak = nextIndex < children.length && children[nextIndex].localName === 'br';

// At the end edge
if (col + colspan === this._columnCount) {
child.style.setProperty(marginEndProp, '0px');
} else if (nextLineBreak) {
if (nextLineBreak) {
const colspanRatio = (this._columnCount - col - colspan) / this._columnCount;
child.style.setProperty(
marginEndProp,
`calc(${colspanRatio * containerWidth}px + ${colspanRatio} * ${columnSpacing})`,
);
child.style.marginInlineEnd = `calc(${colspanRatio * containerWidth}px + ${colspanRatio} * ${columnSpacing})`;
} else {
child.style.removeProperty(marginEndProp);
child.style.marginInlineEnd = '';
}

// Move the column counter
Expand Down
19 changes: 11 additions & 8 deletions packages/form-layout/src/vaadin-form-layout-styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const formLayoutStyles = css`
/* CSS API for host */
--vaadin-form-item-label-width: 8em;
--vaadin-form-item-label-spacing: 1em;
--vaadin-form-layout-row-spacing: 1em;
--vaadin-form-layout-row-spacing: 0;
--vaadin-form-layout-column-spacing: 2em; /* (default) */
align-self: stretch;
}
Expand All @@ -23,20 +23,15 @@ export const formLayoutStyles = css`

#layout {
display: flex;

align-items: baseline; /* default \`stretch\` is not appropriate */

flex-wrap: wrap; /* the items should wrap */
gap: var(--vaadin-form-layout-row-spacing) var(--vaadin-form-layout-column-spacing);
}

#layout ::slotted(*) {
/* Items should neither grow nor shrink. */
flex-grow: 0;
flex-shrink: 0;

/* Margins make spacing between the columns */
margin-left: calc(0.5 * var(--vaadin-form-layout-column-spacing));
margin-right: calc(0.5 * var(--vaadin-form-layout-column-spacing));
}

#layout ::slotted(br) {
Expand All @@ -49,7 +44,15 @@ export const formItemStyles = css`
display: inline-flex;
flex-direction: row;
align-items: baseline;
margin: calc(0.5 * var(--vaadin-form-item-row-spacing, var(--vaadin-form-layout-row-spacing, 1em))) 0;

/*
WARNING: --vaadin-form-item-row-spacing is deprecated since 24.7. Instead you should now:
1. Use --vaadin-form-layout-row-spacing on the <vaadin-form-layout> component to control the gap between rows.
2. Use standard CSS margin on <vaadin-form-layout> to control the spacing around the form layout itself.
*/
--_has-layout-row-spacing: clamp(0, var(--vaadin-form-layout-row-spacing), 1);
--_item-row-spacing: calc((1 - var(--_has-layout-row-spacing)) * var(--vaadin-form-item-row-spacing, 1em));
margin: calc(var(--_item-row-spacing) / 2) 0;
}

:host([label-position='top']) {
Expand Down
60 changes: 29 additions & 31 deletions packages/form-layout/test/form-layout.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,31 +94,34 @@ describe('form layout', () => {

it('should not have default row-spacing', () => {
expect(getComputedStyle(item).getPropertyValue('--vaadin-form-layout-row-spacing').trim()).to.equal('0');
expect(parseFloat(getComputedStyle(item).marginTop)).to.equal(0);
expect(parseFloat(getComputedStyle(item).marginBottom)).to.equal(0);
expect(getComputedStyle(item).marginTop).to.equal('0px');
expect(getComputedStyle(item).marginBottom).to.equal('0px');
});

it('should apply form layout row spacing', () => {
const spacing = 8;
item.style.setProperty('--vaadin-form-layout-row-spacing', `${spacing}px`);
expect(parseFloat(getComputedStyle(item).marginTop)).to.equal(spacing / 2);
expect(parseFloat(getComputedStyle(item).marginBottom)).to.equal(spacing / 2);
layout.style.setProperty('--vaadin-form-layout-row-spacing', '8px');
expect(getComputedStyle(layout.$.layout).rowGap).to.equal('8px');
});

it('should apply form item row spacing', () => {
it('should apply form item row', () => {
vursen marked this conversation as resolved.
Show resolved Hide resolved
const spacing = 8;
item.style.setProperty('--vaadin-form-item-row-spacing', `${spacing}px`);
expect(parseFloat(getComputedStyle(item).marginTop)).to.equal(spacing / 2);
expect(parseFloat(getComputedStyle(item).marginBottom)).to.equal(spacing / 2);
expect(getComputedStyle(item).marginTop).to.equal(`${spacing / 2}px`);
expect(getComputedStyle(item).marginBottom).to.equal(`${spacing / 2}px`);
});

it('should not apply form item row spacing when form layout spacing is non-zero', () => {
layout.style.setProperty('--vaadin-form-layout-row-spacing', '8px');
item.style.setProperty('--vaadin-form-item-row-spacing', `8px`);
expect(getComputedStyle(item).marginTop).to.equal('0px');
expect(getComputedStyle(item).marginBottom).to.equal('0px');
});

it('should apply default column-spacing', async () => {
// Override to not depend on the theme changes
layout.style.setProperty('--lumo-space-l', '2rem');
layout.style.setProperty('--lumo-space-l', '8px');
await nextResize(layout);
expect(getParsedWidth(layout.firstElementChild).spacing).to.equal('1rem');
expect(getComputedStyle(layout.firstElementChild).getPropertyValue('margin-left')).to.equal('0px'); // Zero because it's first
expect(getComputedStyle(layout.firstElementChild).getPropertyValue('margin-right')).to.equal('16px'); // 0.5 * 2rem in px
expect(getComputedStyle(layout.$.layout).columnGap).to.equal('8px');
});
});

Expand Down Expand Up @@ -531,29 +534,24 @@ describe('form layout', () => {

newFormItem.hidden = false;
await nextRender(container);
const unhiddenItemWidth = newFormItem.getBoundingClientRect().width;
expect(unhiddenItemWidth).to.equal(itemWidth);
expect(newFormItem.getBoundingClientRect().width).to.equal(itemWidth);
});

it('should update layout after a new item is added', async () => {
const newFormItem = document.createElement('vaadin-form-item');
newFormItem.innerHTML = '<label slot="label">Field</label><input />';
layout.insertBefore(newFormItem, items[0]);
await nextRender(container);
expect(getComputedStyle(newFormItem).marginLeft).to.be.equal('0px');
it('should update margin-inline-end after adding <br>', async () => {
const br = document.createElement('br');
layout.insertBefore(br, items[1]);
await nextRender(layout);
expect(getComputedStyle(items[0]).marginInlineEnd).to.not.equal('0px');
});

it('should update layout after an item is removed', async () => {
const newFormItem = document.createElement('vaadin-form-item');
newFormItem.innerHTML = '<label slot="label">Field</label><input />';
layout.insertBefore(newFormItem, items[0]);
await nextRender(container);
it('should update margin-inline-end after removing <br>', async () => {
const br = document.createElement('br');
layout.insertBefore(br, items[1]);
await nextRender(layout);

expect(getComputedStyle(items[0]).marginLeft).to.not.be.equal('0px');

newFormItem.remove();
await nextRender(container);
expect(getComputedStyle(items[0]).marginLeft).to.be.equal('0px');
br.remove();
await nextRender(layout);
expect(getComputedStyle(items[0]).marginInlineEnd).to.equal('0px');
});

it('should not update layout when setting hidden to true', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ registerStyles(
css`
:host {
--vaadin-form-layout-column-spacing: var(--lumo-space-l);
--vaadin-form-layout-row-spacing: 0;
--vaadin-form-item-row-spacing: 0;
Copy link
Contributor Author

@vursen vursen Feb 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed to override the default 1em value because it's now a part of the var expression: https://github.com/vaadin/web-components/pull/8638/files#diff-6ad2d1beab300f671707a82e473d6377e11eb67525696d17cc7ceb3097b6bd3fR54

}
`,
{ moduleId: 'lumo-form-layout' },
Expand Down