# Level up
> XP bar with a hot leading edge; when it overflows the bar flashes and the level number bursts into pixels that reassemble as the next level.
- Element: `<px-xp>`
- React: `import { PxXp } from "@/components/lumesec/px-xp"`
- Collection: Pixel Lab (https://elements.lumesec.ai/components/pixel-lab)
- Registry item: https://elements.lumesec.ai/r/px-xp.json
- Page: https://elements.lumesec.ai/components/pixel-lab/xp



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

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

<px-xp></px-xp>
```

## Playground

Change a prop and the component updates. Props marked live animate to the new value; the others rebuild the element.

## Installation

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

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-xp.json
```

## Usage

React:

```tsx
import { PxXp } from "@/components/lumesec/px-xp";

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

HTML:

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

<px-xp></px-xp>
```

## Behaviour

XP pours into a pixel bar with a hot leading edge. When it overflows, the bar flashes and the level number bursts into pixels that reassemble as the next one.

## API reference

### Attributes

| Attribute | React prop | Type     | Default | Description                                 |
| --------- | ---------- | -------- | ------- | ------------------------------------------- |
| `level`   | `level`    | `number` | `7`     | Starting level. Read once on first connect. |

### Events

Events bubble and cross the shadow boundary unless the description says otherwise.

| Event     | React prop  | Detail              | Description                                       |
| --------- | ----------- | ------------------- | ------------------------------------------------- |
| `gain`    | `onGain`    | `{ xp: number }`    | Fires on each gain with the amount added.         |
| `levelup` | `onLevelup` | `{ level: number }` | Fires when the bar overflows, with the new level. |

### Methods

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

| Method             | Description                                                                       |
| ------------------ | --------------------------------------------------------------------------------- |
| `gain(xp: number)` | Adds XP, fires `gain` and animates the bar; overflow carries into the next level. |

## Accessibility

* The level is text ("Level 7"). The bar canvas has `role="progressbar"` with `aria-label="XP towards level 8"`, `aria-valuenow`, `aria-valuemax` and `aria-valuetext` such as "196 of 240 XP", updated on every gain and level-up.
* The status line is an `aria-live="polite"` region that announces "Level N reached".
* "+40 XP" and "+180 XP" are native buttons.
* Reduced motion: the bar jumps to the new value and the level number changes in place without bursting into pixels; sparks are skipped.

## 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 `--foreground`, `--lumesec` and `--muted-foreground`.

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

## Notes

* XP starts at 196 and is not configurable. Each level needs 100 + 20 x level XP, so level 7 needs 240.
* The level number is set in the monospace font; during a level-up its pixels are sampled from the text and hand back to it once they settle. The canvas is 104px tall.


