-
Notifications
You must be signed in to change notification settings - Fork 309
Expand file tree
/
Copy pathThreadListContainer.tsx
More file actions
118 lines (114 loc) · 3.6 KB
/
ThreadListContainer.tsx
File metadata and controls
118 lines (114 loc) · 3.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { useThreadList } from "@openuidev/react-headless";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import clsx from "clsx";
import { EllipsisVerticalIcon, MenuIcon, Trash2Icon } from "lucide-react";
import { useEffect } from "react";
import { Button } from "../Button";
import { IconButton } from "../IconButton";
const ThreadItem = ({
title,
isSelected,
onSelect,
onDelete,
}: {
title: string;
isSelected: boolean;
onSelect: () => void;
onDelete: () => void;
}) => {
return (
<div
className={clsx("openui-bottom-tray-thread-item", {
"openui-bottom-tray-thread-item--selected": isSelected,
})}
>
<button className="openui-bottom-tray-thread-item-title" onClick={onSelect}>
{title}
</button>
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild>
<IconButton
icon={<EllipsisVerticalIcon size="1em" />}
aria-label={`More actions for ${title}`}
variant="tertiary"
size="extra-small"
className="openui-bottom-tray-thread-item-menu-trigger"
/>
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content
className="openui-bottom-tray-thread-item-menu"
side="right"
align="start"
sideOffset={4}
>
<DropdownMenu.Item
asChild
onSelect={(e) => {
e.stopPropagation();
onDelete();
}}
>
<Button
type="button"
variant="tertiary"
buttonType="destructive"
size="small"
iconLeft={<Trash2Icon size={14} />}
className="openui-bottom-tray-thread-item-menu-action"
>
Delete
</Button>
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
</div>
);
};
export const ThreadListContainer = () => {
const threads = useThreadList((s) => s.threads);
const selectedThreadId = useThreadList((s) => s.selectedThreadId);
const loadThreads = useThreadList((s) => s.loadThreads);
const selectThread = useThreadList((s) => s.selectThread);
const deleteThread = useThreadList((s) => s.deleteThread);
useEffect(() => {
loadThreads();
}, [loadThreads]);
return (
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild>
<IconButton
icon={<MenuIcon size="1em" />}
variant="tertiary"
aria-label="Thread list"
className="openui-bottom-tray-thread-list-trigger"
/>
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content
className="openui-bottom-tray-thread-list-dropdown"
side="bottom"
align="end"
sideOffset={8}
>
<div className="openui-bottom-tray-thread-list-header">All threads</div>
<div className="openui-bottom-tray-thread-list-items">
{threads.map((thread) => (
<ThreadItem
key={thread.id}
title={thread.title}
isSelected={selectedThreadId === thread.id}
onSelect={() => selectThread(thread.id)}
onDelete={() => deleteThread(thread.id)}
/>
))}
{threads.length === 0 && (
<div className="openui-bottom-tray-thread-list-empty">No threads yet</div>
)}
</div>
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
);
};