Tool.tsx48 lines · main
| 1 | import type { PropsWithChildren, ReactNode } from 'react' |
| 2 | import { cn, Collapsible, CollapsibleContent, CollapsibleTrigger } from 'ui' |
| 3 | |
| 4 | type ToolProps = PropsWithChildren<{ |
| 5 | className?: string |
| 6 | label: ReactNode |
| 7 | icon?: ReactNode |
| 8 | }> |
| 9 | |
| 10 | export function Tool({ className, label, icon, children }: ToolProps) { |
| 11 | const isCollapsible = !!children |
| 12 | |
| 13 | return ( |
| 14 | <div |
| 15 | className={cn( |
| 16 | 'tool-item text-foreground-lighter flex items-center gap-2 py-2', |
| 17 | '[&:not(.tool-item+.tool-item)]:mt-4 [&:not(:has(+.tool-item))]:mb-4', |
| 18 | '[&:has(+.tool-item)]:border-b [&:has(+.tool-item)]:border-b-muted', |
| 19 | 'first:mt-0! last:mb-0', |
| 20 | className |
| 21 | )} |
| 22 | > |
| 23 | <Collapsible> |
| 24 | <CollapsibleTrigger |
| 25 | className={cn('flex items-center gap-2 w-full text-left')} |
| 26 | disabled={!children} |
| 27 | > |
| 28 | {icon} |
| 29 | {typeof label === 'string' ? ( |
| 30 | <span className="text-foreground-lighter">{label}</span> |
| 31 | ) : ( |
| 32 | label |
| 33 | )} |
| 34 | </CollapsibleTrigger> |
| 35 | |
| 36 | {isCollapsible && ( |
| 37 | <CollapsibleContent |
| 38 | className={cn('pl-6 py-2 text-xs leading-normal', 'max-h-64 overflow-y-auto')} |
| 39 | > |
| 40 | {children} |
| 41 | </CollapsibleContent> |
| 42 | )} |
| 43 | </Collapsible> |
| 44 | </div> |
| 45 | ) |
| 46 | } |
| 47 | |
| 48 | Tool.displayName = 'Tool' |