# Barras de progreso

> Lineal, indeterminada, radial y segmentada.

Categoría: Estado & Progreso · Solar v0.8.0

Usa este HTML tal cual, con Tailwind y ccs-tailwind-config.js cargados (ver https://utiliza.me/solar/instalacion.html).

## Guía: Cuándo usarlo

- Determinada cuando se conoce el avance; indeterminada cuando no se sabe cuánto falta.
- Bajo 1 segundo no va indicador: basta que el botón cambie de estado.
- Entre 2 y 10 segundos, la indeterminada. De 10 segundos en adelante, la determinada con su porcentaje.
- Radial para una cifra sola en poco espacio; lineal cuando va con etiqueta, dentro de una lista.
- Si lo que avanza es un formulario de varios pasos, el indicador es otro: ve Stepper.

Por qué: Los tiempos vienen de NN/G: pasados los 10 segundos una barra indeterminada deja de servir, porque nadie distingue si el sistema sigue trabajando o se colgó, y ahí hace falta saber cuánto queda.
NN/G recomienda además contar pasos antes que mostrar un porcentaje cuando se puede («3 de 50»): un porcentaje no dice cuánto trabajo es lo que falta.

## Lineal · determinada

La forma por defecto. Lleva siempre una etiqueta y el valor en texto: la barra sola no dice de qué es ni cuánto queda.

```html
<div>
  <div class="space-y-5">
    <div>
      <div class="flex items-center justify-between mb-2 text-sm">
        <span class="font-medium">Perfil de empresa</span>
        <span class="mono text-ccs-slate dark:text-ccs-dark-text-2">25%</span>
      </div>
      <div class="h-2 rounded-full bg-ccs-bg overflow-hidden dark:bg-ccs-dark-overlay" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="25" aria-label="Perfil de empresa">
        <div class="h-full bg-ccs-blue rounded-full dark:bg-ccs-dark-accent" style="width:25%"></div>
      </div>
    </div>
    <div>
      <div class="flex items-center justify-between mb-2 text-sm">
        <span class="font-medium">Documentos legales</span>
        <span class="mono text-ccs-slate dark:text-ccs-dark-text-2">62%</span>
      </div>
      <div class="h-2 rounded-full bg-ccs-bg overflow-hidden dark:bg-ccs-dark-overlay" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="62" aria-label="Documentos legales">
        <div class="h-full bg-ccs-blue rounded-full dark:bg-ccs-dark-accent" style="width:62%"></div>
      </div>
    </div>
    <div>
      <div class="flex items-center justify-between mb-2 text-sm">
        <span class="font-medium">Inscripción a comités</span>
        <span class="mono text-ccs-success dark:text-ccs-dark-success">100% · completado</span>
      </div>
      <div class="h-2 rounded-full bg-ccs-bg overflow-hidden dark:bg-ccs-dark-overlay" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="100" aria-valuetext="100%, completado" aria-label="Inscripción a comités">
        <div class="h-full bg-ccs-green rounded-full" style="width:100%"></div>
      </div>
    </div>
    <div>
      <div class="flex items-center justify-between mb-2 text-sm">
        <span class="font-medium">Migración de datos</span>
        <span class="mono text-ccs-slate dark:text-ccs-dark-text-2">78%</span>
      </div>
      <div class="h-3 rounded-full bg-ccs-bg overflow-hidden dark:bg-ccs-dark-overlay" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="78" aria-label="Migración de datos">
        <div class="h-full bg-ccs-banner rounded-full dark:bg-ccs-banner-dark" style="width:78%"></div>
      </div>
    </div>
    <div>
      <div class="text-sm font-medium mb-2">Carga de archivo · contrato-anexo.pdf</div>
      <div class="h-6 rounded-full bg-ccs-bg overflow-hidden relative dark:bg-ccs-dark-overlay" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="43" aria-valuetext="2,1 de 4,8 MB" aria-label="Carga de archivo · contrato-anexo.pdf">
        <div class="h-full bg-ccs-blue rounded-full flex items-center justify-end pr-3 dark:bg-ccs-blue-mid" style="width:43%">
          <span class="text-xs mono text-white font-medium">2.1 / 4.8 MB</span>
        </div>
      </div>
    </div>
  </div>
</div>
```

## Lineal · indeterminada

Entre 2 y 10 segundos, cuando no se puede calcular el avance. Si la espera puede pasar de 10 segundos, usa la determinada.

```html
<div>
  <div class="space-y-4">
    <div>
      <div class="text-sm text-ccs-slate mb-2 dark:text-ccs-dark-text-2">Sincronizando con la base de datos…</div>
      <div class="h-1.5 rounded-full bg-ccs-bg overflow-hidden relative dark:bg-ccs-dark-overlay" role="progressbar" aria-label="Sincronizando con la base de datos…">
        <div class="ccs-progress-indet"></div>
      </div>
    </div>
    <div>
      <div class="text-sm text-ccs-slate mb-2 dark:text-ccs-dark-text-2">Procesando solicitud…</div>
      <div class="h-1 bg-ccs-bg overflow-hidden relative dark:bg-ccs-dark-overlay" role="progressbar" aria-label="Procesando solicitud…">
        <div class="ccs-progress-indet"></div>
      </div>
    </div>
  </div>
</div>
```

## Radial · determinada

Una cifra sola en poco espacio, como una tarjeta de resumen. Con varias medidas en una lista, la lineal se compara mejor.

```html
<div>
  <div class="flex flex-wrap items-center gap-8">
    <div class="flex flex-col items-center gap-2">
      <div class="relative w-20 h-20" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="25" aria-label="Perfil">
        <svg aria-hidden="true" class="w-20 h-20 -rotate-90" viewBox="0 0 100 100">
          <circle cx="50" cy="50" r="42" fill="none" class="stroke-ccs-line dark:stroke-ccs-dark-line" stroke-width="10"/>
          <circle cx="50" cy="50" r="42" fill="none" class="stroke-ccs-blue dark:stroke-ccs-dark-accent" stroke-width="10" stroke-linecap="round" stroke-dasharray="263.9" stroke-dashoffset="197.9"/>
        </svg>
        <div class="absolute inset-0 grid place-items-center text-sm font-semibold">25%</div>
      </div>
      <div class="text-xs text-ccs-slate dark:text-ccs-dark-text-2">Perfil</div>
    </div>
    <div class="flex flex-col items-center gap-2">
      <div class="relative w-20 h-20" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="62" aria-label="Docs">
        <svg aria-hidden="true" class="w-20 h-20 -rotate-90" viewBox="0 0 100 100">
          <circle cx="50" cy="50" r="42" fill="none" class="stroke-ccs-line dark:stroke-ccs-dark-line" stroke-width="10"/>
          <circle cx="50" cy="50" r="42" fill="none" class="stroke-ccs-blue dark:stroke-ccs-dark-accent" stroke-width="10" stroke-linecap="round" stroke-dasharray="263.9" stroke-dashoffset="100.3"/>
        </svg>
        <div class="absolute inset-0 grid place-items-center text-sm font-semibold">62%</div>
      </div>
      <div class="text-xs text-ccs-slate dark:text-ccs-dark-text-2">Docs</div>
    </div>
    <div class="flex flex-col items-center gap-2">
      <div class="relative w-20 h-20" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="100" aria-valuetext="Listo, 100%" aria-label="Inscripción">
        <svg aria-hidden="true" class="w-20 h-20 -rotate-90" viewBox="0 0 100 100">
          <circle cx="50" cy="50" r="42" fill="none" class="stroke-ccs-line dark:stroke-ccs-dark-line" stroke-width="10"/>
          <circle cx="50" cy="50" r="42" fill="none" class="stroke-ccs-green dark:stroke-ccs-green-br" stroke-width="10" stroke-linecap="round" stroke-dasharray="263.9" stroke-dashoffset="0"/>
        </svg>
        <div class="absolute inset-0 grid place-items-center text-ccs-success dark:text-ccs-dark-success">
          <svg class="w-7 h-7" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="m5 12 5 5L20 7"/></svg>
        </div>
      </div>
      <div class="text-xs text-ccs-slate dark:text-ccs-dark-text-2">Listo</div>
    </div>
    <div class="flex flex-col items-center gap-2">
      <div class="relative w-32 h-32" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="74" aria-label="Onboarding">
        <svg aria-hidden="true" class="w-32 h-32 -rotate-90" viewBox="0 0 100 100">
          <circle cx="50" cy="50" r="44" fill="none" class="stroke-ccs-line dark:stroke-ccs-dark-line" stroke-width="8"/>
          <circle cx="50" cy="50" r="44" fill="none" class="stroke-ccs-blue dark:stroke-ccs-dark-accent" stroke-width="8" stroke-linecap="round" stroke-dasharray="276.5" stroke-dashoffset="71.9"/>
        </svg>
        <div class="absolute inset-0 flex flex-col items-center justify-center">
          <div class="text-2xl font-semibold leading-none">74%</div>
          <div class="text-xs uppercase tracking-wider text-ccs-slate mt-1 dark:text-ccs-dark-text-2">Onboarding</div>
        </div>
      </div>
    </div>
    <div class="flex flex-col items-center gap-2">
      <div class="relative w-20 h-20" role="progressbar" aria-label="Cargando…">
        <svg aria-hidden="true" class="w-20 h-20 ccs-spin" viewBox="0 0 100 100">
          <circle cx="50" cy="50" r="42" fill="none" class="stroke-ccs-line dark:stroke-ccs-dark-line" stroke-width="8"/>
          <circle cx="50" cy="50" r="42" fill="none" class="stroke-ccs-blue dark:stroke-ccs-dark-accent" stroke-width="8" stroke-linecap="round" stroke-dasharray="263.9" stroke-dashoffset="180"/>
        </svg>
      </div>
      <div class="text-xs text-ccs-slate dark:text-ccs-dark-text-2">Cargando…</div>
    </div>
  </div>
</div>
```

## Segmentada · multi-categoría

Muestra la composición de un total, no un avance: cada tramo es una categoría y la suma es el 100 %.

```html
<div>
  <div class="flex items-center justify-between mb-3 text-sm">
    <span class="font-medium">Distribución de socios por sector</span>
    <span class="mono text-ccs-slate dark:text-ccs-dark-text-2">3.420 socios</span>
  </div>
  <div class="h-3 rounded-full overflow-hidden flex" role="img" aria-label="Retail 38%, Servicios 24%, Logística 18%, TI 12%, Otros 8%">
    <div class="bg-ccs-blue dark:bg-ccs-dark-accent" style="width:38%"></div>
    <div class="bg-ccs-blue-light" style="width:24%"></div>
    <div class="bg-ccs-green" style="width:18%"></div>
    <div class="bg-ccs-green-br" style="width:12%"></div>
    <div class="bg-ccs-slate" style="width:8%"></div>
  </div>
  <div class="mt-4 flex flex-wrap gap-x-6 gap-y-2 text-xs">
    <span class="inline-flex items-center gap-2"><span class="w-2.5 h-2.5 rounded-none bg-ccs-blue dark:bg-ccs-dark-accent"></span>Retail 38%</span>
    <span class="inline-flex items-center gap-2"><span class="w-2.5 h-2.5 rounded-none bg-ccs-blue-light"></span>Servicios 24%</span>
    <span class="inline-flex items-center gap-2"><span class="w-2.5 h-2.5 rounded-none bg-ccs-green"></span>Logística 18%</span>
    <span class="inline-flex items-center gap-2"><span class="w-2.5 h-2.5 rounded-none bg-ccs-green-br"></span>TI 12%</span>
    <span class="inline-flex items-center gap-2"><span class="w-2.5 h-2.5 rounded-none bg-ccs-slate"></span>Otros 8%</span>
  </div>
</div>
```

## Guía: Comportamiento

- El marcado declara el avance: role="progressbar", aria-valuemin, aria-valuemax y aria-valuenow, más aria-valuetext cuando lo que se muestra no es un porcentaje. La indeterminada lleva el rol y el nombre, sin aria-valuenow.
- El ancho lo fija el proyecto desde JavaScript. En los ejemplos va escrito en el HTML para que la barra se vea llena.
- No se usa <progress>: no toma los colores de Solar y cambia entre navegadores.

Por qué: Un atributo style en el HTML lo bloquean las políticas de seguridad de contenido (CSP) más usadas, así que en producción el ancho se escribe desde el script.
Es el mismo motivo por el que las casillas y los radios no usan el control del navegador: lo que Solar no puede pintar con sus tokens, no lo usa.
