# 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> ```