fix(portal): align stepper labels with circles via per-unit absolute positioning
Original macro put the 5 labels in a separate flex container below the
stepper with flex:1 each. That distributes them at 10%/30%/50%/70%/90%
(centred in 1/5 slots) while the circles distribute at 0%/25%/50%/75%/
100% (edges via space-between + line-flex). Result: labels visibly off
from their circles, getting worse the wider the row.
Restructured the macro so each circle + its label live inside a single
.o_fp_step_unit. The label is absolute-positioned at top:100% / left:50%
with translateX(-50%), so its horizontal centre always pins to the
circle's centre regardless of text width. Wider labels ('Inspected')
overflow equally to both sides instead of pushing the column.
Bumped stepper margin-bottom to 2.4rem so the absolutely-positioned
labels have clearance below. Dropped the now-unused .o_fp_step_labels
container rule.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,19 @@
|
||||
.o_fp_stepper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: .35rem;
|
||||
// Bottom space for the absolutely-positioned labels below each circle.
|
||||
// ~2.2rem covers two short lines (title + time_label).
|
||||
margin-bottom: 2.4rem;
|
||||
|
||||
// Each unit holds one circle + its label. The label is absolutely
|
||||
// positioned (see .o_fp_step_label below) so its horizontal centre
|
||||
// lines up with the circle's centre even when text is wider than 24px.
|
||||
.o_fp_step_unit {
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.o_fp_step_circle {
|
||||
width: 24px;
|
||||
@@ -20,7 +32,6 @@
|
||||
font-family: $fp-font;
|
||||
font-size: .65rem;
|
||||
font-weight: 700;
|
||||
flex-shrink: 0;
|
||||
background: $fp-card-bg;
|
||||
border: 1.5px solid $fp-card-border;
|
||||
color: $fp-muted-light;
|
||||
@@ -58,6 +69,40 @@
|
||||
&.o_fp_step_line_done { background: $fp-teal; }
|
||||
&.o_fp_step_line_warn { background: $fp-amber; }
|
||||
}
|
||||
|
||||
// Label centred on its circle via absolute positioning. Wider text
|
||||
// ("Inspected") overflows equally left + right instead of pushing
|
||||
// the column or sitting in a separate flex slot.
|
||||
.o_fp_step_label {
|
||||
position: absolute;
|
||||
top: calc(100% + .45rem);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
font-size: .68rem;
|
||||
|
||||
.o_fp_step_label_title {
|
||||
color: $fp-muted-light;
|
||||
font-weight: 500;
|
||||
}
|
||||
.o_fp_step_label_time {
|
||||
color: $fp-disabled;
|
||||
font-size: .6rem;
|
||||
}
|
||||
&.o_fp_step_label_done {
|
||||
.o_fp_step_label_title { color: $fp-text-body; }
|
||||
.o_fp_step_label_time { color: $fp-muted-light; }
|
||||
}
|
||||
&.o_fp_step_label_active {
|
||||
.o_fp_step_label_title { color: $fp-teal; font-weight: 700; }
|
||||
.o_fp_step_label_time { color: $fp-teal; }
|
||||
}
|
||||
&.o_fp_step_label_active_warn {
|
||||
.o_fp_step_label_title { color: $fp-amber-text; font-weight: 700; }
|
||||
.o_fp_step_label_time { color: $fp-amber-text; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pulsing glow for the active step indicator. Kept subtle - the ring
|
||||
@@ -83,34 +128,5 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Step labels row below the stepper
|
||||
.o_fp_step_labels {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: .68rem;
|
||||
|
||||
.o_fp_step_label {
|
||||
text-align: center;
|
||||
flex: 1;
|
||||
.o_fp_step_label_title {
|
||||
color: $fp-muted-light;
|
||||
font-weight: 500;
|
||||
}
|
||||
.o_fp_step_label_time {
|
||||
color: $fp-disabled;
|
||||
font-size: .6rem;
|
||||
}
|
||||
&.o_fp_step_label_done {
|
||||
.o_fp_step_label_title { color: $fp-text-body; }
|
||||
.o_fp_step_label_time { color: $fp-muted-light; }
|
||||
}
|
||||
&.o_fp_step_label_active {
|
||||
.o_fp_step_label_title { color: $fp-teal; font-weight: 700; }
|
||||
.o_fp_step_label_time { color: $fp-teal; }
|
||||
}
|
||||
&.o_fp_step_label_active_warn {
|
||||
.o_fp_step_label_title { color: $fp-amber-text; font-weight: 700; }
|
||||
.o_fp_step_label_time { color: $fp-amber-text; }
|
||||
}
|
||||
}
|
||||
}
|
||||
// Legacy .o_fp_step_labels container removed — labels are now nested
|
||||
// inside each .o_fp_step_unit (see above) so they centre on their circle.
|
||||
|
||||
@@ -27,17 +27,29 @@
|
||||
<t t-set="active_state" t-value="active_state or 'normal'"/>
|
||||
<div class="o_fp_stepper">
|
||||
<t t-foreach="steps" t-as="step">
|
||||
<!-- circle -->
|
||||
<div t-attf-class="o_fp_step_circle #{
|
||||
'o_fp_step_done' if step['status'] == 'done' else
|
||||
(('o_fp_step_active_warn' if active_state == 'warn' else 'o_fp_step_active') if step['status'] == 'active' else '')
|
||||
}">
|
||||
<t t-if="step['status'] == 'done'">✓</t>
|
||||
<t t-elif="step['status'] in ('active', 'pending')">
|
||||
<t t-out="step_index + 1"/>
|
||||
</t>
|
||||
<!-- Unit = circle + its label stacked. Label is absolutely
|
||||
positioned below the circle (in SCSS) so its horizontal
|
||||
centre lines up with the circle no matter how wide the
|
||||
text is — fixes the column-vs-edge distribution
|
||||
mismatch we had with a separate labels row. -->
|
||||
<div class="o_fp_step_unit">
|
||||
<div t-attf-class="o_fp_step_circle #{
|
||||
'o_fp_step_done' if step['status'] == 'done' else
|
||||
(('o_fp_step_active_warn' if active_state == 'warn' else 'o_fp_step_active') if step['status'] == 'active' else '')
|
||||
}">
|
||||
<t t-if="step['status'] == 'done'">✓</t>
|
||||
<t t-elif="step['status'] in ('active', 'pending')">
|
||||
<t t-out="step_index + 1"/>
|
||||
</t>
|
||||
</div>
|
||||
<div t-attf-class="o_fp_step_label #{
|
||||
'o_fp_step_label_done' if step['status'] == 'done' else
|
||||
(('o_fp_step_label_active_warn' if active_state == 'warn' else 'o_fp_step_label_active') if step['status'] == 'active' else '')
|
||||
}">
|
||||
<div class="o_fp_step_label_title" t-out="step['label']"/>
|
||||
<div class="o_fp_step_label_time" t-out="step.get('time_label') or ''"/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- connecting line (omit after last circle) -->
|
||||
<t t-if="not step_last">
|
||||
<div t-attf-class="o_fp_step_line #{
|
||||
'o_fp_step_line_done' if step['status'] == 'done' else
|
||||
@@ -46,18 +58,6 @@
|
||||
</t>
|
||||
</t>
|
||||
</div>
|
||||
<!-- Labels under -->
|
||||
<div class="o_fp_step_labels">
|
||||
<t t-foreach="steps" t-as="step">
|
||||
<div t-attf-class="o_fp_step_label #{
|
||||
'o_fp_step_label_done' if step['status'] == 'done' else
|
||||
(('o_fp_step_label_active_warn' if active_state == 'warn' else 'o_fp_step_label_active') if step['status'] == 'active' else '')
|
||||
}">
|
||||
<div class="o_fp_step_label_title" t-out="step['label']"/>
|
||||
<div class="o_fp_step_label_time" t-out="step.get('time_label') or ''"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- ================================================================== -->
|
||||
|
||||
Reference in New Issue
Block a user