# Scrubber

An interactive scrubber component for exploring individual data points in charts. Displays values on hover or drag and supports custom labels and formatting.

## Import

```tsx
import { Scrubber } from '@coinbase/cds-mobile-visualization'
```

## Examples

### Basic Example

Scrubber can be used to provide horizontal interaction with a chart. As your mouse hovers over the chart, you will see a reference line and scrubber head following your cursor.

```jsx
<LineChart
  enableScrubbing
  height={150}
  series={[
    {
      id: 'prices',
      data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
    },
  ]}
  curve="monotone"
  showYAxis
  showArea
  yAxis={{
    showGrid: true,
  }}
>
  <Scrubber />
</LineChart>
```

### Multiple Series

All series will be scrubbed by default. You can set the `seriesIds` prop to restrict the scrubbing to specific series.

```jsx
<LineChart
  enableScrubbing
  height={150}
  series={[
    {
      id: 'top',
      data: [15, 28, 32, 44, 46, 36, 40, 45, 48, 38],
    },
    {
      id: 'upperMiddle',
      data: [12, 23, 21, 29, 34, 28, 31, 38, 42, 35],
      color: '#ef4444',
      type: 'dotted',
    },
    {
      id: 'lowerMiddle',
      data: [8, 15, 14, 25, 20, 18, 22, 28, 24, 30],
      color: '#f59e0b',
      curve: 'natural',
      LineComponent: (props) => (
        <GradientLine {...props} endColor="#F7931A" startColor="#E3D74D" strokeWidth={4} />
      ),
    },
    {
      id: 'bottom',
      data: [4, 8, 11, 15, 16, 14, 16, 10, 12, 14],
      color: '#800080',
      curve: 'step',
      AreaComponent: DottedArea,
      showArea: true,
    },
  ]}
>
  <Scrubber seriesIds={['top', 'lowerMiddle']} />
</LineChart>
```

### Pulsing

Setting the `idlePulse` prop will cause the scrubber heads to pulse when the user is not actively scrubbing.

```jsx
<LineChart
  enableScrubbing
  height={250}
  series={[
    {
      id: 'prices',
      data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
    },
  ]}
  curve="monotone"
  showArea
>
  <Scrubber idlePulse />
</LineChart>
```

#### With Imperative Handle

You can also use the imperative handle to pulse the scrubber heads programmatically.

```jsx
function ImperativeHandle() {
  const theme = useTheme();
  const scrubberRef = useRef(null);
  return (
    <VStack gap={2}>
      <LineChart
        enableScrubbing
        height={150}
        series={[
          {
            id: 'priceA',
            data: [2400, 1398, 9800, 3908, 4800, 3800, 4300],
            color: theme.color.accentBoldBlue,
            curve: 'natural',
          },
          {
            id: 'priceB',
            data: [2000, 2491, 4501, 6049, 5019, 4930, 5910],
            color: theme.color.accentBoldGreen,
            curve: 'natural',
          },
          {
            id: 'priceC',
            data: [1000, 4910, 2300, 5910, 3940, 2940, 1940],
            color: theme.color.accentBoldPurple,
            curve: 'natural',
          },
          {
            id: 'priceD',
            data: [4810, 2030, 5810, 3940, 2940, 1940, 940],
            color: theme.color.accentBoldYellow,
            curve: 'natural',
          },
        ]}
        xAxis={{
          range: ({ min, max }) => ({ min, max: max - 32 }),
        }}
        showYAxis
        yAxis={{
          domain: {
            min: 0,
          },
          showGrid: true,
          tickLabelFormatter: (value) => value.toLocaleString(),
        }}
      >
        <Scrubber ref={scrubberRef} />
      </LineChart>
      <Button onClick={() => scrubberRef.current?.pulse()}>Pulse</Button>
    </VStack>
  );
}
```

### Disable Overlay When Scrubbing

By default, the scrubber will show an overlay to de-emphasize future data. You can hide this by setting the `hideOverlay` prop to `true`.

```jsx
<LineChart
  enableScrubbing
  height={250}
  series={[
    {
      id: 'prices',
      data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
    },
  ]}
  curve="monotone"
  showYAxis
  showArea
  yAxis={{
    showGrid: true,
  }}
>
  <Scrubber hideOverlay />
</LineChart>
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `BeaconComponent` | `ComponentClass<ScrubberBeaconProps, any> \| FunctionComponent<ScrubberBeaconProps>` | No | `-` | Custom component for the scrubber beacon. |
| `LineComponent` | `FunctionComponent<ReferenceLineProps> \| ComponentClass<ReferenceLineProps, any>` | No | `-` | Custom component for the scrubber line. |
| `hideLine` | `boolean` | No | `-` | Hides the scrubber line |
| `hideOverlay` | `boolean` | No | `-` | Whether to hide the overlay rect which obscures future data. |
| `idlePulse` | `boolean` | No | `-` | Pulse the scrubber beacon while it is at rest. |
| `key` | `Key \| null` | No | `-` | - |
| `label` | `ChartTextChildren \| ((dataIndex: number) => ChartTextChildren)` | No | `-` | Label text displayed above the scrubber line. |
| `labelProps` | `ReferenceLineLabelProps` | No | `-` | Props passed to the scrubber lines label. |
| `lineStroke` | `string` | No | `-` | Stroke color for the scrubber line. |
| `overlayOffset` | `number` | No | `2` | Offset of the overlay rect relative to the drawing area. Useful for when scrubbing over lines, where the stroke width would cause part of the line to be visible. |
| `ref` | `((instance: ScrubberBeaconRef \| null) => void) \| RefObject<ScrubberBeaconRef> \| null` | No | `-` | - |
| `seriesIds` | `string[]` | No | `-` | An array of series IDs that will receive visual emphasis as the user scrubs through the chart. Use this prop to restrict the scrubbing visual behavior to specific series. By default, all series will be highlighted by the Scrubber. |
| `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 |


