Skip to main content

Custom Components

Unlike a typical React component, you can't simply wrap your Zeego elements in other components.

tsx
// 🚫 this will not work
const Content = () => {
return (
<DropdownMenu.Content>
<DropdownMenu.Item />
<DropdownMenu.Item />
</DropdownMenu.Content>
)
}
export default function Menu() {
return (
<DropdownMenu.Root>
<Content />
</DropdownMenu.Root>
)
}
tsx
// 🚫 this will not work
const Content = () => {
return (
<DropdownMenu.Content>
<DropdownMenu.Item />
<DropdownMenu.Item />
</DropdownMenu.Content>
)
}
export default function Menu() {
return (
<DropdownMenu.Root>
<Content />
</DropdownMenu.Root>
)
}

Instead, you need to render your components inline:

tsx
export default function Menu() {
return (
<DropdownMenu.Root>
<DropdownMenu.Content>
<DropdownMenu.Item />
<DropdownMenu.Item />
</DropdownMenu.Content>
</DropdownMenu.Root>
)
}
tsx
export default function Menu() {
return (
<DropdownMenu.Root>
<DropdownMenu.Content>
<DropdownMenu.Item />
<DropdownMenu.Item />
</DropdownMenu.Content>
</DropdownMenu.Root>
)
}

However, you'll likely want to create your own custom components to wrap each Zeego primitive. For these cases, you can use the create() function to wrap primitives.

Create custom components​

Each Zeego primitive set has a create function that lets you wrap the built-in components.

jsx
import * as DropdownMenu from 'zeego/dropdown-menu'
 
const DropdownMenuItem = DropdownMenu.create((props) => {
// you can add your own components in here
return <DropdownMenu.Item {...props} />
}, 'Item')
jsx
import * as DropdownMenu from 'zeego/dropdown-menu'
 
const DropdownMenuItem = DropdownMenu.create((props) => {
// you can add your own components in here
return <DropdownMenu.Item {...props} />
}, 'Item')

You can now use your custom DropdownMenuItem component.

If you don't wrap custom components with create(), they won't work properly on iOS or Android.

create(Component, displayName)​

create takes two arguments: first, the component to wrap, and second, the name of the primitive it's wrapping.

TypeScript Support​

You can extend the default props of the component you're wrapping:

tsx
import * as DropdownMenu from 'zeego/dropdown-menu'
type ItemProps = React.ComponentProps<typeof DropdownMenu['Item']>
const DropdownMenuItem = DropdownMenu.create((props: ItemProps) => {
return <DropdownMenu.Item {...props} />
}, 'Item')
tsx
import * as DropdownMenu from 'zeego/dropdown-menu'
type ItemProps = React.ComponentProps<typeof DropdownMenu['Item']>
const DropdownMenuItem = DropdownMenu.create((props: ItemProps) => {
return <DropdownMenu.Item {...props} />
}, 'Item')

create Example​

tsx
import * as DropdownMenu from 'zeego/dropdown-menu'
 
type ItemProps = React.ComponentProps<typeof DropdownMenu['Item']>
 
const DropdownMenuItem = DropdownMenu.create((props: ItemProps) => {
return <DropdownMenu.Item {...props} />
}, 'Item')
 
export function Menu() {
return (
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<></>
</DropdownMenu.Trigger>
 
<DropdownMenu.Content>
<DropdownMenuItem key="first">
<DropdownMenu.ItemTitle>My Menu Item</DropdownMenu.ItemTitle>
</DropdownMenuItem>
</DropdownMenu.Content>
</DropdownMenu.Root>
)
}
tsx
import * as DropdownMenu from 'zeego/dropdown-menu'
 
type ItemProps = React.ComponentProps<typeof DropdownMenu['Item']>
 
const DropdownMenuItem = DropdownMenu.create((props: ItemProps) => {
return <DropdownMenu.Item {...props} />
}, 'Item')
 
export function Menu() {
return (
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<></>
</DropdownMenu.Trigger>
 
<DropdownMenu.Content>
<DropdownMenuItem key="first">
<DropdownMenu.ItemTitle>My Menu Item</DropdownMenu.ItemTitle>
</DropdownMenuItem>
</DropdownMenu.Content>
</DropdownMenu.Root>
)
}