# bun/jsx-no-forbidden-nesting

> Disallow a JSX element inside another element that cannot contain it

HTML doesn't allow a link or a button inside another link or button. Browsers disagree about what a click on the inner element does. In server-rendered HTML, the parser ends an `a` or a `button` where the next one starts and ignores a `form` inside a `form`, so the DOM doesn't match your JSX.

The inner element is reported at any depth, not only as a direct child. By default the rule knows these pairs:

| Outer | Cannot contain |
| --- | --- |
| `a` | `a`, `button` |
| `button` | `a`, `button` |
| `form` | `form` |
| `label` | `label` |

Only the tag names are compared, so a `Link` component that renders an `a` doesn't count as an `a`.

{/* Generated by src/codegen/lint-rule-docs.ts. Do not edit this section. */}

## Configure

Off by default. To turn it on:

```toml bunfig.toml
[lint.rules]
"bun/jsx-no-forbidden-nesting" = "error" # or "warn"
```

Every option, set to its default. The ones that are commented out are unset by default.

```toml bunfig.toml
[lint.rules]
"bun/jsx-no-forbidden-nesting" = ["error", {
  # pairs = <list of objects>,
}]
```

{/* End of the generated section. */}

## Examples

Reported:

{/* bad */}
```jsx
const card = (
  <a href={post.url}>
    <h2>{post.title}</h2>
    <button onClick={save}>Save</button>
  </a>
);
```

Not reported:

{/* good */}
```jsx
const card = (
  <article>
    <a href={post.url}>
      <h2>{post.title}</h2>
    </a>
    <button onClick={save}>Save</button>
  </article>
);
```

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `pairs` | The table above | A list of `{ outer, inner }` names. It replaces the default list. |

Use it for your own components:

```toml bunfig.toml
[lint.rules]
"bun/jsx-no-forbidden-nesting" = ["error", {
  pairs = [{ outer = "Link", inner = "Button" }],
}]
```

{/* bad {"options": [{"pairs": [{"outer": "Link", "inner": "Button"}]}]} */}
```jsx
const row = (
  <Link to="/settings">
    <Button>Settings</Button>
  </Link>
);
```

Then the default pairs no longer apply. Add them to the list if you want to keep them:

{/* good {"options": [{"pairs": [{"outer": "Link", "inner": "Button"}]}]} */}
```jsx
const row = (
  <a href="/settings">
    <button>Settings</button>
  </a>
);
```
