Composition
Composable compound components you can use whole or extend with your own styles.
How Composition Works
Compose UI components handle behavior, state management, keyboard interactions, and ARIA attributes automatically. Tailwind CSS provides the styling layer.
This means you get components that are both ready to use out of the box and easy to customize when you need something different.
Using Components As-Is
The simplest approach is to use components directly:
import { Button } from '@lglab/compose-ui/button'
function MyComponent() {
return <Button variant='outline'>Click me</Button>
}Components come with sensible defaults and multiple variants to cover common use cases.
Extending with className
All components accept a className prop that merges with the default styles using tailwind-merge. This lets you add or override styles without fighting specificity:
<Button className='w-full'>Full Width Button</Button><DialogContent className='max-w-2xl'>{/* Wider dialog */}</DialogContent>Compound Components
Compose UI components use the compound component pattern, giving you control over structure while maintaining proper behavior:
import { TabsIndicator, TabsList, TabsPanel, TabsRoot, TabsTab } from '@lglab/compose-ui/tabs'
export function Tabs() {
return (
<TabsRoot defaultValue='one'>
<TabsList>
<TabsTab value='one'>First</TabsTab>
<TabsTab value='two'>Second</TabsTab>
<TabsIndicator />
</TabsList>
<TabsPanel value='one'>Content one</TabsPanel>
<TabsPanel value='two'>Content two</TabsPanel>
</TabsRoot>
)
}You can rearrange, wrap, or style individual parts as needed. Each sub-component is a separate export, so you only import what you use.
Wrapping Components
For repeated customizations, wrap components to create your own variants:
import { Button, type ButtonProps } from '@lglab/compose-ui/button'
function IconButton({ children, ...props }: ButtonProps) {
return (
<Button size='icon' variant='ghost' {...props}>
{children}
</Button>
)
}