# Point

Visual markers that highlight specific data values on a chart. Points can be customized with different colors, sizes, and interactivity.

## Import

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

## Examples

### Basic Example

Points are visual markers that highlight specific data values on a chart. They can be used to emphasize important data points, show discrete values, or provide interactive elements.

```jsx
<LineChart
  enableScrubbing
  height={{ base: 150, tablet: 200, desktop: 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,
  }}
  renderPoints={() => true}
>
  <Scrubber />
</LineChart>
```

### Conditional Points

You can conditionally render points to highlight specific values in your data, such as maximum/minimum values or outliers.

```jsx
function AssetPriceWithMinMax() {
  const data = sparklineInteractiveData.hour.map((d) => d.value);

  const minPrice = Math.min(...data);
  const maxPrice = Math.max(...data);

  const formatPrice = useCallback((price: number) => {
    return new Intl.NumberFormat('en-US', {
      style: 'currency',
      currency: 'USD',
    }).format(price);
  }, []);

  return (
    <LineChart
      series={[
        {
          id: 'btc',
          data: data,
          color: assets.btc.color,
        },
      ]}
      showArea
      areaType="dotted"
      height={{ base: 150, tablet: 200, desktop: 250 }}
      style={{ outlineColor: assets.btc.color }}
      renderPoints={({ dataX, dataY }) => {
        const isMin = dataY === minPrice;
        const isMax = dataY === maxPrice;

        if (isMin) {
          return { label: formatPrice(dataY), labelProps: {  dy: 6, verticalAlignment: 'top' } };
        }

        if (isMax) {
          return { label: formatPrice(dataY), labelProps: { dy: -6, verticalAlignment: 'bottom' } };
        }
      }}
    />
  );
};
```

### Interactive Points

Points can be made interactive by adding click handlers, allowing users to explore data in more detail.

```jsx
<LineChart
  height={{ base: 150, tablet: 200, desktop: 250 }}
  series={[
    {
      id: 'sales',
      data: [120, 132, 101, 134, 90, 230, 210, 120, 180, 190, 210, 176],
    },
  ]}
  curve="monotone"
  showYAxis
  showArea
  yAxis={{
    showGrid: true,
    label: 'Sales (units)',
  }}
  renderPoints={({ dataX, dataY }) => {
    const months = [
      'Jan',
      'Feb',
      'Mar',
      'Apr',
      'May',
      'Jun',
      'Jul',
      'Aug',
      'Sep',
      'Oct',
      'Nov',
      'Dec',
    ];
    return {
      radius: 4,
      onClick: () => alert(`${months[dataX]}: ${dataY} units sold`),
      accessibilityLabel: `${months[dataX]} sales: ${dataY} units`,
    };
  }}
/>
```

### Customization

Points support extensive customization through various properties including colors, sizes, animations, and labels.

```jsx
function CustomizedPoints() {
  const theme = useTheme();
  return (
    <LineChart
      height={{ base: 150, tablet: 200, desktop: 250 }}
      series={[
        {
          id: 'performance',
          data: [65, 70, 72, 85, 88, 92, 78, 82, 90, 95, 91, 94],
        },
      ]}
      curve="monotone"
      showYAxis
      showArea
      yAxis={{
        showGrid: true,
        label: 'Performance Score',
      }}
      renderPoints={({ dataX, dataY }) => {
        const isHighPerformance = dataY >= 90;
        const isLowPerformance = dataY < 75;

        return {
          fill: isHighPerformance
            ? theme.color.bgPositive
            : isLowPerformance
              ? theme.color.bgNegative
              : theme.color.fgPrimary,
          radius: isHighPerformance ? 6 : 4,
          strokeWidth: 2,
          stroke: theme.color.bg,
          label: isHighPerformance || isLowPerformance ? `${dataY}%` : undefined,
          labelProps: {
            verticalAlignment: isHighPerformance ? 'bottom' : 'top',
            dy: isHighPerformance ? -10 : 10,
            color: isHighPerformance
              ? theme.color.fgPositive
              : isLowPerformance
                ? theme.color.fgNegative
                : undefined,
          },
        };
      }}
    />
  );
}
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `dataX` | `number` | Yes | `-` | X coordinate in data space (not pixel coordinates). |
| `dataY` | `number` | Yes | `-` | Y coordinate in data space (not pixel coordinates). |
| `accessibilityLabel` | `string` | No | `-` | Accessibility label for screen readers to describe the point. If not provided, a default label will be generated using the data coordinates. |
| `fill` | `string` | No | `-` | The fill color of the point. |
| `label` | `null \| string \| number \| ReactElement<TSpanProps, TSpan> \| ReactElement<TextPathProps, TextPath> \| ValidChartTextChildElements[]` | No | `-` | Simple text label to display at the point position. If provided, a ChartText will be automatically rendered. |
| `labelProps` | `Omit<ChartTextProps, children \| x \| y>` | No | `-` | Configuration for the automatically rendered label. Only used when label prop is provided. |
| `onPress` | `((point: { x: number; y: number; dataX: number; dataY: number; }) => void)` | No | `-` | Handler for when the point is clicked. |
| `onScrubberEnter` | `((point: { x: number; y: number; }) => void)` | No | `-` | Handler for when the scrubber enters this point. |
| `opacity` | `number` | No | `-` | Opacity of the point. |
| `pixelCoordinates` | `{ x: number; y: number; }` | No | `-` | Optional pixel coordinates to use instead of calculating from dataX/dataY. Useful for performance when coordinates are already calculated. |
| `radius` | `number` | No | `4` | Radius of the point. |
| `stroke` | `string` | No | `theme.color.bg` | Color of the outer stroke around the point. |
| `strokeWidth` | `number` | No | `2` | Outer stroke width of the point. Set to  0 to remove the stroke. |
| `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 |
| `yAxisId` | `string` | No | `-` | Optional Y-axis id to specify which axis to plot along. Defaults to the first y-axis |


