1import { mergeProps } from "@base-ui/react/merge-props";
2import { useRender } from "@base-ui/react/use-render";
3import type { ComponentProps } from "react";
4
5import { cn } from "~/lib/utils";
6import { Button } from "../ui/button";
7import {
8 THREAD_DETAILS_PANEL_ROW_CLASS,
9 THREAD_DETAILS_PANEL_SELECT_ROW_CLASS,
10 THREAD_DETAILS_PANEL_SPLIT_PRIMARY_CLASS,
11 THREAD_DETAILS_PANEL_SPLIT_SECONDARY_CLASS,
12 THREAD_DETAILS_PANEL_ICON_ACTION_CLASS,
13 THREAD_DETAILS_PANEL_META_ACTION_CLASS,
14 THREAD_DETAILS_PANEL_CHEVRON_CLASS,
15} from "./threadDetailsPanelStyles";
16import { ChevronDownIcon } from "lucide-react";
17
18const parts = {
19 row: THREAD_DETAILS_PANEL_ROW_CLASS,
20 select: THREAD_DETAILS_PANEL_SELECT_ROW_CLASS,
21 primary: THREAD_DETAILS_PANEL_SPLIT_PRIMARY_CLASS,
22 secondary: THREAD_DETAILS_PANEL_SPLIT_SECONDARY_CLASS,
23 icon: THREAD_DETAILS_PANEL_ICON_ACTION_CLASS,
24 meta: THREAD_DETAILS_PANEL_META_ACTION_CLASS,
25};
26
27/** Panel controls own their fixed density; toolbar controls use the standard Button variants. */
28export function ThreadDetailsControl({
29 panel = true,
30 part = "row",
31 multiline = false,
32 tone = "default",
33 className,
34 children,
35 size = "default",
36 variant = "default",
37 render,
38 ...props
39}: ComponentProps<typeof Button> & {
40 panel?: boolean;
41 part?: keyof typeof parts;
42 multiline?: boolean;
43 tone?: "default" | "muted" | "primary" | "destructive";
44}) {
45 const control = useRender({
46 defaultTagName: "button",
47 render,
48 props: mergeProps<"button">(
49 {
50 type: render ? undefined : "button",
51 className: cn(
52 "relative inline-flex shrink-0 cursor-pointer items-center whitespace-nowrap border outline-none transition-[box-shadow,scale] [&:not([aria-haspopup]):not(:disabled):not([aria-disabled=true])]:will-change-[scale] [&:active:not([aria-haspopup])]:scale-[0.97] focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 disabled:pointer-events-none disabled:opacity-64 aria-disabled:cursor-not-allowed aria-disabled:opacity-64 [&_svg]:shrink-0",
53 parts[part],
54 multiline && "h-auto min-h-8 py-0.75 disabled:opacity-100 sm:h-auto",
55 tone === "muted" && "text-muted-foreground/70 hover:text-foreground/80",
56 tone === "primary" && "text-primary hover:text-primary",
57 tone === "destructive" &&
58 "text-destructive hover:text-destructive data-pressed:text-destructive",
59 className,
60 ),
61 },
62 props,
63 {
64 children:
65 part === "select" ? (
66 <>
67 {children}
68 <span data-slot="select-icon">
69 <ChevronDownIcon className={THREAD_DETAILS_PANEL_CHEVRON_CLASS} />
70 </span>
71 </>
72 ) : (
73 children
74 ),
75 },
76 ),
77 });
78 if (!panel) {
79 return (
80 <Button
81 {...props}
82 render={render}
83 size={multiline ? "sm-multiline" : size}
84 variant={variant}
85 className={className}
86 >
87 {children}
88 </Button>
89 );
90 }
91 return control;
92}