# Progress bar

- Entry point: `@koobiq/components/progress-bar`
- NgModule: `KbqProgressBarModule`
- Page: https://koobiq.io/en/components/progress-bar/overview

## Overview

`<kbq-progress-bar>` is a component that displays a progress indicator.

### Simple progress bar

A `<kbq-progress-bar>` element can be used on its own to create a horizontal progress line with koobiq theme

```html
<kbq-progress-bar></kbq-progress-bar>
```

### Props

#### value

Displaying length of progress bar depends on this property\
The range of value is \[0, 100]\
Default: 0

This will fill 30% of the whole progress bar:

```html
<kbq-progress-bar [value]="30"></kbq-progress-bar>
```

Values outside the range are clamped, and the property is ignored in indeterminate mode.

**Example: Progress bar** (`progress-bar-overview`)

```ts progress-bar-overview-example.ts
import { ChangeDetectionStrategy, Component, model } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { KbqInputModule } from '@koobiq/components/input';
import { KbqProgressBarModule } from '@koobiq/components/progress-bar';

@Component({
    selector: 'progress-bar-overview-example',
    imports: [
        KbqProgressBarModule,
        KbqInputModule,
        FormsModule
    ],
    template: `
        <kbq-progress-bar class="example-progress-bar" [value]="percent()" />
        <kbq-form-field>
            <input kbqInput kbqNumberInput [min]="0" [max]="100" [step]="5" [(ngModel)]="percent" />
            <kbq-stepper />
        </kbq-form-field>
    `,
    styles: `
        .example-progress-bar {
            margin-bottom: var(--kbq-size-m);
        }
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ProgressBarOverviewExample {
    readonly percent = model(30);
}
```

#### mode

Enum ('determinate', 'indeterminate')\
Default: 'determinate'

To show indeterminate progress

```html
<kbq-progress-bar [mode]="'indeterminate'"></kbq-progress-bar>
```

Or for determinate progress

```html
<kbq-progress-bar [mode]="'determinate'" [value]="30"></kbq-progress-bar>
```

**Example: Progress bar indeterminate** (`progress-bar-indeterminate`)

```ts progress-bar-indeterminate-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { KbqProgressBarModule } from '@koobiq/components/progress-bar';

@Component({
    selector: 'progress-bar-indeterminate-example',
    imports: [
        KbqProgressBarModule
    ],
    template: `
        <kbq-progress-bar class="example-progress-bar" [mode]="'indeterminate'" />
    `,
    styles: `
        .example-progress-bar {
            margin-bottom: var(--kbq-size-m);
        }
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ProgressBarIndeterminateExample {}
```

#### color

Enum ('theme', 'contrast', 'contrast-fade', 'error')\
Default: 'theme'\
Sets the color of the filled part of the bar. The track keeps the same color in every variant.

```html
<kbq-progress-bar [color]="'theme'" [value]="30"></kbq-progress-bar>
<kbq-progress-bar [color]="'contrast'" [value]="30"></kbq-progress-bar>
<kbq-progress-bar [color]="'contrast-fade'" [value]="30"></kbq-progress-bar>
<kbq-progress-bar [color]="'error'" [value]="30"></kbq-progress-bar>
```

An empty, `null` or `undefined` binding falls back to `'theme'`, so a color that is not resolved yet
never leaves the bar invisible.

#### aria-label

Accessible name of the bar\
Default: taken from the a11y locale configuration

Bind it when the bar has no visible label of its own:

```html
<kbq-progress-bar [value]="30" aria-label="Uploading the archive"></kbq-progress-bar>
```

### Content projection

`kbq-progress-bar-text` renders a label above the bar and `kbq-progress-bar-caption` renders a caption
below it. Both are optional and can be used together.

```html
<kbq-progress-bar [value]="30">
    <div kbq-progress-bar-text>Uploading the archive</div>
    <div kbq-progress-bar-caption>3 of 12 files</div>
</kbq-progress-bar>
```

The projected text also names the bar for assistive technology, and the caption describes it — the
component links them with `aria-labelledby` and `aria-describedby`. A bound `aria-label` takes
precedence over the projected text.

### Accessibility

The host element carries `role="progressbar"`. In determinate mode it reports `aria-valuenow`
(the clamped `value`) together with `aria-valuemin="0"` and `aria-valuemax="100"`; in indeterminate
mode all three are omitted, which is how an unknown duration is expressed.

### Theming

The color of a `<kbq-progress-bar>` can be changed by using the `color` property. By default, it uses
the theme's `theme` color.

An individual bar can also be restyled through the two custom properties it paints from:
`--kbq-progress-bar-fill` for the filled part and `--kbq-progress-bar-track` for the track. Override
those rather than the `--kbq-progress-bar-bar-*` tokens they default to: `contrast`, `contrast-fade`
and `error` each redeclare `--kbq-progress-bar-fill`, so overriding
`--kbq-progress-bar-bar-foreground` reaches only a bar left on the default color.

## API

### Components

#### KbqProgressBar (component)

Horizontal indicator of the progress of an operation.

```ts
@Component({ selector: 'kbq-progress-bar' })
class KbqProgressBar extends KbqColorDirective {
    readonly id = input<string>(`kbq-progress-bar-${idIterator++}`);
    readonly value = input<number>(0);
    readonly mode = input<ProgressBarMode>('determinate');
    readonly ariaLabel = input<string | null>(null, {
        alias: 'aria-label'
    });
    readonly color = input<T | null | undefined>();
    get colorClassName(): string;
    setDefaultColor(color: T): void;
}
```

- `[id]`: `string` — Id of the host element. Generated when not supplied.
- `[value]`: `number` — Share of the work that is done, in the `[0, 100]` range. Ignored in indeterminate mode.
- `[mode]`: `ProgressBarMode` — Whether the bar reports `value`, or an operation whose duration is unknown.
- `[aria-label]`: `string | null` — Accessible name of the bar. Takes precedence over a projected `[kbq-progress-bar-text]`; when
  neither is given, the bar falls back to the `progressBar` name from the a11y locale.
- `[color]`: `T | null | undefined` — Color of the component. A value set in code holds until the input changes, and the default color is used
  while both are unset or falsy.
- `colorClassName`: `string` — current class name of color
- `setDefaultColor()`: `void` — this color will be used as a default value. For example [color]="'' | false | undefined | null".

### Directives

#### KbqProgressBarCaption (directive)

Caption projected below the bar. Describes the bar for assistive tech: `KbqProgressBar` points its
`aria-describedby` at this element.

```ts
@Directive({ selector: '[kbq-progress-bar-caption]' })
class KbqProgressBarCaption {
    readonly id = input<string>(
        `kbq-progress-bar-caption-${captionIdIterator++}`
    );
}
```

- `[id]`: `string` — Element id. Generated when not supplied, so the bar can always reference it.

#### KbqProgressBarText (directive)

Label projected above the bar. Names the bar for assistive tech: `KbqProgressBar` points its
`aria-labelledby` at this element.

```ts
@Directive({ selector: '[kbq-progress-bar-text]' })
class KbqProgressBarText {
    readonly id = input<string>(
        `kbq-progress-bar-text-${textIdIterator++}`
    );
}
```

- `[id]`: `string` — Element id. Generated when not supplied, so the bar can always reference it.

### Types

#### ProgressBarMode (type)

Whether the bar reports a known share of the work, or an operation whose duration is unknown.

```ts
type ProgressBarMode = 'determinate' | 'indeterminate';
```
