# Diff review
> Unified diff reviewer with dithered add and remove tints and a minimap; accepting or rejecting a hunk dissolves the dropped lines.
- Element: `<hf-diff>`
- React: `import { HfDiff } from "@/components/lumesec/hf-diff"`
- Collection: Pixel HD (https://elements.lumesec.ai/components/pixel-hd)
- Registry item: https://elements.lumesec.ai/r/hf-diff.json
- Page: https://elements.lumesec.ai/components/pixel-hd/diff



Live preview: https://elements.lumesec.ai/view/hf-diff

```html
<hf-diff>
--- a/src/auth/session.ts
+++ b/src/auth/session.ts
@@ -12,7 +12,9 @@ export async function refresh(session) {
-  return login();
+  return rotate(token);
</hf-diff>
```

## Installation

```bash
npx shadcn@latest add @lumesec/hf-diff
```

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/hf-diff.json
```

## Usage

React:

```tsx
import { HfDiff } from "@/components/lumesec/hf-diff";

export function Example() {
  return (
    <HfDiff>
      {`--- a/src/auth/session.ts
+++ b/src/auth/session.ts
@@ -12,7 +12,9 @@ export async function refresh(session) {
-  return login();
+  return rotate(token);`}
    </HfDiff>
  );
}
```

HTML:

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

<hf-diff>
--- a/src/auth/session.ts
+++ b/src/auth/session.ts
@@ -12,7 +12,9 @@ export async function refresh(session) {
-  return login();
+  return rotate(token);
</hf-diff>
```

## Behaviour

Takes a unified diff as its text content. Added and removed lines get dithered tints and a minimap on the right; accepting a hunk dissolves the dropped lines to the right.

## API reference

### Events

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

| Event     | React prop  | Detail                                | Description                                                                                                     |
| --------- | ----------- | ------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `resolve` | `onResolve` | `{ hunk: number, accepted: boolean }` | Fires when a hunk is accepted or rejected. `hunk` is its zero-based index. Accept all fires once per open hunk. |

### Methods

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

| Method                                    | Description                                                                                     |
| ----------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `resolve(index: number, accept: boolean)` | Accepts or rejects a hunk by index, as its buttons do. Ignored if the hunk is already resolved. |

## Accessibility

* The code area has `role="table"`, and each hunk header and line has `role="row"`; there are no cell roles.
* Each hunk has native Accept and Reject buttons; the button names repeat for every hunk.
* Resolved hunk headers read `✓ Accepted · …` or `✕ Rejected · …`. The added and removed counters are not a live region.
* Line tints and the minimap are drawn on an `aria-hidden` canvas; the `+` and `−` markers remain in the text.
* Reduced motion: dropped lines collapse without the dissolve particles and the counters change without rolling.

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

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

## Notes

* Pass a unified diff as the element's text content. It is read once on connect; without text a built-in sample diff is shown.
* One file per element: the header shows the last `+++` path with `b/` removed, and hunks start at `@@ -a,b +c,d @@` lines. Line numbers count from the hunk headers.
* In React, pass the diff as a string expression such as `{diff}` so line breaks survive; plain JSX text collapses newlines and the diff does not parse.
* Accept all accepts every open hunk. The code area scrolls horizontally for long lines; hunk headers with their buttons, the tints and the minimap stay in view.


