# ProgressBarWithFloatLabel

**📖 Live documentation:** https://cds.coinbase.com/components/feedback/ProgressBarWithFloatLabel/?platform=mobile

A ProgressBar with a floating label that moves with progress.

## Import

```tsx
import { ProgressBarWithFloatLabel } from '@coinbase/cds-mobile/visualizations/ProgressBarWithFloatLabel'
```

## Examples

### Label Above

```jsx
<VStack gap={2}>
  <ProgressBarWithFloatLabel label={0} progress={0} labelPlacement="above">
    <ProgressBar progress={0} />
  </ProgressBarWithFloatLabel>
  <ProgressBarWithFloatLabel label={20} progress={0.2} labelPlacement="above">
    <ProgressBar progress={0.2} />
  </ProgressBarWithFloatLabel>
</VStack>
```

### Label Below

```jsx
<VStack gap={2}>
  <ProgressBarWithFloatLabel label={0} progress={0} labelPlacement="below">
    <ProgressBar progress={0} />
  </ProgressBarWithFloatLabel>
  <ProgressBarWithFloatLabel label={20} progress={0.2} labelPlacement="below">
    <ProgressBar progress={0.2} />
  </ProgressBarWithFloatLabel>
</VStack>
```

### Disabled

```jsx
<VStack gap={2}>
  <ProgressBarWithFloatLabel label={70} progress={0.7} disabled>
    <ProgressBar progress={0.7} disabled />
  </ProgressBarWithFloatLabel>
</VStack>
```

### Custom Labels

```jsx
function Example() {
  const renderLabelNumStr = useCallback((num) => {
    return `$${num.toLocaleString()}`;
  }, []);

  const renderLabelNum = useCallback((num, disabled) => {
    return (
      <Text as="span" font="title3" disabled={disabled}>
        ${num.toLocaleString()}
      </Text>
    );
  }, []);

  return (
    <VStack gap={2}>
      <ProgressBarWithFloatLabel
        progress={0.6}
        label={{ value: 12500, render: renderLabelNumStr }}
        labelPlacement="above"
      >
        <ProgressBar progress={0.6} />
      </ProgressBarWithFloatLabel>
      <ProgressBarWithFloatLabel
        progress={0.6}
        label={{ value: 12500, render: renderLabelNum }}
        labelPlacement="above"
      >
        <ProgressBar progress={0.6} />
      </ProgressBarWithFloatLabel>
      <ProgressBarWithFloatLabel
        progress={0.6}
        label={{ value: 12500, render: renderLabelNumStr }}
        labelPlacement="above"
        disabled
      >
        <ProgressBar disabled progress={0.6} />
      </ProgressBarWithFloatLabel>
      <ProgressBarWithFloatLabel
        progress={0.6}
        label={{ value: 12500, render: renderLabelNum }}
        labelPlacement="above"
        disabled
      >
        <ProgressBar disabled progress={0.6} />
      </ProgressBarWithFloatLabel>
    </VStack>
  );
}
```

### Custom Styles

You can customize the appearance of the progress bar and float label using the `styles` prop.

```tsx
<ProgressContainerWithButtons>
  {({ calculateProgress }) => (
    <VStack gap={2}>
      <ProgressBarWithFloatLabel
        label={Math.round(calculateProgress(0.4) * 100)}
        labelPlacement="above"
        progress={calculateProgress(0.4)}
        styles={{
          label: { color: 'blue' },
        }}
      >
        <ProgressBar progress={calculateProgress(0.4)} />
      </ProgressBarWithFloatLabel>
    </VStack>
  )}
</ProgressContainerWithButtons>
```

### Animation

By default, ProgressBar animates progress changes. Use `disableAnimateOnMount` to skip the initial animation while still animating subsequent changes.

```tsx
<VStack gap={2}>
  <Text variant="label2">Normal animation</Text>
  <ProgressBarWithFloatLabel label={50} progress={0.5} labelPlacement="above">
    <ProgressBar progress={0.5} />
  </ProgressBarWithFloatLabel>

  <Text variant="label2">Disable animation on mount</Text>
  <ProgressBarWithFloatLabel disableAnimateOnMount label={50} progress={0.5} labelPlacement="above">
    <ProgressBar disableAnimateOnMount progress={0.5} />
  </ProgressBarWithFloatLabel>
</VStack>
```

#### Callbacks

You can use the `onAnimationStart` and `onAnimationEnd` callbacks to track the progress of the animation.

```jsx
function Example() {
  const [animationStatus, setAnimationStatus] = React.useState('Ready');

  const handleAnimationStart = useCallback(() => {
    setAnimationStatus('Animating...');
  }, []);

  const handleAnimationEnd = useCallback(() => {
    setAnimationStatus('Animation Ended');
  }, []);

  return (
    <VStack gap={2}>
      <Text>Animation Status: {animationStatus}</Text>
      <ProgressBarWithFloatLabel label={20} progress={0.2} labelPlacement="above">
        <ProgressBar
          onAnimationEnd={handleAnimationEnd}
          onAnimationStart={handleAnimationStart}
          progress={0.2}
        />
      </ProgressBarWithFloatLabel>
    </VStack>
  );
}
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `label` | `number \| { value: number; render: (num: number, disabled?: boolean \| undefined) => ReactNode; }` | Yes | `-` | Label that is floated at the end of the filled in bar. If a number is used then it will format it as a percentage. |
| `disableAnimateOnMount` | `boolean` | No | `false` | Disable animation on component mount |
| `disabled` | `boolean` | No | `-` | Toggle used to show a disabled progress visualization |
| `labelPlacement` | `above \| below` | No | `above` | Position of label relative to the bar |
| `progress` | `number` | No | `-` | Number between 0-1 representing the progress percentage |
| `style` | `null \| false \|  \| ViewStyle \| RegisteredStyle<ViewStyle> \| RecursiveArray<Falsy \| ViewStyle \| RegisteredStyle<ViewStyle>>` | No | `-` | - |
| `styles` | `{ root?: StyleProp<ViewStyle>; labelContainer?: StyleProp<ViewStyle>; label?: StyleProp<TextStyle>; }` | No | `-` | Custom styles for individual elements of the ProgressBarWithFloatLabel component |
| `testID` | `string` | No | `-` | Used to locate this element in unit and end-to-end tests. Under the hood, testID translates to data-testid on Web. On Mobile, testID stays the same - testID |


## Styles

| Selector | Static class name | Description |
| --- | --- | --- |
| `root` | `-` | Root element |
| `labelContainer` | `-` | Label container element |
| `label` | `-` | Label element |


