# Composition **Category**: native **URL**: https://www.heroui.com/docs/native/getting-started/composition **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/getting-started/(handbook)/composition.mdx > Build flexible UI with component composition patterns *** HeroUI Native uses composition patterns to create flexible, customizable components. Change the rendered element, compose components together, and maintain full control over markup. ## Compound Components HeroUI Native components use a compound component pattern with dot notation—components export sub-components as properties (e.g., `Button.Label`, `Dialog.Trigger`, `Accordion.Item`) that work together to form complete UI elements. ```tsx import { Button, Dialog } from 'heroui-native'; function DialogExample() { return ( Open Dialog Dialog Title Dialog description ); } ``` ## The asChild Prop The `asChild` prop lets you change what element a component renders. When `asChild` is true, HeroUI Native clones the child element and merges props instead of rendering its default element. ```tsx import { Button, Dialog } from 'heroui-native'; function DialogExample() { return ( {/* With asChild: Button becomes the trigger directly, no wrapper element */} {/* Dialog.Close can also use asChild */} Dialog Title Dialog description ); } ``` ## Custom Components Create your own components by composing HeroUI Native primitives: ```tsx import { Button, Card, Popover } from 'heroui-native'; import { View } from 'react-native'; // Product card component function ProductCard({ title, description, price, onBuy, ...props }) { return ( {price} {title} {description} ); } // Popover button component function PopoverButton({ children, popoverContent, ...props }) { return ( {popoverContent} ); } // Usage console.log('Buy')} /> Information Additional details here }> Show Info ``` ## Custom Variants Create custom variants using `tailwind-variants` to extend component styling. Note that text color classes must be applied to `Button.Label`, not the parent `Button`: ```tsx import { Button } from 'heroui-native'; import type { ButtonRootProps } from 'heroui-native'; import { tv, type VariantProps } from 'tailwind-variants'; const customButtonVariants = tv({ base: 'font-semibold rounded-lg', variants: { intent: { primary: 'bg-blue-500', secondary: 'bg-gray-200', danger: 'bg-red-500', }, }, defaultVariants: { intent: 'primary', }, }); const customLabelVariants = tv({ base: '', variants: { intent: { primary: 'text-white', secondary: 'text-gray-800', danger: 'text-white', }, }, defaultVariants: { intent: 'primary', }, }); type CustomButtonVariants = VariantProps; interface CustomButtonProps extends Omit, CustomButtonVariants { className?: string; labelClassName?: string; } export function CustomButton({ intent, className, labelClassName, children, ...props }: CustomButtonProps) { return ( ); } ``` ## Next Steps - Learn about [Styling](/docs/native/getting-started/styling) system - Explore [Theming](/docs/native/getting-started/theming) documentation - Explore [Animation](/docs/native/getting-started/animation) options