mobile: wrap tabs, trim portfolio + markets bar columns

Three pieces of phone-side feedback:

1. Indicator group tabs wrap onto multiple rows instead of
   horizontal-scrolling — every group is visible at a glance. Each
   button keeps its own bottom border so wrapped rows stay
   visually delimited; the container's bottom border is removed.

2. Portfolio holdings table hides Qty and Avg columns on mobile via
   the mobile-hide class (same mechanism as the indicator table).
   Remaining columns are the actionable ones: Ticker, Name, Last,
   P/L, %.

3. Markets bar at the bottom compacts to one row per chip —
   dot + code + change% only. The state word ("open" / "closed")
   is implied by the dot colour; the index label, price, and
   until-time are dropped on mobile. Grid columns drop their 220px
   floor so the full set fits the viewport without horizontal
   scroll (previously the bar scrolled within itself).
This commit is contained in:
Giorgio Gilestro 2026-05-28 19:10:58 +02:00
parent 8ec4ea1c72
commit 6459e8c43d
3 changed files with 53 additions and 19 deletions

View file

@ -248,11 +248,19 @@
identifying anchor. */ identifying anchor. */
.dense td.label { font-weight: 600; } .dense td.label { font-weight: 600; }
/* Group-tabs strip already has overflow-x:auto; widen the tap /* Group tabs: wrap onto multiple rows instead of horizontal
targets so swipe-scrolling on a touchscreen feels natural. */ scrolling so the user can see every group at a glance. The
border-bottom moves to each row so wrapped rows are still
visually delimited. */
.group-tabs {
flex-wrap: wrap;
overflow-x: visible;
border-bottom: 0;
}
.group-tabs button { .group-tabs button {
padding: 8px 14px; padding: 6px 10px;
font-size: 11.5px; font-size: 11px;
border-bottom: 1px solid var(--border);
white-space: nowrap; white-space: nowrap;
} }

View file

@ -386,19 +386,45 @@ body.drawer-open .drawer-backdrop { opacity: 1; }
} }
.app-main > * { min-width: 0; } .app-main > * { min-width: 0; }
/* Markets bar: the desktop grid uses minmax(220px, 1fr) per market, /* Markets bar: compact each chip so the full set fits the viewport
which at 4+ markets blows out to 880px+ and forces page-wide without horizontal scrolling. We drop:
horizontal scroll. On phones, let the bar itself scroll - state word ("open" / "closed") the dot already conveys that
horizontally so the page can stay narrow. Each chip gets a - index label (e.g. "SPX") implied by the market code
reasonable min-width so the values inside don't wrap. */ - index price keep the change% which is the actionable number
- until-time too detailed for a glance
Remaining: dot + market code + change%. The grid keeps auto-fit
but the minimum drops from 220px to 0 so it always fits. */
.markets-bar__inner { .markets-bar__inner {
grid-template-columns: none; grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
display: flex; gap: 0;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
} }
.markets-bar .mkt { .markets-bar .mkt {
flex: 0 0 auto; grid-template-columns: auto 1fr auto;
min-width: 160px; grid-template-rows: auto;
padding: 5px 6px;
gap: 4px;
font-size: 10px;
} }
/* Re-flow the chip's grid so it's a single row of three: dot,
code, change. The 2-row layout (which had state/when on row 2)
is dropped along with the elements that lived there. */
.markets-bar .mkt .mkt__dot {
grid-row: 1; grid-column: 1;
width: 6px; height: 6px;
}
.markets-bar .mkt .mkt__name {
grid-row: 1; grid-column: 2;
font-size: 10px;
letter-spacing: 0.04em;
}
.markets-bar .mkt .mkt__index {
grid-row: 1; grid-column: 3;
font-size: 10px;
}
/* Strip the now-redundant content. The elements still render but
occupy no space so the chip stays narrow. */
.markets-bar .mkt__state,
.markets-bar .mkt__when,
.markets-bar .mkt__index-label,
.markets-bar .mkt__index-price { display: none; }
} }

View file

@ -51,8 +51,8 @@
<tr> <tr>
<th>Ticker</th> <th>Ticker</th>
<th>Name</th> <th>Name</th>
<th class="num">Qty</th> <th class="num mobile-hide">Qty</th>
<th class="num">Avg</th> <th class="num mobile-hide">Avg</th>
<th class="num">Last</th> <th class="num">Last</th>
<th class="num">P/L</th> <th class="num">P/L</th>
<th class="num">%</th> <th class="num">%</th>
@ -63,8 +63,8 @@
<tr> <tr>
<td class="label">{{ pos.ticker }}</td> <td class="label">{{ pos.ticker }}</td>
<td>{{ pos.name or "" }}</td> <td>{{ pos.name or "" }}</td>
<td class="num">{{ pos.quantity | price }}</td> <td class="num mobile-hide">{{ pos.quantity | price }}</td>
<td class="num neu">{{ pos.average_price | price }}</td> <td class="num neu mobile-hide">{{ pos.average_price | price }}</td>
<td class="num">{{ pos.current_price | price }}</td> <td class="num">{{ pos.current_price | price }}</td>
<td class="num {% if pos.ppl is none %}neu{% elif pos.ppl >= 0 %}pos{% else %}neg{% endif %}"> <td class="num {% if pos.ppl is none %}neu{% elif pos.ppl >= 0 %}pos{% else %}neg{% endif %}">
{{ pos.ppl | signed }} {{ pos.ppl | signed }}