Fix rotated table layout issues
This commit is contained in:
fraxle
2026-08-09 09:47:57 +01:00
parent 1bb870eab3
commit dace65b750
4 changed files with 149 additions and 103 deletions
+90 -55
View File
@@ -2542,28 +2542,25 @@
is two tables kept in step by useTableScroll — this is ONE table in a
single scroll pane, so both sticky edges are pure CSS.
The pane scrolls in both axes rather than letting the page scroll
vertically: sticky positioning resolves against the nearest scrolling
ancestor, and making the pane scroll horizontally makes it the
vertical scroll ancestor too. Scrolling both here is what lets the
hour row and the metric column stay pinned at the same time.
A single table in the shared .utci-tbody-scroll horizontal scroller.
The normal orientation splits head from body so its header can stick
to the viewport; here the hour row scrolls away with the table by
design, so that machinery is not needed. The metric column pins with
plain CSS sticky, which works fine inside the scroller. The table
keeps its natural height and the page scrolls normally.
══════════════════════════════════════════════════════════════════════ */
.utci-rotated-scroll {
overflow: auto;
max-height: min(78vh, 900px);
-webkit-overflow-scrolling: touch;
overscroll-behavior: contain;
cursor: grab; /* drag-to-scroll, same as the normal body scroller */
}
.utci-rotated-scroll:active {
cursor: grabbing;
/* Fallback only, for the first paint before the measurement lands.
useTableScroll measures the pinned column and writes --hour-col-w
inline — it can't be fixed here, because auto layout widens that
column to fit the longest metric name on show. */
.utci-table-wrap.is-rotated {
--hour-col-w: 136px;
}
/* Auto layout — the whole point of the rotated view is that each column
is only as wide as the hour it holds, so the fixed layout the normal
table needs for its JS width-sync is explicitly turned off here. */
.utci-table.utci-table-rotated {
/* Auto layout: with a single table there are no header widths to match,
so each hour column can simply size to its own content. */
table-layout: auto;
width: max-content;
min-width: 100%;
@@ -2594,12 +2591,10 @@
white-space: nowrap;
}
/* ── STICKY HOUR ROW (top) ────────────────────────────────────────── */
/* The hour row is deliberately NOT sticky: pinning it would mean the
metric rows sliding underneath, and with only a dozen of them the
table reads as shrinking away to nothing. It scrolls with the page. */
.utci-table-rotated thead th {
position: sticky;
top: 0;
z-index: 4;
background: #f0e4c4;
vertical-align: middle;
}
@@ -2668,6 +2663,33 @@
background-image: linear-gradient(var(--grp-tint, transparent), var(--grp-tint, transparent));
}
/* The group rules carry a 2px left border that marks where a group STARTS
along the columns. Rotated, groups are stacked rows and have no left
edge to mark, so it shows up as a stray line — and its width offsets
the label 2px against the metric names below it. */
.utci-table.utci-table-rotated tbody .grp-label-row--rotated th {
border-left: 0;
}
/* The group heading pins with the metric names it labels. */
.utci-table.utci-table-rotated tbody th.rot-group-label {
position: sticky;
left: 0;
z-index: 3;
text-align: left;
padding: 5px 16px;
box-shadow: 1px 0 0 rgba(74, 50, 24, 0.18);
}
/* The per-hour cells filling out a divider row. They carry the group tint
and, in the current hour's column, its share of the brass bracket. */
.utci-table.utci-table-rotated tbody td.grp-label-fill {
padding: 5px 0;
min-width: 0;
background: var(--grp-tint, transparent);
border-bottom: 1px solid rgba(74, 50, 24, 0.18);
}
.utci-table.utci-table-rotated tbody th.rot-metric-label {
position: sticky;
left: 0;
@@ -2681,15 +2703,14 @@
/* The corner cell sits in both sticky tracks, so it needs to win over
each of them. */
/* The selector is deliberately over-qualified: the normal orientation's
`.utci-table thead th:first-child` rule pins the Hour heading with
position:relative + a JS transform, and would otherwise out-specify
this and stop the corner sticking. */
/* The corner pins alongside the metric names below it. Over-qualified so
it beats the normal orientation's `.utci-table thead th:first-child`
rule, which sets position:relative for the JS transform this view
doesn't use. */
.utci-table.utci-table-rotated thead th.rot-corner {
position: sticky;
top: 0;
left: 0;
z-index: 6;
z-index: 4;
background: #f0e4c4;
text-align: left;
transform: none;
@@ -2710,12 +2731,10 @@
@media (max-width: 640px) {
/* Icon-only on narrow screens — the toolbar is already tight. */
.table-rotate-btn-label {
display: none;
}
.table-rotate-btn {
padding: 6px 8px;
font-size: 0;
gap: 0;
padding: 6px 7px;
}
}
@@ -2728,11 +2747,6 @@
padding: 5px 16px;
border-right: 0;
}
.utci-table-rotated .grp-label-pin {
position: sticky;
left: 16px;
display: inline-block;
}
/* ── NOW / NIGHT ──────────────────────────────────────────────────────
Rotated, "now" is a column rather than a row, so the brass bracket
@@ -2750,39 +2764,57 @@
color: #7a5c30;
}
/* ── TOOLBAR BUTTON HEIGHTS ───────────────────────────────────────────
Quick/Detailed, Rotate and Edit columns sit on one row and have to
agree on height. They didn't: the first two set line-height:1 while
Edit columns leaves it at normal, so the same 6px padding produced a
box ~3px taller. Pinning one line-height and one min-height across all
three settles it regardless of font-size differences. */
.fvt-btn,
.table-rotate-btn,
.col-toggles-edit-btn {
min-height: 29px;
line-height: 1;
}
/* ── ROTATE BUTTON ────────────────────────────────────────────────────
Sits in the toolbar after the view switcher and Edit columns, and only
while the detailed table is showing. */
Sits beside the Quick/Detailed view toggle and only while the detailed
table is showing. Deliberately mirrors .fvt-btn — same type, padding,
border and states — so it reads as part of that control group rather
than a stray button. Standalone, so it keeps a radius on all corners
where .fvt-btn splits its radius across the segmented pair. */
.table-rotate-btn {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 11px;
border: 1px solid #c9b08a;
border-radius: 6px;
background: #fffcf2;
color: #8a6a34;
gap: 4px;
font-family: Manrope, sans-serif;
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.06em;
line-height: 1;
padding: 6px 8px;
cursor: pointer;
transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.table-rotate-btn-icon {
font-size: 14px;
line-height: 1;
border: 1.5px solid #c9b08a;
border-radius: 3px;
background: #f5edd6;
color: #6b4228;
transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.table-rotate-btn:hover {
background: #f6ead0;
color: #6b4f2a;
border-color: #c8922a;
background: #fef3dc;
}
.table-rotate-btn.on {
background: #c8922a;
border-color: #c8922a;
color: #fffcf2;
color: #fff;
}
/* The icon turns with the state it describes — flat when hours run down
the side, quarter-turned when they run along the top. */
.table-rotate-btn .fvt-btn-icon {
transition: transform 0.18s ease;
}
.table-rotate-btn.on .fvt-btn-icon {
transform: rotate(90deg);
}
/* ── MOBILE ───────────────────────────────────────────────────────── */
@@ -2802,4 +2834,7 @@
.utci-table-rotated .rot-metric-label {
min-width: 112px;
}
.utci-table-wrap.is-rotated {
--hour-col-w: 112px;
}
}