Fix mobile slide tables and thumbnails
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile, web, pulse-signage-web) (push) Successful in 1m14s
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile.player, player, pulse-signage-player) (push) Successful in 35s

This commit is contained in:
lzstealth committed 2026-10-22 15:54:19 +01:00
1 parent b41440bdc5
commit 700278e7fb
3 files changed
+70 -3

No files matched your search

+5
View File
@@ -8,6 +8,11 @@ All notable changes to this project will be documented in this file.
- Updated web and player container images to Node.js 26.12.1 to address the October 2026 security releases. - Updated web and player container images to Node.js 26.12.1 to address the October 2026 security releases.
### Fixed
- Slide thumbnails and empty placeholders on Slides and playlist pages preserve the canvas aspect ratio and display the full image without cropping on smaller screens; standalone thumbnails are centered within their column.
- Responsive tables keep descriptive text columns wide enough for multi-word lines on mobile, using horizontal scrolling instead of squeezing text into narrow columns.
## 2.16.3 - 2026-10-21 ## 2.16.3 - 2026-10-21
### Changed ### Changed
+29 -3
View File
@@ -2120,6 +2120,22 @@ td[data-label="Slides"] {
overflow-wrap: anywhere; overflow-wrap: anywhere;
} }
@media (max-width: 767.98px) {
.table-responsive > table.table > tbody > tr > td:is(
[data-label="Name"],
[data-label="Title"],
[data-label="Template"],
[data-label="Description"],
[data-label="Client"],
[data-label="Current Screen"],
[data-label="Current Slide"],
[data-label="Slides"]
) {
min-width: 14rem;
overflow-wrap: break-word;
}
}
.slide-editor-shell { .slide-editor-shell {
display: grid; display: grid;
grid-template-columns: minmax(0, 1fr) minmax(18rem, 24rem); grid-template-columns: minmax(0, 1fr) minmax(18rem, 24rem);
@@ -4032,6 +4048,8 @@ table.table > :not(caption) > * > * {
.playlist-slide-thumb { .playlist-slide-thumb {
flex: 0 0 auto; flex: 0 0 auto;
width: min(5.5rem, calc(5.5rem * (var(--playlist-slide-thumb-aspect-ratio, 16 / 9))));
min-height: 0;
max-width: 5.5rem; max-width: 5.5rem;
max-height: 5.5rem; max-height: 5.5rem;
aspect-ratio: var(--playlist-slide-thumb-aspect-ratio, 16 / 9); aspect-ratio: var(--playlist-slide-thumb-aspect-ratio, 16 / 9);
@@ -4043,10 +4061,18 @@ table.table > :not(caption) > * > * {
justify-content: center; justify-content: center;
} }
.card .table td[data-label="Thumbnail"] {
padding-inline: 1.5rem;
}
td[data-label="Thumbnail"] > .playlist-slide-thumb {
margin-inline: auto;
}
.playlist-slide-thumb-image { .playlist-slide-thumb-image {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover; object-fit: contain;
display: block; display: block;
} }
@@ -4056,8 +4082,8 @@ table.table > :not(caption) > * > * {
justify-content: center; justify-content: center;
width: 100%; width: 100%;
height: 100%; height: 100%;
min-width: 5.5rem; min-width: 0;
min-height: 3.5rem; min-height: 0;
color: var(--bs-secondary-color, #6c757d); color: var(--bs-secondary-color, #6c757d);
background: background:
linear-gradient(135deg, rgba(255, 255, 255, 0.06) 0%, rgba(255, 255, 255, 0.02) 100%), linear-gradient(135deg, rgba(255, 255, 255, 0.06) 0%, rgba(255, 255, 255, 0.02) 100%),
+36
View File
@@ -4,6 +4,42 @@ const vm = require('node:vm');
const test = require('node:test'); const test = require('node:test');
const assert = require('node:assert/strict'); const assert = require('node:assert/strict');
test('slide table thumbnails size to the canvas ratio and show the whole image', () => {
const stylesheet = fs.readFileSync(path.join(__dirname, '..', 'src', 'web', 'public', 'css', 'theme-custom.css'), 'utf8');
const thumbRule = stylesheet.match(/^\.playlist-slide-thumb\s*\{([^}]+)\}/m)[1];
const imageRule = stylesheet.match(/^\.playlist-slide-thumb-image\s*\{([^}]+)\}/m)[1];
const placeholderRule = stylesheet.match(/^\.playlist-slide-thumb-placeholder\s*\{([^}]+)\}/m)[1];
assert.match(thumbRule, /width:\s*min\(5\.5rem, calc\(5\.5rem \* \(var\(--playlist-slide-thumb-aspect-ratio, 16 \/ 9\)\)\)\);/);
assert.match(thumbRule, /aspect-ratio:\s*var\(--playlist-slide-thumb-aspect-ratio, 16 \/ 9\);/);
assert.match(thumbRule, /min-height:\s*0;/);
assert.match(thumbRule, /flex:\s*0 0 auto;/);
assert.match(imageRule, /object-fit:\s*contain;/);
assert.match(placeholderRule, /min-width:\s*0;/);
assert.match(placeholderRule, /min-height:\s*0;/);
});
test('standalone slide thumbnails are centered within their table column', () => {
const stylesheet = fs.readFileSync(path.join(__dirname, '..', 'src', 'web', 'public', 'css', 'theme-custom.css'), 'utf8');
const columnRule = stylesheet.match(/^td\[data-label="Thumbnail"\] > \.playlist-slide-thumb\s*\{([^}]+)\}/m)[1];
const cellRule = stylesheet.match(/^\.card \.table td\[data-label="Thumbnail"\]\s*\{([^}]+)\}/m)[1];
assert.match(columnRule, /margin-inline:\s*auto;/);
assert.match(cellRule, /padding-inline:\s*1\.5rem;/);
});
test('mobile responsive tables keep descriptive columns wide enough for phrases', () => {
const stylesheet = fs.readFileSync(path.join(__dirname, '..', 'src', 'web', 'public', 'css', 'theme-custom.css'), 'utf8');
const mobileRule = stylesheet.match(/@media \(max-width: 767\.98px\)\s*\{\s*\.table-responsive > table\.table > tbody > tr > td:is\(([\s\S]*?)\)\s*\{([^}]+)\}/);
assert.ok(mobileRule);
for (const label of ['Name', 'Title', 'Template', 'Description', 'Client', 'Current Screen', 'Current Slide', 'Slides']) {
assert.ok(mobileRule[1].includes('[data-label="' + label + '"]'));
}
assert.match(mobileRule[2], /min-width:\s*14rem;/);
assert.match(mobileRule[2], /overflow-wrap:\s*break-word;/);
});
test('table pagination cards skip the minimum height for short content', () => { test('table pagination cards skip the minimum height for short content', () => {
const cardStyle = { const cardStyle = {
properties: {}, properties: {},