diff --git a/entry_types/scrolled/package/spec/frontend/Layout-spec.js b/entry_types/scrolled/package/spec/frontend/Layout-spec.js index 07e72809a1..03f3e093ea 100644 --- a/entry_types/scrolled/package/spec/frontend/Layout-spec.js +++ b/entry_types/scrolled/package/spec/frontend/Layout-spec.js @@ -122,6 +122,24 @@ describe('Layout', () => { ); }); + it('creates new group for side elements', () => { + const items = [ + {id: 1, type: 'probe', position: 'inline'}, + {id: 2, type: 'probe', position: 'side'}, + {id: 3, type: 'probe', position: 'side'}, + {id: 4, type: 'probe', position: 'inline'} + ]; + const {container} = renderInEntry( + + {(children, {position}) =>
{position} {children}
} +
+ ); + + expect(container.textContent).toEqual( + '[inline 1 ][side 2 3 inline 4 ]' + ); + }); + it('places inline elements with custom margin in separate box in same group', () => { const items = [ {id: 1, type: 'probe', position: 'inline'}, @@ -139,6 +157,22 @@ describe('Layout', () => { expect(container.textContent).toEqual('[inline normal 1 inline custom 2 inline normal 3 ]'); }); + it('places side elements with and without custom margin in separate groups', () => { + const items = [ + {id: 1, type: 'probe', position: 'side'}, + {id: 2, type: 'probeWithCustomMargin', position: 'side'} + ]; + const {container} = renderInEntry( + + {(children, {position, customMargin}) => +
{position} {customMargin ? 'custom' : 'normal'} {children}
+ } +
+ ); + + expect(container.textContent).toEqual('[side normal 1 ][side custom 2 ]'); + }); + it('places sticky elements with and without custom margin in separate groups', () => { const items = [ {id: 1, type: 'probe', position: 'sticky'}, @@ -199,6 +233,23 @@ describe('Layout', () => { }); }); + it('continues inline box after being interrupted by side box', () => { + const items = [ + {id: 1, type: 'probe', position: 'inline'}, + {id: 2, type: 'probe', position: 'inline'}, + {id: 3, type: 'probe', position: 'side'}, + {id: 4, type: 'probe', position: 'side'}, + {id: 5, type: 'probe', position: 'inline'}, + ]; + const {container} = renderInEntry( + + {(children, boxProps) => {children}} + + ); + + expect(container.textContent).toEqual('[( 1 2 |][( 3 4 )| 5 )]'); + }); + it('continues inline box after being interrupted by sticky box', () => { const items = [ {id: 1, type: 'probe', position: 'inline'}, @@ -233,6 +284,23 @@ describe('Layout', () => { expect(container.textContent).toEqual('[( 1 2 |][( 3 4 )| 5 )]'); }); + it('continues inline box in new group after side box', () => { + const items = [ + {id: 1, type: 'probe', position: 'inline'}, + {id: 2, type: 'probe', position: 'side'}, + {id: 3, type: 'probe', position: 'inline'}, + {id: 4, type: 'probe', position: 'side'}, + {id: 5, type: 'probe', position: 'inline'}, + ]; + const {container} = renderInEntry( + + {(children, boxProps) => {children}} + + ); + + expect(container.textContent).toEqual('[( 1 |][( 2 )| 3 |][( 4 )| 5 )]'); + }); + it('continues inline box in new group after sticky box', () => { const items = [ {id: 1, type: 'probe', position: 'inline'}, @@ -282,6 +350,22 @@ describe('Layout', () => { expect(container.textContent).toEqual('[( 1 2 )][( 3 )][( 4 )]'); }); + it('does not continue inline box after being interrupted by side and full box', () => { + const items = [ + {id: 1, type: 'probe', position: 'inline'}, + {id: 2, type: 'probe', position: 'side'}, + {id: 3, type: 'probe', position: 'inline', width: 3}, + {id: 4, type: 'probe', position: 'inline'}, + ]; + const {container} = renderInEntry( + + {(children, boxProps) => {children}} + + ); + + expect(container.textContent).toEqual('[( 1 )][( 2 )][( 3 )][( 4 )]'); + }); + it('does not continue inline box after being interrupted by sticky and full box', () => { const items = [ {id: 1, type: 'probe', position: 'inline'}, @@ -298,6 +382,22 @@ describe('Layout', () => { expect(container.textContent).toEqual('[( 1 )][( 2 )][( 3 )][( 4 )]'); }); + it('does not continue inline box after being interrupted by full and side box', () => { + const items = [ + {id: 1, type: 'probe', position: 'inline'}, + {id: 2, type: 'probe', position: 'inline', width: 3}, + {id: 3, type: 'probe', position: 'side'}, + {id: 4, type: 'probe', position: 'inline'}, + ]; + const {container} = renderInEntry( + + {(children, boxProps) => {children}} + + ); + + expect(container.textContent).toEqual('[( 1 )][( 2 )][( 3 )( 4 )]'); + }); + it('does not continue inline box after being interrupted by full and sticky box', () => { const items = [ {id: 1, type: 'probe', position: 'inline'}, @@ -329,6 +429,21 @@ describe('Layout', () => { expect(container.textContent).toEqual('[( 1 )( 2 )( 3 )]'); }); + it('continues inline box after being interrupted by side custom margin box', () => { + const items = [ + {id: 1, type: 'probe', position: 'inline'}, + {id: 2, type: 'probeWithCustomMargin', position: 'side'}, + {id: 3, type: 'probe', position: 'inline'}, + ]; + const {container} = renderInEntry( + + {(children, boxProps) => {children}} + + ); + + expect(container.textContent).toEqual('[( 1 |][( 2 )| 3 )]'); + }); + it('continues inline box after being interrupted by sticky custom margin box', () => { const items = [ {id: 1, type: 'probe', position: 'inline'}, @@ -344,6 +459,37 @@ describe('Layout', () => { expect(container.textContent).toEqual('[( 1 |][( 2 )| 3 )]'); }); + it('inlines side elements of different width at different breakpoints ', () => { + const items = [ + {id: 1, type: 'probe', position: 'side'}, + {id: 2, type: 'probe', position: 'side', width: 1}, + {id: 3, type: 'probe', position: 'side', width: 2} + ]; + viewportWidth = 1000; + const {container} = renderInEntry( + + {(children, {position}) =>
{position} {children}
} +
, + { + seed: { + themeOptions: { + properties: { + root: { + twoColumnStickyBreakpoint: '950px', + twoColumnStickyLgBreakpoint: '1024px', + twoColumnStickyXlBreakpoint: '1180px' + } + } + } + } + } + ); + + expect(container.textContent).toEqual( + '[side 1 inline 2 ][inline 3 ]' + ); + }); + it('inlines sticky elements of different width at different breakpoints ', () => { const items = [ {id: 1, type: 'probe', position: 'sticky'}, @@ -375,6 +521,39 @@ describe('Layout', () => { ); }); + it('decreases size when inlining wide side elements', () => { + const items = [ + {id: 1, type: 'probe', position: 'side', width: -2}, + {id: 2, type: 'probe', position: 'side', width: -1}, + {id: 3, type: 'probe', position: 'side'}, + {id: 4, type: 'probe', position: 'side', width: 1}, + {id: 5, type: 'probe', position: 'side', width: 2} + ]; + viewportWidth = 500; + const {container} = renderInEntry( + + {(children, {position, width}) =>
{position} {widthName(width)} {children}
} +
, + { + seed: { + themeOptions: { + properties: { + root: { + twoColumnStickyBreakpoint: '950px', + twoColumnStickyLgBreakpoint: '1024px', + twoColumnStickyXlBreakpoint: '1180px' + } + } + } + } + } + ); + + expect(container.textContent).toEqual( + '[inline xs 1 ][inline sm 2 ][inline md 3 4 ][inline lg 5 ]' + ); + }); + it('decreases size when inlining wide sticky elements', () => { const items = [ {id: 1, type: 'probe', position: 'sticky', width: -2}, diff --git a/entry_types/scrolled/package/src/frontend/layouts/TwoColumn.js b/entry_types/scrolled/package/src/frontend/layouts/TwoColumn.js index a42f23e26d..3cc968e75a 100644 --- a/entry_types/scrolled/package/src/frontend/layouts/TwoColumn.js +++ b/entry_types/scrolled/package/src/frontend/layouts/TwoColumn.js @@ -110,19 +110,19 @@ function groupItemsByPosition(items, shouldInline) { const {customMargin: elementSupportsCustomMargin} = api.contentElementTypes.getOptions(item.type) || {}; let width = item.width || 0; - const position = item.position === 'sticky' && !shouldInline(width) ? 'sticky' : 'inline'; + const position = onTheSide(item.position) && !shouldInline(width) ? item.position : 'inline'; const customMargin = !!elementSupportsCustomMargin && width < widths.full; - if (item.position === 'sticky' && position === 'inline' && width > widths.md) { + if (onTheSide(item.position) && position === 'inline' && width > widths.md) { width -= 1; } if (!currentGroup || previousPosition !== position || - (position === 'sticky' && currentBox.customMargin !== customMargin) || + (onTheSide(position) && currentBox.customMargin !== customMargin) || currentBox.width !== width) { currentBox = null; - if (!(previousPosition === 'sticky' && position === 'inline' && width <= widths.md)) { + if (!(onTheSide(previousPosition) && position === 'inline' && width <= widths.md)) { currentGroup = { width, boxes: [] @@ -149,7 +149,7 @@ function groupItemsByPosition(items, shouldInline) { lastInlineBox = currentBox; } else if ((position === 'inline' && width > widths.md) || - (customMargin && position !== 'sticky')) { + (customMargin && !onTheSide(position))) { lastInlineBox = null; } @@ -163,6 +163,10 @@ function groupItemsByPosition(items, shouldInline) { return groups; } +function onTheSide(position) { + return position === 'side' || position === 'sticky'; +} + function renderPlaceholder(placeholder) { if (!placeholder) { return null; diff --git a/entry_types/scrolled/package/src/frontend/layouts/TwoColumn.module.css b/entry_types/scrolled/package/src/frontend/layouts/TwoColumn.module.css index d731b8d82f..98ae1e978d 100644 --- a/entry_types/scrolled/package/src/frontend/layouts/TwoColumn.module.css +++ b/entry_types/scrolled/package/src/frontend/layouts/TwoColumn.module.css @@ -80,32 +80,36 @@ margin-left: auto; } -.sticky { +.side { --content-width: var(--theme-two-column-sticky-content-width, 25vw); --content-max-width: min(var(--content-width), var(--two-column-sticky-content-max-width, 600px)); - position: sticky; float: right; clear: both; top: 33%; width: var(--content-width); } -.right .sticky { +.sticky { + composes: side; + position: sticky; +} + +.right .side { float: left; } -.sticky.width-lg { +.side.width-lg { --content-width: var(--theme-two-column-sticky-lg-content-width, 35vw); --content-max-width: min(var(--content-width), var(--two-column-sticky-lg-content-max-width, 700px)); } -.sticky.width-xl { +.side.width-xl { --content-width: var(--theme-two-column-sticky-xl-content-width, 45vw); --content-max-width: min(var(--content-width), var(--two-column-sticky-xl-content-max-width, 1000px)); } -.sticky.customMargin { +.side.customMargin { width: 100%; }