Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
51a76ea
feat: support custom slots
francinelucca Oct 10, 2025
95661d8
Create lucky-walls-jog.md
francinelucca Oct 10, 2025
e6d732b
use symbol instead of string
francinelucca Oct 10, 2025
323ab24
Merge branch 'chore/implement-slot-names' of https://github.com/prime…
francinelucca Oct 10, 2025
9ea6440
add optional chaining
francinelucca Oct 10, 2025
0908048
fix tests, add more slots
francinelucca Oct 10, 2025
1a44837
fix errors
francinelucca Oct 10, 2025
e6a02e8
add more slots
francinelucca Oct 10, 2025
af0fd69
add more slots
francinelucca Oct 10, 2025
c12d3ee
add more slots
francinelucca Oct 10, 2025
52f412c
Merge branch 'main' of github.com:primer/react into chore/implement-s…
francinelucca Oct 10, 2025
737b286
add more slots
francinelucca Oct 10, 2025
d93b129
add more slots
francinelucca Oct 10, 2025
2cc3f49
fix error
francinelucca Oct 10, 2025
e30a5ee
add more slots
francinelucca Oct 10, 2025
4aec1c6
fix error
francinelucca Oct 10, 2025
eb25c86
add more slots
francinelucca Oct 10, 2025
7c27f1d
fix errors
francinelucca Oct 10, 2025
ba06f45
add more slots
francinelucca Oct 10, 2025
3e2c13e
add more slots
francinelucca Oct 10, 2025
1adf9a9
add optional chaining
francinelucca Oct 10, 2025
df1c8ba
Add TS types for __SLOT__ prop
adierkens Oct 10, 2025
8a8c54f
update exports
francinelucca Oct 10, 2025
120baeb
test fix
francinelucca Oct 10, 2025
d7237cc
remove ts ignores
francinelucca Oct 10, 2025
64ddae1
slot cleanup
francinelucca Oct 10, 2025
fc39021
slot clean up
francinelucca Oct 10, 2025
17f45ae
clean up slots
francinelucca Oct 10, 2025
658f728
remove unused import
francinelucca Oct 10, 2025
a44928d
revert change
francinelucca Oct 10, 2025
ad3ef08
ts fixes
francinelucca Oct 10, 2025
22854cf
more cleanups
francinelucca Oct 10, 2025
0910a6b
more cleanups
francinelucca Oct 10, 2025
526f892
type fix
francinelucca Oct 10, 2025
69c291c
Merge branch 'main' into chore/implement-slot-names
francinelucca Oct 10, 2025
489f62e
VRT fix
francinelucca Oct 10, 2025
e74690d
Merge branch 'chore/implement-slot-names' of github.com:primer/react …
francinelucca Oct 10, 2025
07ec7da
Merge branch 'main' into chore/implement-slot-names
francinelucca Oct 10, 2025
f740169
refactor getSlot to isSlot
francinelucca Oct 10, 2025
49e51c5
correct conditional
francinelucca Oct 10, 2025
97a467f
remove slot from ActionList
francinelucca Oct 10, 2025
f0e93b2
remove type
francinelucca Oct 10, 2025
84d758a
type fixes
francinelucca Oct 10, 2025
f50d6b3
Merge branch 'main' into chore/implement-slot-names
francinelucca Oct 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/lucky-walls-jog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@primer/react": minor
"@primer/styled-react": patch
---

feat: support custom slots
5 changes: 4 additions & 1 deletion packages/react/src/ActionList/Description.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Truncate from '../Truncate'
import {ItemContext} from './shared'
import classes from './ActionList.module.css'
import {clsx} from 'clsx'
import type {FCWithSlotMarker} from '../utils/types/Slots'

