Skip to content

Slot

Size
0.51 kb
View source

The Slot component merges its props onto its immediate child, enabling flexible prop forwarding and event handling across your components.

This utility is inspired by @radix-ui/react-slot.

Setup

Define and export the Slot component.

slot.tsx
import { defineSlot } from 'crustack/slot'
export const Slot = defineSlot()

Use the strict option to prevent the Slot props from being overriden by the child’s props. See the detailed behavior section for more info.

slot.tsx
import { defineSlot } from 'crustack/slot'
export const StrictSlot = defineSlot({ strict: true })

Examples

1. Enhancing Child Functionality

With the Slot component, you can easily enhance the functionality of a child element by forwarding props such as event handlers.

import { Slot } from './slot'
import { ReactNode } from 'react'
function Trigger(props: { children: ReactNode }) {
return (
<Slot onClick={() => console.log('Do something to open a modal')}>
{props.children}
</Slot>
)
}

Usage:

import { Trigger } from './your-trigger'
export default () => (
<Trigger>
<Button>Open</Button>
</Trigger>
)

Here, clicking the button within the Trigger will log a message to the console and could trigger further functionality, such as opening a modal.

2. Add asChild prop

The Slot component can be used with an asChild prop to replace the underlying HTML element, making the component highly reusable while maintaining prop merging behavior.

import { Slot } from './slot'
import { ReactNode } from 'react'
type Props = ComponentProps<'button'> & {
asChild?: boolean
}
function Button(props: Props) {
const Comp = asChild ? Slot : 'button'
return <Comp {...props} />
}

Usage:

import { Button } from './your-button'
export default () => (
<Button asChild>
<a href="/contact">Contact</a>
</Button>
)

In this example, the Button component wraps an anchor tag, allowing the link to inherit button-like behavior while preserving the original anchor styles and attributes.

Detailed behavior

  • Event Handlers: props beginning with on are merged. Child handlers are invoked before the slot handlers.
  • Styles: The style prop is merged. Child styles take precedence and override any conflicting styles from the Slot.
  • ClassNames: The className prop is also merged.
  • Other props:
    • when strict: false the child’s props override those of the slot.
    • when strict: true an Error is thrown if both the Slot and the child define the same prop.