Skip to content
CodeAtlas UI

Feedback

Progress

A linear progress bar with determinate values, an indeterminate animation and an accessible label.

<script>
  import { Progress } from "@codeatlasdev/ui";
</script>

<Progress value={60} label="Upload progress" />
<Progress indeterminate label="Loading" />

Renders role="progressbar" with aria-valuenow, aria-valuemin and aria-valuemax. Always pass label so screen readers know what is progressing. The indeterminate state omits aria-valuenow.

Determinate

An explicit value from 0 to max (100 by default).

25%
50%
75%
100%
Code
svelte
<script lang="ts">
  import { Progress } from '@codeatlasdev/ui';
</script>

<div class="col">
  {#each [25, 50, 75, 100] as v}
    <div class="row">
      <span class="label">{v}%</span>
      <Progress value={v} label="{v} percent" />
    </div>
  {/each}
</div>

<style>
  .col { display: flex; flex-direction: column; gap: 16px; width: 100%; max-width: 480px; }
  .row { display: flex; align-items: center; gap: 14px; }
  .label {
    font-size: var(--ca-font-size-caption);
    font-family: var(--ca-font-mono);
    color: var(--ca-text-secondary);
    min-width: 64px;
    flex-shrink: 0;
    text-align: right;
  }
</style>

Indeterminate

Use when progress cannot be determined.

Loading
Syncing
Code
svelte
<script lang="ts">
  import { Progress } from '@codeatlasdev/ui';
</script>

<div class="col">
  <div class="row">
    <span class="label">Loading</span>
    <Progress indeterminate label="Loading content" />
  </div>
  <div class="row">
    <span class="label">Syncing</span>
    <Progress indeterminate label="Syncing data" />
  </div>
</div>

<style>
  .col { display: flex; flex-direction: column; gap: 16px; width: 100%; max-width: 480px; }
  .row { display: flex; align-items: center; gap: 14px; }
  .label {
    font-size: var(--ca-font-size-caption);
    font-family: var(--ca-font-mono);
    color: var(--ca-text-secondary);
    min-width: 64px;
    flex-shrink: 0;
    text-align: right;
  }
</style>

Animated

Start a simulated upload.

0%
Code
svelte
<script lang="ts">
  import { Progress, Button } from '@codeatlasdev/ui';
  import { onDestroy } from 'svelte';

  let value = $state(0);
  let running = $state(false);
  let timer: ReturnType<typeof setInterval> | undefined;

  function start() {
    if (running) return;
    value = 0;
    running = true;
    timer = setInterval(() => {
      value = Math.min(100, value + 5);
      if (value >= 100) {
        clearInterval(timer);
        running = false;
      }
    }, 100);
  }

  onDestroy(() => clearInterval(timer));
</script>

<div class="col">
  <div class="row">
    <span class="label">{value}%</span>
    <Progress {value} label="Upload progress" />
  </div>
  <Button variant="outlined" size="sm" disabled={running} onclick={start}>
    {running ? 'Uploading…' : 'Start upload'}
  </Button>
</div>

<style>
  .col { display: flex; flex-direction: column; gap: 16px; width: 100%; max-width: 480px; }
  .row { display: flex; align-items: center; gap: 14px; }
  .label {
    font-size: var(--ca-font-size-caption);
    font-family: var(--ca-font-mono);
    color: var(--ca-text-secondary);
    min-width: 64px;
    flex-shrink: 0;
    text-align: right;
  }
</style>

Props

PropTypeDefaultDescription
valuenumber0Current progress value.
maxnumber100Maximum value. The fill is clamped between 0 and 100%.
indeterminatebooleanfalsePlays the shimmer animation when progress is unknown.
labelstring–Accessible aria-label for screen readers.
classstring''Extra CSS classes.