export type ActionListDescriptionProps = {
/**
Expand All @@ -21,7 +22,7 @@ export type ActionListDescriptionProps = {
truncate?: boolean
}

export const Description: React.FC<React.PropsWithChildren<ActionListDescriptionProps>> = ({
export const Description: FCWithSlotMarker<React.PropsWithChildren<ActionListDescriptionProps>> = ({
variant = 'inline',
className,
truncate,
Expand Down Expand Up @@ -70,3 +71,5 @@ export const Description: React.FC<React.PropsWithChildren<ActionListDescription
)
}
}

Description.__SLOT__ = Symbol('ActionList.Description')
5 changes: 4 additions & 1 deletion packages/react/src/ActionList/Divider.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type React from 'react'
import {clsx} from 'clsx'
import classes from './ActionList.module.css'
import type {FCWithSlotMarker} from '../utils/types/Slots'

export type ActionListDividerProps = {
className?: string
Expand All @@ -10,7 +11,7 @@ export type ActionListDividerProps = {
/**
* Visually separates `Items` or `Groups` in an `ActionList`.
*/
export const Divider: React.FC<React.PropsWithChildren<ActionListDividerProps>> = ({className, style}) => {
export const Divider: FCWithSlotMarker<React.PropsWithChildren<ActionListDividerProps>> = ({className, style}) => {
return (
<li
className={clsx(className, classes.Divider)}
Expand All @@ -20,3 +21,5 @@ export const Divider: React.FC<React.PropsWithChildren<ActionListDividerProps>>
/>
)
}

Divider.__SLOT__ = Symbol('ActionList.Divider')
8 changes: 6 additions & 2 deletions packages/react/src/ActionList/Group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {invariant} from '../utils/invariant'
import {clsx} from 'clsx'
import classes from './ActionList.module.css'
import groupClasses from './Group.module.css'
import type {FCWithSlotMarker} from '../utils/types/Slots'

type HeadingProps = {
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
Expand Down Expand Up @@ -67,7 +68,7 @@ export const GroupContext = React.createContext<ContextProps>({
selectionVariant: undefined,
})

export const Group: React.FC<React.PropsWithChildren<ActionListGroupProps>> = ({
export const Group: FCWithSlotMarker<React.PropsWithChildren<ActionListGroupProps>> = ({
title,
variant = 'subtle',
auxiliaryText,
Expand Down Expand Up @@ -138,7 +139,7 @@ export type ActionListGroupHeadingProps = Pick<ActionListGroupProps, 'variant' |
* hidden from the accessibility tree due to the limitation of listbox children. https://w3c.github.io/aria/#listbox
* groups under menu or listbox are labelled by `aria-label`
*/
export const GroupHeading: React.FC<React.PropsWithChildren<ActionListGroupHeadingProps>> = ({
export const GroupHeading: FCWithSlotMarker<React.PropsWithChildren<ActionListGroupHeadingProps>> = ({
as,
variant = 'subtle',
// We are not recommending this prop to be used, it should only be used internally for incremental rollout.
Expand Down Expand Up @@ -210,3 +211,6 @@ export const GroupHeading: React.FC<React.PropsWithChildren<ActionListGroupHeadi

GroupHeading.displayName = 'ActionList.GroupHeading'
Group.displayName = 'ActionList.Group'

Group.__SLOT__ = Symbol('ActionList.Group')
GroupHeading.__SLOT__ = Symbol('ActionList.GroupHeading')
2 changes: 2 additions & 0 deletions packages/react/src/ActionList/Heading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,5 @@ export const Heading = forwardRef(({as, size, children, visuallyHidden = false,
}) as PolymorphicForwardRefComponent<HeadingLevels, ActionListHeadingProps>

Heading.displayName = 'ActionList.Heading'

Heading.__SLOT__ = Symbol('ActionList.Heading')
7 changes: 4 additions & 3 deletions packages/react/src/ActionList/Item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,9 @@ const UnwrappedItem = <As extends React.ElementType = 'li'>(
)
}

const Item = fixedForwardRef(UnwrappedItem)

Object.assign(Item, {displayName: 'ActionList.Item'})
const Item = Object.assign(fixedForwardRef(UnwrappedItem), {
displayName: 'ActionList.Item',
__SLOT__: Symbol('ActionList.Item'),
})

export {Item}
2 changes: 2 additions & 0 deletions packages/react/src/ActionList/LinkItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,5 @@ export const LinkItem = React.forwardRef(
) as PolymorphicForwardRefComponent<'a', ActionListLinkItemProps>

LinkItem.displayName = 'ActionList.LinkItem'

LinkItem.__SLOT__ = Symbol('ActionList.LinkItem')
2 changes: 2 additions & 0 deletions packages/react/src/ActionList/TrailingAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,5 @@ export const TrailingAction = forwardRef(
)
},
) as PolymorphicForwardRefComponent<'button' | 'a', ActionListTrailingActionProps>

TrailingAction.__SLOT__ = Symbol('ActionList.TrailingAction')
8 changes: 6 additions & 2 deletions packages/react/src/ActionList/Visuals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {ItemContext} from './shared'
import {Tooltip, type TooltipProps} from '../TooltipV2'
import {clsx} from 'clsx'
import classes from './ActionList.module.css'
import type {FCWithSlotMarker} from '../utils/types/Slots'

export type VisualProps = React.HTMLAttributes<HTMLSpanElement>

Expand All @@ -13,7 +14,7 @@ export const VisualContainer: React.FC<React.PropsWithChildren<VisualProps>> = (
}

export type ActionListLeadingVisualProps = VisualProps
export const LeadingVisual: React.FC<React.PropsWithChildren<VisualProps>> = ({className, ...props}) => {
export const LeadingVisual: FCWithSlotMarker<React.PropsWithChildren<VisualProps>> = ({className, ...props}) => {
return (
<VisualContainer className={clsx(className, classes.LeadingVisual)} {...props}>
{props.children}
Expand All @@ -22,7 +23,7 @@ export const LeadingVisual: React.FC<React.PropsWithChildren<VisualProps>> = ({c
}

export type ActionListTrailingVisualProps = VisualProps
export const TrailingVisual: React.FC<React.PropsWithChildren<VisualProps>> = ({className, ...props}) => {
export const TrailingVisual: FCWithSlotMarker<React.PropsWithChildren<VisualProps>> = ({className, ...props}) => {
const {trailingVisualId} = React.useContext(ItemContext)
return (
<VisualContainer className={clsx(className, classes.TrailingVisual)} id={trailingVisualId} {...props}>
Expand Down Expand Up @@ -78,3 +79,6 @@ export const VisualOrIndicator: React.FC<

LeadingVisual.displayName = 'ActionList.LeadingVisual'
TrailingVisual.displayName = 'ActionList.TrailingVisual'

LeadingVisual.__SLOT__ = Symbol('ActionList.LeadingVisual')
TrailingVisual.__SLOT__ = Symbol('ActionList.TrailingVisual')
27 changes: 22 additions & 5 deletions packages/react/src/ActionMenu/ActionMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import type {ForwardRefComponent as PolymorphicForwardRefComponent} from '../uti
import {Tooltip} from '../TooltipV2/Tooltip'
import styles from './ActionMenu.module.css'
import {useResponsiveValue, type ResponsiveValue} from '../hooks/useResponsiveValue'
import {isSlot} from '../utils/is-slot'
import type {FCWithSlotMarker, WithSlotMarker} from '../utils/types/Slots'

export type MenuCloseHandler = (
gesture: 'anchor-click' | 'click-outside' | 'escape' | 'tab' | 'item-select' | 'arrow-left' | 'close',
Expand Down Expand Up @@ -71,7 +73,7 @@ const mergeAnchorHandlers = (anchorProps: React.HTMLAttributes<HTMLElement>, but
return mergedAnchorProps
}

const Menu: React.FC<React.PropsWithChildren<ActionMenuProps>> = ({
const Menu: FCWithSlotMarker<React.PropsWithChildren<ActionMenuProps>> = ({
anchorRef: externalAnchorRef,
open,
onOpenChange,
Expand Down Expand Up @@ -112,7 +114,7 @@ const Menu: React.FC<React.PropsWithChildren<ActionMenuProps>> = ({
// 🚨 Accounting for Tooltip wrapping ActionMenu.Button or being a direct child of ActionMenu.Anchor.
const contents = React.Children.map(children, child => {
// Is ActionMenu.Button wrapped with Tooltip? If this is the case, our anchor is the tooltip's trigger (ActionMenu.Button's grandchild)
if (child.type === Tooltip) {
if (child.type === Tooltip || isSlot(child, Tooltip)) {
// tooltip trigger
const anchorChildren = child.props.children
if (anchorChildren.type === MenuButton) {
Expand All @@ -129,7 +131,8 @@ const Menu: React.FC<React.PropsWithChildren<ActionMenuProps>> = ({
return null
} else if (child.type === Anchor) {
const anchorChildren = child.props.children
const isWrappedWithTooltip = anchorChildren !== undefined ? anchorChildren.type === Tooltip : false
const isWrappedWithTooltip =
anchorChildren !== undefined ? anchorChildren.type === Tooltip || isSlot(anchorChildren, Tooltip) : false
if (isWrappedWithTooltip) {
if (anchorChildren.props.children !== null) {
renderAnchor = anchorProps => {
Expand Down Expand Up @@ -175,7 +178,15 @@ const Menu: React.FC<React.PropsWithChildren<ActionMenuProps>> = ({
}

export type ActionMenuAnchorProps = {children: React.ReactElement; id?: string} & React.HTMLAttributes<HTMLElement>
const Anchor = React.forwardRef<HTMLElement, ActionMenuAnchorProps>(({children: child, ...anchorProps}, anchorRef) => {
const Anchor: WithSlotMarker<
React.ForwardRefExoticComponent<
{
children: React.ReactElement
id?: string
} & React.HTMLAttributes<HTMLElement> &
React.RefAttributes<HTMLElement>
>
> = React.forwardRef<HTMLElement, ActionMenuAnchorProps>(({children: child, ...anchorProps}, anchorRef) => {
const {onOpen, isSubmenu} = React.useContext(MenuContext)

const openSubmenuOnRightArrow: React.KeyboardEventHandler<HTMLElement> = useCallback(
Expand Down Expand Up @@ -247,7 +258,7 @@ type MenuOverlayProps = Partial<OverlayProps> &
children: React.ReactNode
onPositionChange?: ({position}: {position: AnchorPosition}) => void
}
const Overlay: React.FC<React.PropsWithChildren<MenuOverlayProps>> = ({
const Overlay: FCWithSlotMarker<React.PropsWithChildren<MenuOverlayProps>> = ({
children,
align = 'start',
side,
Expand Down Expand Up @@ -323,4 +334,10 @@ const Overlay: React.FC<React.PropsWithChildren<MenuOverlayProps>> = ({
}

Menu.displayName = 'ActionMenu'

Menu.__SLOT__ = Symbol('ActionMenu')
MenuButton.__SLOT__ = Symbol('ActionMenu.Button')
Anchor.__SLOT__ = Symbol('ActionMenu.Anchor')
Overlay.__SLOT__ = Symbol('ActionMenu.Overlay')

export const ActionMenu = Object.assign(Menu, {Button: MenuButton, Anchor, Overlay, Divider})
5 changes: 3 additions & 2 deletions packages/react/src/Autocomplete/Autocomplete.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type React from 'react'
import {useCallback, useReducer, useRef} from 'react'
import type {ComponentProps} from '../utils/types'
import type {ComponentProps, FCWithSlotMarker} from '../utils/types'
import {AutocompleteContext} from './AutocompleteContext'
import AutocompleteInput from './AutocompleteInput'
import AutocompleteMenu from './AutocompleteMenu'
Expand Down Expand Up @@ -46,7 +46,7 @@ const reducer = (state: State, action: Action) => {
}
}

const Autocomplete: React.FC<React.PropsWithChildren<{id?: string}>> = ({children, id: idProp}) => {
const Autocomplete: FCWithSlotMarker<React.PropsWithChildren<{id?: string}>> = ({children, id: idProp}) => {
const activeDescendantRef = useRef<HTMLElement>(null)
const scrollContainerRef = useRef<HTMLDivElement>(null)
const inputRef = useRef<HTMLInputElement>(null)
Expand Down Expand Up @@ -98,6 +98,7 @@ export type {AutocompleteInputProps} from './AutocompleteInput'
export type {AutocompleteMenuProps} from './AutocompleteMenu'
export type {AutocompleteOverlayProps} from './AutocompleteOverlay'
export default Object.assign(Autocomplete, {
__SLOT__: Symbol('Autocomplete'),
Context: AutocompleteContext,
Input: AutocompleteInput,
Menu: AutocompleteMenu,
Expand Down
2 changes: 2 additions & 0 deletions packages/react/src/Autocomplete/AutocompleteInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,5 @@ AutocompleteInput.displayName = 'AutocompleteInput'

export type AutocompleteInputProps = ComponentProps<typeof AutocompleteInput>
export default AutocompleteInput

AutocompleteInput.__SLOT__ = Symbol('Autocomplete.Input')
2 changes: 2 additions & 0 deletions packages/react/src/Autocomplete/AutocompleteMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -406,3 +406,5 @@ AutocompleteMenu.displayName = 'AutocompleteMenu'

export type AutocompleteMenuProps = ComponentProps<typeof AutocompleteMenu>
export default AutocompleteMenu

AutocompleteMenu.__SLOT__ = Symbol('Autocomplete.Menu')
2 changes: 2 additions & 0 deletions packages/react/src/Autocomplete/AutocompleteOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,5 @@ AutocompleteOverlay.displayName = 'AutocompleteOverlay'

export type AutocompleteOverlayProps = ComponentProps<typeof AutocompleteOverlay>
export default AutocompleteOverlay

AutocompleteOverlay.__SLOT__ = Symbol('Autocomplete.Overlay')
2 changes: 2 additions & 0 deletions packages/react/src/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,6 @@ export function generateCustomSxProp(

ButtonComponent.displayName = 'Button'

ButtonComponent.__SLOT__ = Symbol('Button')

export {ButtonComponent}
4 changes: 3 additions & 1 deletion packages/react/src/Checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {FormValidationStatus} from '../utils/types/FormValidationStatus'
import {CheckboxGroupContext} from '../CheckboxGroup/CheckboxGroupContext'
import classes from './Checkbox.module.css'
import sharedClasses from './shared.module.css'
import type {WithSlotMarker} from '../utils/types'

export type CheckboxProps = {
/**
Expand Down Expand Up @@ -89,5 +90,6 @@ const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
)

Checkbox.displayName = 'Checkbox'
;(Checkbox as WithSlotMarker<typeof Checkbox>).__SLOT__ = Symbol('Checkbox')

export default Checkbox
export default Checkbox as WithSlotMarker<typeof Checkbox>
17 changes: 13 additions & 4 deletions packages/react/src/CheckboxGroup/CheckboxGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {ChangeEvent, ChangeEventHandler, FC} from 'react'
import type {ChangeEvent, ChangeEventHandler} from 'react'
import React from 'react'
import type {CheckboxOrRadioGroupProps} from '../internal/components/CheckboxOrRadioGroup'
import CheckboxOrRadioGroup from '../internal/components/CheckboxOrRadioGroup'
Expand All @@ -9,6 +9,8 @@ import {useRenderForcingRef} from '../hooks'
import FormControl from '../FormControl'
import Checkbox from '../Checkbox/Checkbox'
import {CheckboxGroupContext} from './CheckboxGroupContext'
import {isSlot} from '../utils/is-slot'
import type {FCWithSlotMarker} from '../utils/types'

export type CheckboxGroupProps = {
/**
Expand All @@ -17,16 +19,21 @@ export type CheckboxGroupProps = {
onChange?: (selected: string[], e?: ChangeEvent<HTMLInputElement>) => void
} & CheckboxOrRadioGroupProps

const CheckboxGroup: FC<React.PropsWithChildren<CheckboxGroupProps>> = ({children, disabled, onChange, ...rest}) => {
const CheckboxGroup: FCWithSlotMarker<React.PropsWithChildren<CheckboxGroupProps>> = ({
children,
disabled,
onChange,
...rest
}) => {
const formControlComponentChildren = React.Children.toArray(children)
.filter(child => React.isValidElement(child) && child.type === FormControl)
.filter(child => React.isValidElement(child) && (child.type === FormControl || isSlot(child, FormControl)))
.map(formControlComponent =>
React.isValidElement(formControlComponent) ? formControlComponent.props.children : [],
)
.flat()

const checkedCheckboxes = React.Children.toArray(formControlComponentChildren)
.filter(child => React.isValidElement(child) && child.type === Checkbox)
.filter(child => React.isValidElement(child) && (child.type === Checkbox || isSlot(child, Checkbox)))
.map(
checkbox =>
React.isValidElement(checkbox) &&
Expand Down Expand Up @@ -73,3 +80,5 @@ export default Object.assign(CheckboxGroup, {
Label: CheckboxOrRadioGroupLabel,
Validation: CheckboxOrRadioGroupValidation,
})

CheckboxGroup.__SLOT__ = Symbol('CheckboxGroup')
23 changes: 18 additions & 5 deletions packages/react/src/FormControl/FormControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {FormControlContextProvider} from './_FormControlContext'
import {warning} from '../utils/warning'
import classes from './FormControl.module.css'
import {BoxWithFallback} from '../internal/components/BoxWithFallback'
import {isSlot} from '../utils/is-slot'

export type FormControlProps = {
children?: React.ReactNode
Expand Down Expand Up @@ -70,12 +71,20 @@ const FormControl = React.forwardRef<HTMLDivElement, FormControlProps>(
const captionId = slots.caption ? `${id}-caption` : undefined
const validationStatus = slots.validation?.props.variant
const InputComponent = childrenWithoutSlots.find(child =>
expectedInputComponents.some(inputComponent => React.isValidElement(child) && child.type === inputComponent),
expectedInputComponents.some(
inputComponent =>
React.isValidElement(child) && (child.type === inputComponent || isSlot(child, inputComponent)),
),
)
const inputProps = React.isValidElement(InputComponent) && InputComponent.props
const isChoiceInput =
React.isValidElement(InputComponent) && (InputComponent.type === Checkbox || InputComponent.type === Radio)
const isRadioInput = React.isValidElement(InputComponent) && InputComponent.type === Radio
React.isValidElement(InputComponent) &&
(InputComponent.type === Checkbox ||
InputComponent.type === Radio ||
isSlot(InputComponent, Checkbox) ||
isSlot(InputComponent, Radio))
const isRadioInput =
React.isValidElement(InputComponent) && (InputComponent.type === Radio || isSlot(InputComponent, Radio))

if (InputComponent) {
warning(
Expand Down Expand Up @@ -139,7 +148,8 @@ const FormControl = React.forwardRef<HTMLDivElement, FormControlProps>(
: null}
{childrenWithoutSlots.filter(
child =>
React.isValidElement(child) && ![Checkbox, Radio].some(inputComponent => child.type === inputComponent),
React.isValidElement(child) &&
![Checkbox, Radio].some(inputComponent => child.type === inputComponent || isSlot(child, inputComponent)),
)}
</div>
{slots.leadingVisual ? (
Expand Down Expand Up @@ -204,7 +214,9 @@ const FormControl = React.forwardRef<HTMLDivElement, FormControlProps>(
{childrenWithoutSlots.filter(
child =>
React.isValidElement(child) &&
!expectedInputComponents.some(inputComponent => child.type === inputComponent),
!expectedInputComponents.some(
inputComponent => child.type === inputComponent || isSlot(child, inputComponent),
),
)}
{slots.validation ? (
<ValidationAnimationContainer show>{slots.validation}</ValidationAnimationContainer>
Expand All @@ -218,6 +230,7 @@ const FormControl = React.forwardRef<HTMLDivElement, FormControlProps>(
)

export default Object.assign(FormControl, {
__SLOT__: Symbol('FormControl'),
Caption: FormControlCaption,
Label: FormControlLabel,
LeadingVisual: FormControlLeadingVisual,
Expand Down
Loading
Loading