mirror of
https://github.com/wekan/wekan.git
synced 2026-11-05 21:44:59 -05:00
Center a collapsed list's rotated title in its column.
The title used to sit near the TOP of a tall (540px) collapsed list, with empty space below it (.tools/collapse.png), on the desktop rule that actually wins (.list.list-collapsed:not(.mobile-view) ...): it explicitly pinned the title with `flex: 0 0 auto` and `align-self: flex-start` and never grew to fill the space left after the collapse-toggle/drag-handle. The plain (mobile-view) rule had the opposite bug - `flex: 1` fighting its own explicit `height: auto !important`, which also kept it from growing. Fixed both to grow (flex: 1 / flex: 1 1 auto) and center (display: flex; align-items/justify-content: center). Centering the title text itself inside its now-correctly-sized box needed one more fix verified with a Playwright screenshot of a minimal reproduction: shrinking the <h2> to its own content (so the parent's centering has something to center) rendered NO TEXT AT ALL for a vertical writing-mode block box with width/height: auto in a real browser. The <h2> stays 100%/100% of its parent instead and centers its own text run with flex (display: flex; align-items/ justify-content: center on the h2 itself), which measured correctly in both the plain and :not(.mobile-view) rule sets. tests/collapsedListTitleCentered.test.cjs pins the fixed values in both rule sets, comment text stripped first so an old value quoted in a "this used to be X" explanatory comment cannot pass as evidence X is gone. Thanks to xet7.
This commit is contained in:
1 parent
ad572c5b9e
commit
385f36e91a
2 files changed
+146
-13
No files matched your search
@@ -385,8 +385,13 @@ body.mobile-mode [id^="swimlane-"] .list[style*="--list-width"]:not(.list-collap
|
||||
.list.list-collapsed .list-header .list-rotated {
|
||||
width: 100% !important;
|
||||
max-width: 100%;
|
||||
height: auto !important;
|
||||
margin: 10px 0 0 0 !important;
|
||||
/* No fixed height/top-margin: `flex: 1` below needs the item's main size to
|
||||
come from flex-basis (0, from the shorthand), not from an explicit
|
||||
`height`, or the box shrinks to its content and sits right under the
|
||||
collapse-toggle/drag-handle instead of filling the rest of the column.
|
||||
That is why the title used to sit near the top of a tall collapsed list
|
||||
with empty space below it instead of being centered in it. */
|
||||
margin: 0 !important;
|
||||
position: relative !important;
|
||||
overflow: hidden !important;
|
||||
transform: none;
|
||||
@@ -402,15 +407,24 @@ body.mobile-mode [id^="swimlane-"] .list[style*="--list-width"]:not(.list-collap
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
white-space: normal;
|
||||
display: block !important;
|
||||
/* Fills its now-stretched parent (.list-rotated, edited above) and centers
|
||||
its own text run with flex: an `auto` width/height on a vertical
|
||||
writing-mode block box measured EMPTY in testing (the text did not
|
||||
render at all) for the equivalent :not(.mobile-view) rule further down,
|
||||
so this keeps 100%/100% and centers what is INSIDE the box instead of
|
||||
shrinking the box to its content. */
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(12px * var(--wekan-ui-font-scale, 1));
|
||||
line-height: 1.2;
|
||||
color: #333;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
height: 100%;
|
||||
max-height: 100%;
|
||||
position: static;
|
||||
inset-inline-start: auto;
|
||||
top: auto;
|
||||
@@ -1458,31 +1472,47 @@ form.inlined-form .list-composer {
|
||||
position: relative !important;
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
height: auto !important;
|
||||
margin: 4px 0 0 0 !important;
|
||||
/* This is the rule that actually wins on desktop (the extra :not() makes
|
||||
it more specific than the plain/media-query versions above), and it
|
||||
used to pin the title to the top-left corner of the collapsed list on
|
||||
purpose (display:block, flex:0 0 auto, align-self:flex-start) - the
|
||||
title should be CENTERED in the column instead, so make this a
|
||||
centering flex container that grows to fill the space left after the
|
||||
collapse-toggle/drag-handle, the same as the other .list-rotated rules
|
||||
in this file already do. */
|
||||
height: auto;
|
||||
margin: 0 !important;
|
||||
transform: none !important;
|
||||
transform-origin: initial !important;
|
||||
overflow: hidden !important;
|
||||
z-index: 1 !important;
|
||||
pointer-events: none !important;
|
||||
display: block !important;
|
||||
flex: 0 0 auto !important;
|
||||
align-self: flex-start;
|
||||
display: flex !important;
|
||||
flex: 1 1 auto !important;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.list.list-collapsed:not(.mobile-view) .list-header .list-rotated h2.list-header-name {
|
||||
display: block !important;
|
||||
/* Fills its now-stretched parent (.list-rotated, edited above) and centers
|
||||
its own text run with flex rather than shrinking to content: an `auto`
|
||||
width/height on a `vertical-lr` block box measured empty in testing
|
||||
(the text simply did not render), so the box keeps filling 100%/100%
|
||||
and centers what is INSIDE it instead. */
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
height: 100% !important;
|
||||
margin: 0 !important;
|
||||
max-height: 100% !important;
|
||||
max-height: 100%;
|
||||
padding: 2px 0 !important;
|
||||
white-space: normal !important;
|
||||
overflow: hidden !important;
|
||||
transform: none !important;
|
||||
writing-mode: vertical-lr !important;
|
||||
text-orientation: mixed !important;
|
||||
text-align: start !important;
|
||||
text-align: center !important;
|
||||
visibility: visible !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
'use strict';
|
||||
|
||||
// A collapsed list's rotated title used to sit near the TOP of the tall
|
||||
// (540px) collapsed column with empty space below it, instead of being
|
||||
// centered in it - visible in .tools/collapse.png. Two separate bugs, in two
|
||||
// separate rule sets that both style `.list-rotated`/`.list-header-name` for
|
||||
// a collapsed list (a plain rule and a more specific `:not(.mobile-view)`
|
||||
// one that actually wins on desktop):
|
||||
//
|
||||
// 1. `.list-rotated` itself did not stretch to fill the space left after
|
||||
// the collapse-toggle/drag-handle - one used `flex: 0 0 auto` outright,
|
||||
// the other had an explicit `height: auto` fighting its own `flex: 1`.
|
||||
// 2. The title `<h2>` filled 100%/100% of that box, which leaves the
|
||||
// parent's centering nothing to center; shrinking the h2 to its content
|
||||
// instead of filling 100%/100% seemed like the fix, but measured EMPTY
|
||||
// in a real browser (a vertical writing-mode block box with `width:
|
||||
// auto; height: auto` rendered no text at all) - so the actual fix
|
||||
// keeps the h2 at 100%/100% and centers its OWN text run with flex
|
||||
// instead of shrinking the box.
|
||||
//
|
||||
// Verified with a Playwright screenshot of a minimal reproduction against
|
||||
// both the `.mobile-view` and non-mobile-view rule sets before pinning this
|
||||
// as a static test (no browser here).
|
||||
//
|
||||
// Run: node tests/collapsedListTitleCentered.test.cjs
|
||||
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const repoRoot = path.resolve(__dirname, '..');
|
||||
const css = fs.readFileSync(path.join(repoRoot, 'client/components/lists/list.css'), 'utf8');
|
||||
|
||||
let passed = 0;
|
||||
function test(name, fn) { fn(); passed += 1; console.log(' ok -', name); }
|
||||
|
||||
console.log('collapsedListTitleCentered:');
|
||||
|
||||
// Extract one `selector { ... }` block by its exact selector line, with its
|
||||
// /* ... */ comments stripped - some of them explain, in prose, the OLD
|
||||
// values being fixed, which must not accidentally satisfy a check looking
|
||||
// for their absence.
|
||||
function ruleBody(selector) {
|
||||
const at = css.indexOf(`${selector} {`);
|
||||
assert.ok(at !== -1, `expected to find the rule: ${selector}`);
|
||||
const end = css.indexOf('\n}', at);
|
||||
return css.slice(at, end).replace(/\/\*[\s\S]*?\*\//g, '');
|
||||
}
|
||||
|
||||
test('.list-rotated grows to fill the collapsed column, in both rule sets', () => {
|
||||
const plain = ruleBody('.list.list-collapsed .list-header .list-rotated');
|
||||
assert.ok(/flex:\s*1\s*;/.test(plain), 'the plain rule uses flex: 1');
|
||||
assert.ok(!/height:\s*auto\s*!important/.test(plain),
|
||||
'and no longer fights it with an explicit height: auto !important');
|
||||
|
||||
const desktop = ruleBody('.list.list-collapsed:not(.mobile-view) .list-header .list-rotated');
|
||||
assert.ok(/flex:\s*1 1 auto\s*!important/.test(desktop),
|
||||
'the desktop (:not(.mobile-view), the one that actually wins) rule grows too');
|
||||
assert.ok(!/flex:\s*0 0 auto/.test(desktop),
|
||||
'the old flex: 0 0 auto (never grow) is gone');
|
||||
assert.ok(!/align-self:\s*flex-start/.test(desktop),
|
||||
'and the old top/start pin (align-self: flex-start) is gone');
|
||||
});
|
||||
|
||||
test('.list-rotated centers its content, in both rule sets', () => {
|
||||
for (const selector of [
|
||||
'.list.list-collapsed .list-header .list-rotated',
|
||||
'.list.list-collapsed:not(.mobile-view) .list-header .list-rotated',
|
||||
]) {
|
||||
const body = ruleBody(selector);
|
||||
assert.ok(/display:\s*flex/.test(body), `${selector} is a flex container`);
|
||||
assert.ok(/align-items:\s*center/.test(body) && /justify-content:\s*center/.test(body),
|
||||
`${selector} centers on both axes`);
|
||||
}
|
||||
});
|
||||
|
||||
test('the title itself centers its OWN text run instead of shrinking to content', () => {
|
||||
// Shrinking width/height to content measured EMPTY in a real browser for a
|
||||
// vertical writing-mode block box - see the header comment. The h2 must
|
||||
// stay 100%/100% and be a flex container of its own, not `display: block`.
|
||||
for (const selector of [
|
||||
'.list.list-collapsed .list-header .list-rotated h2.list-header-name',
|
||||
'.list.list-collapsed:not(.mobile-view) .list-header .list-rotated h2.list-header-name',
|
||||
]) {
|
||||
const body = ruleBody(selector);
|
||||
assert.ok(/display:\s*flex\s*!important/.test(body), `${selector} is display: flex`);
|
||||
assert.ok(/align-items:\s*center/.test(body) && /justify-content:\s*center/.test(body),
|
||||
`${selector} centers its own text run`);
|
||||
assert.ok(/width:\s*100%/.test(body) && /height:\s*100%/.test(body),
|
||||
`${selector} still fills its parent rather than shrinking to content`);
|
||||
assert.ok(!/width:\s*auto\s*;/.test(body) && !/height:\s*auto\s*;(?!\s*!important)/.test(body),
|
||||
`${selector} does not shrink its box to content`);
|
||||
}
|
||||
// The desktop rule's text-align used to be "start" (top/left in its
|
||||
// vertical-lr writing mode), which the flex centering above replaces -
|
||||
// but keep text-align: center too, for the cross-axis wrap of a long title.
|
||||
const desktopH2 = ruleBody(
|
||||
'.list.list-collapsed:not(.mobile-view) .list-header .list-rotated h2.list-header-name');
|
||||
assert.ok(/text-align:\s*center\s*!important/.test(desktopH2),
|
||||
'text-align is center, not the old start');
|
||||
});
|
||||
|
||||
console.log(`\ncollapsedListTitleCentered: ${passed} tests passed`);
|
||||
Reference in new issue
Block a user