# Activity heatmap
> Activity heatmap where each day is nine sub-pixels, so intensity shows as brightness and density; switching metric flips cells in a wave.
- Element: `<px-activity>`
- React: `import { PxActivity } from "@/components/lumesec/px-activity"`
- Collection: Pixel Lab (https://elements.lumesec.ai/components/pixel-lab)
- Registry item: https://elements.lumesec.ai/r/px-activity.json
- Page: https://elements.lumesec.ai/components/pixel-lab/activity



Live preview: https://elements.lumesec.ai/view/px-activity

```html
<script type="module" src="https://elements.lumesec.ai/cdn/px-activity.js"></script>

<px-activity></px-activity>
```

## Installation

```bash
npx shadcn@latest add @lumesec/px-activity
```

First time with the @lumesec registry? Register it once, or install by URL:

```bash
npx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.json
npx shadcn@latest add https://elements.lumesec.ai/r/px-activity.json
```

## Usage

React:

```tsx
import { PxActivity } from "@/components/lumesec/px-activity";

export function Example() {
  return (
    <PxActivity />
  );
}
```

HTML:

```html
<script type="module" src="https://elements.lumesec.ai/cdn/px-activity.js"></script>

<px-activity></px-activity>
```

## Behaviour

Every day is a cell made of nine sub-pixels, so intensity shows as both brightness and density. Hovering draws a crosshair and a tooltip; clicking sends a ripple across the months; switching metric flips the cells in a diagonal wave.

## API reference

### Methods

Call them on the element, for example through a React ref.

| Method                     | Description                                            |
| -------------------------- | ------------------------------------------------------ |
| `setMetric(index: number)` | Switches the metric: `0` for sessions, `1` for tokens. |

## Accessibility

* The metric switch is a `role="radiogroup"` with `aria-label="Metric"`; its two buttons have `role="radio"` and `aria-checked`. Both stay in the tab order and there is no arrow-key handling.
* The canvas has `role="img"` with an `aria-label` giving the total and the longest streak for the current metric.
* The streak summary above the grid is an `aria-live="polite"` region.
* The per-day tooltip appears on pointer hover only.
* Reduced motion: switching metric replaces the cells at once instead of flipping them in a diagonal wave; click ripples still play.

## Theming

The element reads your shadcn theme tokens through its shadow root, so light and dark follow your theme. The accent comes from `--lumesec`. See [Theming](/docs/theming).

This component reads `--card`, `--foreground`, `--lumesec`, `--muted` and `--muted-foreground`.

To restyle only LumeSec elements, set the matching `--ui-*` overrides: `--ui-accent`, `--ui-fg`, `--ui-muted`, `--ui-surface` and `--ui-track`.

## Notes

* The data is generated demo data, derived deterministically from each date, with weekdays busier than weekends. There is no attribute for real data.
* The grid ends at today and shows one 12px column per week, from 8 to 40 weeks depending on width. The canvas is 86px tall.


