diff --git a/lib/public/app.css b/lib/public/app.css index d2a524dfa2..abd8f54853 100644 --- a/lib/public/app.css +++ b/lib/public/app.css @@ -208,6 +208,14 @@ th.text-center, td.text-center { } +/* + * Scrollable wrappers clip everything overflowing their box, including the table shadow: + * leave some room on the sides and at the bottom (not at the top to not break the sticky header) to display it + */ +.table-shadow-room { + padding: 0 6px 6px; +} + .sticky-table-wrapper { flex: 1 1 auto; overflow-y: auto; diff --git a/lib/public/components/common/table/table.js b/lib/public/components/common/table/table.js index c481ec451e..206e26f5cc 100644 --- a/lib/public/components/common/table/table.js +++ b/lib/public/components/common/table/table.js @@ -156,6 +156,7 @@ export const table = ( optionalTableClassesExpression += tableClasses; const firstLevelWrapperClasses = + (scrollEnabled ? '.table-shadow-room' : '') + (verticalScrollEnabled ? '.sticky-table-wrapper' : '') + (singleWrapper && scrollEnabled ? '.scroll-auto' : ''); diff --git a/test/public/runsPerPeriodOrPass/runsPerDataPass.overview.test.js b/test/public/runsPerPeriodOrPass/runsPerDataPass.overview.test.js index 75d4a42e8a..43318e971b 100644 --- a/test/public/runsPerPeriodOrPass/runsPerDataPass.overview.test.js +++ b/test/public/runsPerPeriodOrPass/runsPerDataPass.overview.test.js @@ -97,6 +97,30 @@ module.exports = () => { expect(viewTitleElements).to.have.all.ordered.members(['Physics Runs', 'LHC22b_apass1']); }); + it('leaves enough room around the table to display its shadow', async () => { + await goToPage(page, 'runs-per-data-pass', { queryParameters: { dataPassId: 1 } }); + await page.waitForSelector('.sticky-table-wrapper table tbody tr'); + + // The scrollable wrappers clip what overflows them: the table shadow is visible only if there is some room around the table + const { shadow, spaceLeft, paddingRight, spaceBottom } = await page.evaluate(() => { + const table = document.querySelector('.sticky-table-wrapper table'); + const wrapper = document.querySelector('.sticky-table-wrapper'); + const tableBox = table.getBoundingClientRect(); + const wrapperBox = wrapper.getBoundingClientRect(); + return { + shadow: getComputedStyle(table).boxShadow, + spaceLeft: tableBox.left - wrapperBox.left, + // The table may overflow horizontally (scroll), so its right side can only be checked through the wrapper padding + paddingRight: parseFloat(getComputedStyle(wrapper).paddingRight), + spaceBottom: wrapperBox.bottom - tableBox.bottom, + }; + }); + expect(shadow).to.not.equal('none'); + expect(spaceLeft).to.be.at.least(5); + expect(paddingRight).to.be.at.least(5); + expect(spaceBottom).to.be.at.least(5); + }); + it('shows correct datatypes in respective columns', async () => { const commonColumnsValidators = { runNumber: (number) => !isNaN(number), diff --git a/test/public/runsPerPeriodOrPass/runsPerSimulationPass.overview.test.js b/test/public/runsPerPeriodOrPass/runsPerSimulationPass.overview.test.js index 58effa87e7..078ed2e792 100644 --- a/test/public/runsPerPeriodOrPass/runsPerSimulationPass.overview.test.js +++ b/test/public/runsPerPeriodOrPass/runsPerSimulationPass.overview.test.js @@ -94,6 +94,30 @@ module.exports = () => { expect(await headerBreadcrumbs[1].evaluate((element) => element.innerText)).to.be.equal('LHC23k6b'); }); + it('leaves enough room around the table to display its shadow', async () => { + await goToPage(page, 'runs-per-simulation-pass', { queryParameters: { simulationPassId: 2 } }); + await page.waitForSelector('.sticky-table-wrapper table tbody tr'); + + // The scrollable wrappers clip what overflows them: the table shadow is visible only if there is some room around the table + const { shadow, spaceLeft, paddingRight, spaceBottom } = await page.evaluate(() => { + const table = document.querySelector('.sticky-table-wrapper table'); + const wrapper = document.querySelector('.sticky-table-wrapper'); + const tableBox = table.getBoundingClientRect(); + const wrapperBox = wrapper.getBoundingClientRect(); + return { + shadow: getComputedStyle(table).boxShadow, + spaceLeft: tableBox.left - wrapperBox.left, + // The table may overflow horizontally (scroll), so its right side can only be checked through the wrapper padding + paddingRight: parseFloat(getComputedStyle(wrapper).paddingRight), + spaceBottom: wrapperBox.bottom - tableBox.bottom, + }; + }); + expect(shadow).to.not.equal('none'); + expect(spaceLeft).to.be.at.least(5); + expect(paddingRight).to.be.at.least(5); + expect(spaceBottom).to.be.at.least(5); + }); + it('shows correct datatypes in respective columns', async () => { const tableDataValidators = { runNumber: (number) => !isNaN(number),