feat(portale): progress bar compatta, meno altezza
Segue il mock design-reference/Client-Portal-Progress-Bar: "Step N" e lo stato passano sulla stessa riga, il titolo fase resta sotto — due righe di testo invece di tre — e il padding del contenitore scende da py-8 a py-3. Altezza della sezione da ~147px a ~90px. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,10 @@ const statusWordClass: Record<"upcoming" | "active" | "done", string> = {
|
||||
* Horizontal milestone stepper — replica del "STEP PROGRESS TIMELINE" del mock.
|
||||
* Un nodo per fase reale (non 5 fissi); la linea di fondo si riempie in base a
|
||||
* global_progress_pct.
|
||||
*
|
||||
* Layout compatto (design-reference/Client-Portal-Progress-Bar): il nodo occupa
|
||||
* due righe di testo — "Step N" e lo stato sulla stessa riga, il titolo fase
|
||||
* sotto — con padding ridotto, così la barra ruba poca altezza alla dashboard.
|
||||
*/
|
||||
export function MilestoneStepper({
|
||||
phases,
|
||||
@@ -29,10 +33,10 @@ export function MilestoneStepper({
|
||||
if (phases.length === 0) return null;
|
||||
|
||||
return (
|
||||
<div className="bg-card border-b border-border-light py-8 px-6">
|
||||
<div className="bg-card border-b border-border-light px-6 py-3">
|
||||
<div className="relative mx-auto max-w-[1200px]">
|
||||
{/* Linea di connessione + riempimento dinamico */}
|
||||
<div className="absolute left-[5%] right-[5%] top-[15px] z-0 h-1 rounded-full bg-muted">
|
||||
{/* Linea di connessione + riempimento dinamico (centrata sui cerchi) */}
|
||||
<div className="absolute left-[5%] right-[5%] top-[14px] z-0 h-1 rounded-full bg-muted">
|
||||
<div
|
||||
className="h-full rounded-full bg-primary transition-[width] duration-500 ease-[cubic-bezier(0.4,0,0.2,1)]"
|
||||
style={{ width: `${globalProgress}%` }}
|
||||
@@ -41,13 +45,13 @@ export function MilestoneStepper({
|
||||
|
||||
{/* Nodi milestone */}
|
||||
<div
|
||||
className="relative z-10 grid gap-4"
|
||||
className="relative z-10 grid gap-3"
|
||||
style={{ gridTemplateColumns: `repeat(${phases.length}, minmax(0, 1fr))` }}
|
||||
>
|
||||
{phases.map((phase, i) => {
|
||||
const s = phase.status;
|
||||
return (
|
||||
<div key={phase.id} className="flex flex-col items-center text-center">
|
||||
<div key={phase.id} className="flex min-w-0 flex-col items-center text-center">
|
||||
<div
|
||||
className={
|
||||
"flex h-8 w-8 items-center justify-center rounded-full border-4 border-card text-xs font-bold shadow-md transition-all " +
|
||||
@@ -60,20 +64,24 @@ export function MilestoneStepper({
|
||||
>
|
||||
{s === "done" ? "✓" : i + 1}
|
||||
</div>
|
||||
<span
|
||||
className={
|
||||
"mt-2 text-[11px] font-bold " +
|
||||
(s === "upcoming" ? "text-muted-foreground" : "text-foreground")
|
||||
}
|
||||
>
|
||||
Step {i + 1}
|
||||
</span>
|
||||
<span className="text-[10px] font-medium text-muted-foreground line-clamp-1">
|
||||
<div className="mt-1.5 flex max-w-full items-baseline gap-1.5">
|
||||
<span
|
||||
className={
|
||||
"text-[11px] font-bold leading-tight " +
|
||||
(s === "upcoming" ? "text-muted-foreground" : "text-foreground")
|
||||
}
|
||||
>
|
||||
Step {i + 1}
|
||||
</span>
|
||||
<span
|
||||
className={`truncate text-[9px] font-bold uppercase leading-tight tracking-wide ${statusWordClass[s]}`}
|
||||
>
|
||||
{statusWord[s]}
|
||||
</span>
|
||||
</div>
|
||||
<span className="max-w-full truncate text-[10px] font-medium leading-tight text-muted-foreground">
|
||||
{phase.title}
|
||||
</span>
|
||||
<span className={`mt-1 text-[9px] font-bold uppercase ${statusWordClass[s]}`}>
|
||||
{statusWord[s]}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user