Fix mobile slide tables and thumbnails
This commit is contained in:
1 parent
b41440bdc5
commit
700278e7fb
3 files changed
+70
-3
No files matched your search
@@ -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
|
||||||
|
|||||||
@@ -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%),
|
||||||
|
|||||||
@@ -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: {},
|
||||||
|
|||||||
Reference in new issue
Block a user