---
# System prepended metadata

title: 'Proposal: how slots and children work together'

---

# Proposal: how slots and children work together

## Problem

In v0, most components can take in either `children` or `content`.

If `content` is provided, it renders within the content slot, next to other slots. The `content` is styled as the content should be.

If `children` is provided, it replaces all content in the component. That is, if `icon` content were provided, the `icon` would no longer be rendered.

The presents some confusion to customers when they try to render a `Button`, which has both `icon` and `children`:

```jsx
<Button primary icon={<AddIcon />}>Primary</Button>
```

```
<button>
  ... i want to put stuff here
</button>

<Button>{ (C, p) => I am stuff}</Button>
```

Customers expect it to render the icon and text, as it would in nearly all other component libraries:

![](https://i.imgur.com/ewHqeO1.png)

Instead, the children will disable the `AddIcon` from showing, and the text will render with the wrong styling:

![](https://i.imgur.com/QTmneiE.png)

The v0 approach here is that if you use `children`, slots can only be rendered using staticly available components which would render the slot containers:

```jsx
<Button primary>

  <Button.icon>
    <AddIcon />
  <Button.icon>

  <Button.content>
    Primary
  </Button.content>
  
</Button>
```

Even with this approach, styling becomes unpredictable. Styles which assumed a particular DOM shape may not work as designed.

## Solutions

We want components to be predictable in usage with minimal learning required. So as a goal, this:

```jsx
<Button primary icon={<AddIcon/>}>Primary</Button>
```

Should render this:

![](https://i.imgur.com/ewHqeO1.png)


### Solution 1: treat `children` as a targetable slot, no `content` slot

`children` becomes a targetable slot container, rendered as a span.

```jsx
<Button primary icon={<AddIcon />}>Primary</Button>
```

Renders:

```jsx
<button>
  <span class="Button-icon">
    <svg ... /> // AddIcon
  </span>
  <span class="Button-children">
    Primary
  </span>
</button>
```

### Solution 1b: Same as 1, but additionally support the `content` slot for backwards compatibility

"children" becomes a targetable slot container, rendered as a span.

```jsx
<Button primary icon={<AddIcon/>} content="content">Primary</Button>
```

Renders:

```jsx
<button>
  <span class="Button-icon">
    <svg ... /> // AddIcon
  </span>
  <span class="Button-content">
    content
  </span>
  <span class="Button-children">
    Primary
  </span>
</button>
```

### Solution 2: Render component children within the `content` slot next to `content` children.

```jsx
<Button primary icon={<AddIcon/>} content="content">Primary</Button>
```

Renders:

```jsx
<button>
  <span class="Button-icon">
    <svg ... /> // AddIcon
  </span>
  <span class="Button-content">
    content
    Primary
  </span>
</button>
```

### Solution 3: Redirect the children prop to content.children

Basically if children is provided, that takes precedence over content prop.

```jsx
<Button primary icon={<AddIcon/>} content="content">Primary</Button>
```

Renders:

```jsx
<button>
  <span class="Button-icon">
    <svg ... /> // AddIcon
  </span>
  <span class="Button-content">
    Primary
  </span>
</button>
```

or just content:

```jsx
<Button primary icon={<AddIcon/>} content="content" />
```

Renders:

```jsx
<button>
  <span class="Button-icon">
    <svg ... /> // AddIcon
  </span>
  <span class="Button-content">
    content
  </span>
</button>
```
