fix(tablet): tighten layout for iPad + custom dropdown chevron
Operators run the Tablet Station on iPads (mostly landscape, sometimes portrait). The previous design pushed the dashboard panels below the fold on a 1024×768 viewport — meant a swipe before they could see their queue. Tightens spacing across the page without changing the visual language. What changed (all behind @media (max-width: 1180px)): - Page padding 24/32 → 16/20, gap between sections 24 → 16 - Hero title 32 → 24px, subtitle margin-top halved - KPI strip switches from auto-fit to fixed 6-column grid so all six KPIs stay on a single row instead of wrapping at iPad widths; per-tile padding 20 → 12/16, value font 44 → 24px, label 14 → 12px - Active WO banner padding 20 → 12/16 - Dashboard breakpoint to single-column lowered 1100 → 760px so iPad portrait still gets two columns of panels - Panel padding 20 → 16, panel-head padding-bottom 12 → 8 - Empty state padding 32/16 → 16/12 (the "All caught up" tile no longer eats 140px per panel) - Queue rows min-height 64 → 52, bake/gate rows 64 → 48 Station picker dropdown: - Native chevron suppressed via appearance: none and replaced with an inlined SVG arrow positioned with explicit right-edge inset. Stroke uses currentColor so it follows light/dark mode. - Right padding bumped from $fp-space-4 → $fp-space-7 to give the arrow breathing room — previously hugged the rounded corner. Station dropdown labels: - Append "(CODE)" after the name. The shop's five stations (Bake Oven Tablet / Inspection Kiosk / Plating Room Tablet 1 / Receiving Mobile / Shipping Desktop) all live in the same facility with no work_center, so without the code suffix the dropdown options looked similar at a glance. Bumped fusion_plating_shopfloor → 19.0.10.0.0. Asset bundle regenerated as bc28f73. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
{
|
||||
'name': 'Fusion Plating — Shop Floor',
|
||||
'version': '19.0.9.0.0',
|
||||
'version': '19.0.10.0.0',
|
||||
'category': 'Manufacturing/Plating',
|
||||
'summary': 'Shop-floor tablet stations, QR scanning, bake window enforcer, '
|
||||
'first-piece inspection gates.',
|
||||
|
||||
@@ -34,10 +34,14 @@
|
||||
padding: $fp-space-6 $fp-space-7;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $fp-space-6;
|
||||
gap: $fp-space-5;
|
||||
|
||||
@media (max-width: 900px) { padding: $fp-space-4; gap: $fp-space-4; }
|
||||
@media (max-width: 600px) { padding: $fp-space-3; gap: $fp-space-4; }
|
||||
// Tablet sweet spot — iPad landscape (1024) and portrait (768).
|
||||
// The goal is to fit Hero + KPIs + Active WO + the first row of
|
||||
// panels in a single 768-tall viewport.
|
||||
@media (max-width: 1180px) { padding: $fp-space-4 $fp-space-5; gap: $fp-space-4; }
|
||||
@media (max-width: 900px) { padding: $fp-space-4; gap: $fp-space-3; }
|
||||
@media (max-width: 600px) { padding: $fp-space-3; gap: $fp-space-3; }
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -62,12 +66,18 @@
|
||||
margin: 0;
|
||||
color: $fp-ink;
|
||||
display: flex; align-items: center; gap: $fp-space-3;
|
||||
|
||||
// Smaller hero on tablet — saves ~16px of vertical space without
|
||||
// losing the page identity.
|
||||
@media (max-width: 1180px) { font-size: $fp-text-xl; gap: $fp-space-2; }
|
||||
}
|
||||
.o_fp_tablet_subtitle {
|
||||
margin-top: $fp-space-2;
|
||||
font-size: $fp-text-sm;
|
||||
color: $fp-ink-mute;
|
||||
display: flex; flex-wrap: wrap; gap: $fp-space-3; align-items: center;
|
||||
|
||||
@media (max-width: 1180px) { margin-top: $fp-space-1; }
|
||||
}
|
||||
.o_fp_tablet_chip {
|
||||
display: inline-flex;
|
||||
@@ -93,7 +103,10 @@
|
||||
.o_fp_station_picker {
|
||||
min-width: 240px;
|
||||
min-height: $fp-touch-min;
|
||||
padding: $fp-space-2 $fp-space-4;
|
||||
// Reserve room on the right so the custom chevron has breathing
|
||||
// space between itself and the rounded corner — the native arrow
|
||||
// hugs the edge in Odoo's frame, which looked cramped on iPad.
|
||||
padding: $fp-space-2 $fp-space-7 $fp-space-2 $fp-space-4;
|
||||
border: 1px solid #{$fp-border};
|
||||
border-radius: $fp-radius-md;
|
||||
background-color: $fp-card;
|
||||
@@ -103,6 +116,20 @@
|
||||
cursor: pointer;
|
||||
transition: box-shadow $fp-dur $fp-ease, border-color $fp-dur $fp-ease;
|
||||
|
||||
// Suppress the browser's native chevron and paint our own. The
|
||||
// SVG is inlined (data URL) so it renders crisply at any DPI and
|
||||
// doesn't trigger an extra HTTP request. Stroke uses currentColor
|
||||
// so it follows light/dark mode automatically.
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='currentColor' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'><polyline points='1 1.5 6 6.5 11 1.5'/></svg>");
|
||||
background-repeat: no-repeat;
|
||||
// Inset from the right edge so the chevron sits inside the
|
||||
// padded zone, not flush with the border radius.
|
||||
background-position: right $fp-space-4 center;
|
||||
background-size: 12px 8px;
|
||||
|
||||
&:focus { @include fp-focus-ring; border-color: $fp-accent; }
|
||||
@media (max-width: 600px) { min-width: 0; width: 100%; }
|
||||
}
|
||||
@@ -205,6 +232,16 @@
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
gap: $fp-space-4;
|
||||
|
||||
// iPad landscape (1024) — six 130px tiles + gaps fit on one row.
|
||||
// Keeps the KPI strip a single line so the dashboard can stay above
|
||||
// the fold.
|
||||
@media (max-width: 1180px) {
|
||||
grid-template-columns: repeat(6, minmax(0, 1fr));
|
||||
gap: $fp-space-3;
|
||||
}
|
||||
@media (max-width: 820px) {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: $fp-space-3;
|
||||
@@ -220,6 +257,15 @@
|
||||
display: flex; flex-direction: column; gap: $fp-space-2;
|
||||
transition: transform $fp-dur $fp-ease, box-shadow $fp-dur $fp-ease;
|
||||
|
||||
@media (max-width: 1180px) {
|
||||
padding: $fp-space-3 $fp-space-4;
|
||||
gap: $fp-space-1;
|
||||
.o_fp_kpi_value { font-size: $fp-text-xl; }
|
||||
.o_fp_kpi_label { font-size: $fp-text-xs; }
|
||||
// Pull the status dot in so it doesn't crowd small tiles
|
||||
&::after { top: $fp-space-3; right: $fp-space-3; width: 8px; height: 8px; }
|
||||
}
|
||||
|
||||
@include fp-hover-only {
|
||||
&:hover {
|
||||
transform: translateY(-2px);
|
||||
@@ -286,6 +332,7 @@
|
||||
box-shadow: $fp-elev-1;
|
||||
color: $fp-ink;
|
||||
|
||||
@media (max-width: 1180px) { padding: $fp-space-3 $fp-space-4; }
|
||||
@media (max-width: 600px) {
|
||||
flex-direction: column; align-items: stretch;
|
||||
> .btn { width: 100%; min-height: $fp-touch-min; }
|
||||
@@ -327,12 +374,17 @@
|
||||
grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
|
||||
gap: $fp-space-5;
|
||||
|
||||
@media (max-width: 1100px) { grid-template-columns: 1fr; }
|
||||
@media (max-width: 600px) { gap: $fp-space-3; }
|
||||
// Keep the two-column layout down to iPad portrait (768) so the
|
||||
// queue and the bath/bake panels stay side-by-side instead of
|
||||
// stacking. Below that the single-column layout still kicks in.
|
||||
@media (max-width: 1180px) { gap: $fp-space-3; }
|
||||
@media (max-width: 760px) { grid-template-columns: 1fr; }
|
||||
@media (max-width: 600px) { gap: $fp-space-3; }
|
||||
}
|
||||
.o_fp_right_col {
|
||||
display: flex; flex-direction: column; gap: $fp-space-5;
|
||||
@media (max-width: 600px) { gap: $fp-space-3; }
|
||||
display: flex; flex-direction: column; gap: $fp-space-4;
|
||||
@media (max-width: 1180px) { gap: $fp-space-3; }
|
||||
@media (max-width: 600px) { gap: $fp-space-3; }
|
||||
}
|
||||
|
||||
|
||||
@@ -345,7 +397,8 @@
|
||||
border-radius: $fp-radius-lg;
|
||||
box-shadow: $fp-elev-1;
|
||||
padding: $fp-space-5;
|
||||
@media (max-width: 600px) { padding: $fp-space-4; }
|
||||
@media (max-width: 1180px) { padding: $fp-space-4; }
|
||||
@media (max-width: 600px) { padding: $fp-space-4; }
|
||||
}
|
||||
.o_fp_panel_head {
|
||||
display: flex;
|
||||
@@ -355,6 +408,14 @@
|
||||
padding-bottom: $fp-space-3;
|
||||
border-bottom: 1px solid #{$fp-border};
|
||||
|
||||
@media (max-width: 1180px) {
|
||||
margin-bottom: $fp-space-3;
|
||||
padding-bottom: $fp-space-2;
|
||||
h3 { font-size: $fp-text-base;
|
||||
> .fa { width: 28px; height: 28px; font-size: 0.85rem; }
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: $fp-text-lg;
|
||||
font-weight: $fp-weight-bold;
|
||||
@@ -402,6 +463,15 @@
|
||||
opacity: 0.5;
|
||||
margin-bottom: $fp-space-3;
|
||||
}
|
||||
|
||||
// On tablet, the "All caught up" state was eating ~140px of
|
||||
// vertical space per panel. Halve it so the dashboard stays
|
||||
// dense even when one or two panels are empty.
|
||||
@media (max-width: 1180px) {
|
||||
padding: $fp-space-4 $fp-space-3;
|
||||
font-size: $fp-text-sm;
|
||||
i.fa { font-size: 1.75rem; margin-bottom: $fp-space-2; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -422,6 +492,12 @@
|
||||
border-radius: $fp-radius-md;
|
||||
background-color: $fp-card;
|
||||
min-height: 64px;
|
||||
|
||||
@media (max-width: 1180px) {
|
||||
grid-template-columns: 36px 1fr auto;
|
||||
padding: $fp-space-2 $fp-space-3;
|
||||
min-height: 52px;
|
||||
}
|
||||
transition: background-color $fp-dur $fp-ease,
|
||||
border-color $fp-dur $fp-ease,
|
||||
box-shadow $fp-dur $fp-ease,
|
||||
@@ -463,6 +539,8 @@
|
||||
font-size: 0.72rem;
|
||||
letter-spacing: 0.04em;
|
||||
|
||||
@media (max-width: 1180px) { width: 32px; height: 32px; }
|
||||
|
||||
&[data-priority="high"] { @include fp-pill(--bs-danger); }
|
||||
&[data-priority="med"] { @include fp-pill(--bs-warning); }
|
||||
&[data-priority="low"] { background-color: $fp-card-soft; color: $fp-ink-mute; }
|
||||
@@ -561,6 +639,12 @@
|
||||
border-radius: $fp-radius-md;
|
||||
background-color: $fp-card;
|
||||
min-height: 64px;
|
||||
|
||||
@media (max-width: 1180px) {
|
||||
padding: $fp-space-2 $fp-space-3;
|
||||
min-height: 48px;
|
||||
gap: $fp-space-2;
|
||||
}
|
||||
transition: box-shadow $fp-dur $fp-ease, border-color $fp-dur $fp-ease;
|
||||
|
||||
@include fp-hover-only { &:hover { box-shadow: $fp-elev-2; } }
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
<option t-att-value="s.id"
|
||||
t-att-selected="state.stationId === s.id">
|
||||
<t t-esc="s.name"/>
|
||||
<t t-if="s.code"> (<t t-esc="s.code"/>)</t>
|
||||
<t t-if="s.work_center"> · <t t-esc="s.work_center"/></t>
|
||||
</option>
|
||||
</t>
|
||||
|
||||
Reference in New Issue
Block a user