From da5e42ca617bbdd902d60fc93fc09ccb12dc97ee Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 5 Oct 2026 15:07:00 +0000 Subject: [PATCH 1/5] docs: prefer React elements for slot-based props Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- contributor-docs/style.md | 52 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/contributor-docs/style.md b/contributor-docs/style.md index b76f56d6a98..2ae35f76a9b 100644 --- a/contributor-docs/style.md +++ b/contributor-docs/style.md @@ -67,6 +67,7 @@ row before the line. - [Base components](#base-components) - [Utilities](#utilities) - [Props](#props) + - [Prefer accepting React elements for slot-based props](#prefer-accepting-react-elements-for-slot-based-props) - [Prefer applying component rest parameters to the root element rendered by a component](#prefer-applying-component-rest-parameters-to-the-root-element-rendered-by-a-component) - [Merge shared props intentionally](#merge-shared-props-intentionally) - [Prefer authoring callback prop types with arguments that can be extended](#prefer-authoring-callback-prop-types-with-arguments-that-can-be-extended) @@ -248,6 +249,57 @@ solid foundations. Examples include hooks such as `useMergedRefs`, ### Props +#### Prefer accepting React elements for slot-based props + +When designing props that fill a content slot, such as `leadingVisual`, +`trailingVisual`, or `icon`, prefer accepting React elements rather than component +types or functions that return elements. Render the supplied element directly. +Use `React.ReactElement` for element-only slots, or `React.ReactNode` when the slot +also supports other renderable content, such as text. + +This lets consumers configure the element through its own props without wrapping +it in an inline component. It also allows Server Components to pass JSX through +these props to Client Components, whereas component functions cannot be passed +across that boundary. See [#8450](https://github.com/primer/react/pull/8450) for the +`IconButton` example that motivated this guidance. + + + + + +
UnpreferredPreferred
+ +```tsx +type Props = { + leadingVisual?: React.ElementType + trailingVisual?: React.ElementType +} + +function Usage() { + return } /> +} +``` + + + +```tsx +type Props = { + leadingVisual?: React.ReactElement + trailingVisual?: React.ReactElement +} + +function Usage() { + return } trailingVisual={} /> +} +``` + +
+ +Reserve render props for cases where the consumer needs state or other values +from the component to determine what to render. When extending an existing +component-type slot API to accept elements, preserve the existing form for +backwards compatibility and prefer the element form in documentation and stories. + #### Prefer applying component rest parameters to the root element rendered by a component Components may accept forwarding props to an underlying element through rest parameters. This strategy allows the component to accept common prop types like `className`, `data-testid`, and more without having to explicitly annotate each property in the component prop type definition. For example: From 5e7f8680a466f3283534ab21f447e1c265ce1343 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 5 Oct 2026 15:16:25 +0000 Subject: [PATCH 2/5] docs: move slot prop guidance into style-guide skill Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/skills/style-guide/SKILL.md | 51 ++++++++++++++++++++++++++++ contributor-docs/style.md | 52 ----------------------------- 2 files changed, 51 insertions(+), 52 deletions(-) diff --git a/.github/skills/style-guide/SKILL.md b/.github/skills/style-guide/SKILL.md index 71fab2f1be8..2c522b5e448 100644 --- a/.github/skills/style-guide/SKILL.md +++ b/.github/skills/style-guide/SKILL.md @@ -23,3 +23,54 @@ specific topic. Consult this to see if any apply to the task at hand. | Topic | Description | Link | | :-------------------- | :------------------------------------------------------------------------ | :------------------------------------------------------- | | Component prop naming | Use when deciding or evaluating the name for a prop in a React component. | [component-prop-naming](./docs/component-prop-naming.md) | + +## Prefer accepting React elements for slot-based props + +When designing props that fill a content slot, such as `leadingVisual`, +`trailingVisual`, or `icon`, prefer accepting React elements rather than component +types or functions that return elements. Render the supplied element directly. +Use `React.ReactElement` for element-only slots, or `React.ReactNode` when the slot +also supports other renderable content, such as text. + +This lets consumers configure the element through its own props without wrapping +it in an inline component. It also allows Server Components to pass JSX through +these props to Client Components, whereas component functions cannot be passed +across that boundary. See [#8450](https://github.com/primer/react/pull/8450) for the +`IconButton` example that motivated this guidance. + + + + + +
UnpreferredPreferred
+ +```tsx +type Props = { + leadingVisual?: React.ElementType + trailingVisual?: React.ElementType +} + +function Usage() { + return } /> +} +``` + + + +```tsx +type Props = { + leadingVisual?: React.ReactElement + trailingVisual?: React.ReactElement +} + +function Usage() { + return } trailingVisual={} /> +} +``` + +
+ +Reserve render props for cases where the consumer needs state or other values +from the component to determine what to render. When extending an existing +component-type slot API to accept elements, preserve the existing form for +backwards compatibility and prefer the element form in documentation and stories. diff --git a/contributor-docs/style.md b/contributor-docs/style.md index 2ae35f76a9b..b76f56d6a98 100644 --- a/contributor-docs/style.md +++ b/contributor-docs/style.md @@ -67,7 +67,6 @@ row before the line. - [Base components](#base-components) - [Utilities](#utilities) - [Props](#props) - - [Prefer accepting React elements for slot-based props](#prefer-accepting-react-elements-for-slot-based-props) - [Prefer applying component rest parameters to the root element rendered by a component](#prefer-applying-component-rest-parameters-to-the-root-element-rendered-by-a-component) - [Merge shared props intentionally](#merge-shared-props-intentionally) - [Prefer authoring callback prop types with arguments that can be extended](#prefer-authoring-callback-prop-types-with-arguments-that-can-be-extended) @@ -249,57 +248,6 @@ solid foundations. Examples include hooks such as `useMergedRefs`, ### Props -#### Prefer accepting React elements for slot-based props - -When designing props that fill a content slot, such as `leadingVisual`, -`trailingVisual`, or `icon`, prefer accepting React elements rather than component -types or functions that return elements. Render the supplied element directly. -Use `React.ReactElement` for element-only slots, or `React.ReactNode` when the slot -also supports other renderable content, such as text. - -This lets consumers configure the element through its own props without wrapping -it in an inline component. It also allows Server Components to pass JSX through -these props to Client Components, whereas component functions cannot be passed -across that boundary. See [#8450](https://github.com/primer/react/pull/8450) for the -`IconButton` example that motivated this guidance. - - - - - -
UnpreferredPreferred
- -```tsx -type Props = { - leadingVisual?: React.ElementType - trailingVisual?: React.ElementType -} - -function Usage() { - return } /> -} -``` - - - -```tsx -type Props = { - leadingVisual?: React.ReactElement - trailingVisual?: React.ReactElement -} - -function Usage() { - return } trailingVisual={} /> -} -``` - -
- -Reserve render props for cases where the consumer needs state or other values -from the component to determine what to render. When extending an existing -component-type slot API to accept elements, preserve the existing form for -backwards compatibility and prefer the element form in documentation and stories. - #### Prefer applying component rest parameters to the root element rendered by a component Components may accept forwarding props to an underlying element through rest parameters. This strategy allows the component to accept common prop types like `className`, `data-testid`, and more without having to explicitly annotate each property in the component prop type definition. For example: From ac37b2c9d6d742c380c3cd49db9dec7e838cfab4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 5 Oct 2026 15:22:39 +0000 Subject: [PATCH 3/5] docs: organize style-guide skill guidance by topic Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/skills/style-guide/SKILL.md | 66 ++++--------------- .../style-guide/docs/component-prop-types.md | 54 +++++++++++++++ 2 files changed, 66 insertions(+), 54 deletions(-) create mode 100644 .github/skills/style-guide/docs/component-prop-types.md diff --git a/.github/skills/style-guide/SKILL.md b/.github/skills/style-guide/SKILL.md index 2c522b5e448..1edc5de484f 100644 --- a/.github/skills/style-guide/SKILL.md +++ b/.github/skills/style-guide/SKILL.md @@ -20,57 +20,15 @@ deviates from the style guide, call out the reason. In addition, there are a set of topics below that may be used for guidance on a specific topic. Consult this to see if any apply to the task at hand. -| Topic | Description | Link | -| :-------------------- | :------------------------------------------------------------------------ | :------------------------------------------------------- | -| Component prop naming | Use when deciding or evaluating the name for a prop in a React component. | [component-prop-naming](./docs/component-prop-naming.md) | - -## Prefer accepting React elements for slot-based props - -When designing props that fill a content slot, such as `leadingVisual`, -`trailingVisual`, or `icon`, prefer accepting React elements rather than component -types or functions that return elements. Render the supplied element directly. -Use `React.ReactElement` for element-only slots, or `React.ReactNode` when the slot -also supports other renderable content, such as text. - -This lets consumers configure the element through its own props without wrapping -it in an inline component. It also allows Server Components to pass JSX through -these props to Client Components, whereas component functions cannot be passed -across that boundary. See [#8450](https://github.com/primer/react/pull/8450) for the -`IconButton` example that motivated this guidance. - - - - - -
UnpreferredPreferred
- -```tsx -type Props = { - leadingVisual?: React.ElementType - trailingVisual?: React.ElementType -} - -function Usage() { - return } /> -} -``` - - - -```tsx -type Props = { - leadingVisual?: React.ReactElement - trailingVisual?: React.ReactElement -} - -function Usage() { - return } trailingVisual={} /> -} -``` - -
- -Reserve render props for cases where the consumer needs state or other values -from the component to determine what to render. When extending an existing -component-type slot API to accept elements, preserve the existing form for -backwards compatibility and prefer the element form in documentation and stories. +| Topic | Description | Link | +| :-------------------- | :-------------------------------------------------------------------------------- | :------------------------------------------------------- | +| Component prop naming | Use when deciding or evaluating the name for a prop in a React component. | [component-prop-naming](./docs/component-prop-naming.md) | +| Component prop types | Use when designing or reviewing component prop types, including slot-based props. | [component-prop-types](./docs/component-prop-types.md) | + +## Updating this skill + +Keep `SKILL.md` minimal: usage instructions and a table linking to topics. +When adding or updating guidance, edit the relevant topic under `docs/`. +If no existing topic fits, create a new topic file under `docs/` and add a row +to the table with a link and a description of when to consult it. Keep detailed +guidance and examples in topic files rather than in `SKILL.md`. diff --git a/.github/skills/style-guide/docs/component-prop-types.md b/.github/skills/style-guide/docs/component-prop-types.md new file mode 100644 index 00000000000..e361ee109ce --- /dev/null +++ b/.github/skills/style-guide/docs/component-prop-types.md @@ -0,0 +1,54 @@ +# Component Prop Types + +Use these conventions when designing or reviewing prop types for Primer React components. + +## Prefer accepting React elements for slot-based props + +When designing props that fill a content slot, such as `leadingVisual`, +`trailingVisual`, or `icon`, prefer accepting React elements rather than component +types or functions that return elements. Render the supplied element directly. +Use `React.ReactElement` for element-only slots, or `React.ReactNode` when the slot +also supports other renderable content, such as text. + +This lets consumers configure the element through its own props without wrapping +it in an inline component. It also allows Server Components to pass JSX through +these props to Client Components, whereas component functions cannot be passed +across that boundary. See [#8450](https://github.com/primer/react/pull/8450) for the +`IconButton` example that motivated this guidance. + + + + + +
UnpreferredPreferred
+ +```tsx +type Props = { + leadingVisual?: React.ElementType + trailingVisual?: React.ElementType +} + +function Usage() { + return } /> +} +``` + + + +```tsx +type Props = { + leadingVisual?: React.ReactElement + trailingVisual?: React.ReactElement +} + +function Usage() { + return } trailingVisual={} /> +} +``` + +
+ +Reserve render props for cases where the consumer needs state or other values +from the component to determine what to render. When extending an existing +component-type slot API to accept elements, preserve the existing form for +backwards compatibility and prefer the element form in documentation and stories. From f2976183d9b20aaf0425086526f6e0d2598e68ba Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 6 Oct 2026 15:17:23 +0000 Subject: [PATCH 4/5] docs: prefer ReactNode for slot props Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .../style-guide/docs/component-prop-types.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/skills/style-guide/docs/component-prop-types.md b/.github/skills/style-guide/docs/component-prop-types.md index e361ee109ce..7e0dbdf1045 100644 --- a/.github/skills/style-guide/docs/component-prop-types.md +++ b/.github/skills/style-guide/docs/component-prop-types.md @@ -5,10 +5,10 @@ Use these conventions when designing or reviewing prop types for Primer React co ## Prefer accepting React elements for slot-based props When designing props that fill a content slot, such as `leadingVisual`, -`trailingVisual`, or `icon`, prefer accepting React elements rather than component -types or functions that return elements. Render the supplied element directly. -Use `React.ReactElement` for element-only slots, or `React.ReactNode` when the slot -also supports other renderable content, such as text. +`trailingVisual`, or `icon`, prefer `React.ReactNode` rather than component types +or functions that return elements. This accepts JSX as well as other renderable +content and conditional values such as `showIcon && `. Use +`React.ReactElement` only when the API specifically requires a single element. This lets consumers configure the element through its own props without wrapping it in an inline component. It also allows Server Components to pass JSX through @@ -36,12 +36,12 @@ function Usage() { ```tsx type Props = { - leadingVisual?: React.ReactElement - trailingVisual?: React.ReactElement + leadingVisual?: React.ReactNode + trailingVisual?: React.ReactNode } -function Usage() { - return } trailingVisual={} /> +function Usage({showSearch}: {showSearch: boolean}) { + return } trailingVisual={} /> } ``` From f8526ed904ac7ef7d46793c58b9d2924e33a0b74 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 7 Oct 2026 16:38:56 +0000 Subject: [PATCH 5/5] docs: remove PR reference from slot guidance Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .../skills/style-guide/docs/component-prop-types.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/skills/style-guide/docs/component-prop-types.md b/.github/skills/style-guide/docs/component-prop-types.md index 7e0dbdf1045..1b2bae56e00 100644 --- a/.github/skills/style-guide/docs/component-prop-types.md +++ b/.github/skills/style-guide/docs/component-prop-types.md @@ -2,7 +2,7 @@ Use these conventions when designing or reviewing prop types for Primer React components. -## Prefer accepting React elements for slot-based props +## Prefer `React.ReactNode` for slot-based props When designing props that fill a content slot, such as `leadingVisual`, `trailingVisual`, or `icon`, prefer `React.ReactNode` rather than component types @@ -10,11 +10,10 @@ or functions that return elements. This accepts JSX as well as other renderable content and conditional values such as `showIcon && `. Use `React.ReactElement` only when the API specifically requires a single element. -This lets consumers configure the element through its own props without wrapping -it in an inline component. It also allows Server Components to pass JSX through -these props to Client Components, whereas component functions cannot be passed -across that boundary. See [#8450](https://github.com/primer/react/pull/8450) for the -`IconButton` example that motivated this guidance. +This lets consumers pass configured JSX directly without wrapping it in an inline +component. It also allows Server Components to pass JSX through these props to +Client Components, whereas component functions cannot be passed across that +boundary.
UnpreferredPreferred