raft-ui 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/README.md +24 -0
  2. package/dist/cn.d.mts +2 -0
  3. package/dist/cn.mjs +2 -0
  4. package/dist/index.d.mts +2710 -0
  5. package/dist/index.mjs +4821 -0
  6. package/dist/label-DWq4ia5I.mjs +115 -0
  7. package/dist/styled-props-B3SNekJg.d.mts +16 -0
  8. package/dist/wip.d.mts +1238 -0
  9. package/dist/wip.mjs +1416 -0
  10. package/package.json +70 -0
  11. package/src/components/avatar/avatar.tsx +375 -0
  12. package/src/components/avatar/index.ts +17 -0
  13. package/src/components/badge/badge.tsx +393 -0
  14. package/src/components/badge/index.ts +2 -0
  15. package/src/components/banner/banner.tsx +269 -0
  16. package/src/components/banner/index.ts +8 -0
  17. package/src/components/bottom-sheet/bottom-sheet.tsx +152 -0
  18. package/src/components/bottom-sheet/index.ts +22 -0
  19. package/src/components/button/button.tsx +497 -0
  20. package/src/components/button/index.ts +2 -0
  21. package/src/components/checkbox/checkbox-indicator.tsx +128 -0
  22. package/src/components/checkbox/checkbox.tsx +350 -0
  23. package/src/components/checkbox/index.ts +2 -0
  24. package/src/components/combobox/combobox.tsx +603 -0
  25. package/src/components/combobox/index.ts +52 -0
  26. package/src/components/context-menu/context-menu.tsx +380 -0
  27. package/src/components/context-menu/index.ts +34 -0
  28. package/src/components/conversation-preview-card/conversation-preview-card.tsx +336 -0
  29. package/src/components/conversation-preview-card/index.ts +32 -0
  30. package/src/components/description-list/description-list.tsx +116 -0
  31. package/src/components/description-list/index.ts +14 -0
  32. package/src/components/dropdown-menu/dropdown-menu.tsx +405 -0
  33. package/src/components/dropdown-menu/index.ts +38 -0
  34. package/src/components/empty-state/empty-state.tsx +177 -0
  35. package/src/components/empty-state/index.ts +16 -0
  36. package/src/components/field/field.tsx +125 -0
  37. package/src/components/field/index.ts +18 -0
  38. package/src/components/inline-code/index.ts +2 -0
  39. package/src/components/inline-code/inline-code.tsx +33 -0
  40. package/src/components/input/index.ts +2 -0
  41. package/src/components/input/input.tsx +76 -0
  42. package/src/components/input-group/index.ts +7 -0
  43. package/src/components/input-group/input-group.tsx +215 -0
  44. package/src/components/kbd/index.ts +2 -0
  45. package/src/components/kbd/kbd.tsx +43 -0
  46. package/src/components/label/index.ts +7 -0
  47. package/src/components/label/label.tsx +99 -0
  48. package/src/components/lightbox/index.ts +24 -0
  49. package/src/components/lightbox/lightbox.tsx +245 -0
  50. package/src/components/list-item/index.ts +20 -0
  51. package/src/components/list-item/list-item.tsx +263 -0
  52. package/src/components/media-list-item/index.ts +20 -0
  53. package/src/components/media-list-item/media-list-item.tsx +169 -0
  54. package/src/components/notification-center/index.ts +39 -0
  55. package/src/components/notification-center/notification-center.tsx +558 -0
  56. package/src/components/panel-header/index.ts +22 -0
  57. package/src/components/panel-header/panel-header.tsx +199 -0
  58. package/src/components/popover/index.ts +30 -0
  59. package/src/components/popover/popover.tsx +248 -0
  60. package/src/components/preview-shell/index.ts +2 -0
  61. package/src/components/preview-shell/preview-shell.tsx +51 -0
  62. package/src/components/quoted-message-card/index.ts +36 -0
  63. package/src/components/quoted-message-card/quoted-message-card.tsx +391 -0
  64. package/src/components/radio-group/index.ts +6 -0
  65. package/src/components/radio-group/radio-group.tsx +119 -0
  66. package/src/components/section-header/index.ts +16 -0
  67. package/src/components/section-header/section-header.tsx +117 -0
  68. package/src/components/section-label/index.ts +2 -0
  69. package/src/components/section-label/section-label.tsx +38 -0
  70. package/src/components/segmented-control/index.ts +12 -0
  71. package/src/components/segmented-control/segmented-control.tsx +129 -0
  72. package/src/components/select/index.ts +40 -0
  73. package/src/components/select/select.tsx +382 -0
  74. package/src/components/spinner/index.ts +2 -0
  75. package/src/components/spinner/spinner.tsx +228 -0
  76. package/src/components/status/index.ts +2 -0
  77. package/src/components/status/status.tsx +152 -0
  78. package/src/components/tabs/index.ts +24 -0
  79. package/src/components/tabs/tabs.tsx +417 -0
  80. package/src/components/text/index.ts +2 -0
  81. package/src/components/text/text.tsx +130 -0
  82. package/src/components/textarea/index.ts +2 -0
  83. package/src/components/textarea/textarea.tsx +136 -0
  84. package/src/components/toggle-group/index.ts +12 -0
  85. package/src/components/toggle-group/toggle-group.tsx +111 -0
  86. package/src/components/tooltip/index.ts +14 -0
  87. package/src/components/tooltip/tooltip.tsx +186 -0
  88. package/src/fonts/brutal.css +2 -0
  89. package/src/index.ts +404 -0
  90. package/src/legacy/AttentionDot.tsx +28 -0
  91. package/src/legacy/AvatarListRow.tsx +87 -0
  92. package/src/legacy/AvatarSlot.tsx +157 -0
  93. package/src/legacy/Badge.tsx +95 -0
  94. package/src/legacy/Banner.tsx +74 -0
  95. package/src/legacy/BottomSheet.tsx +76 -0
  96. package/src/legacy/CheckMarker.tsx +72 -0
  97. package/src/legacy/Checkbox.tsx +81 -0
  98. package/src/legacy/ConversationPreviewCard.tsx +169 -0
  99. package/src/legacy/DismissBackdrop.tsx +68 -0
  100. package/src/legacy/EmptyState.tsx +63 -0
  101. package/src/legacy/ExperimentalBadge.tsx +19 -0
  102. package/src/legacy/FormField.tsx +106 -0
  103. package/src/legacy/KeyValueRow.tsx +67 -0
  104. package/src/legacy/Lightbox.tsx +119 -0
  105. package/src/legacy/NotificationCenter.tsx +217 -0
  106. package/src/legacy/PanelHeader.tsx +94 -0
  107. package/src/legacy/PreviewShell.tsx +40 -0
  108. package/src/legacy/QuotedMessageCard.tsx +181 -0
  109. package/src/legacy/ReorderablePanelTabs.tsx +151 -0
  110. package/src/legacy/SandboxedPreviewFrame.tsx +59 -0
  111. package/src/legacy/SearchInput.tsx +23 -0
  112. package/src/legacy/SectionEyebrow.tsx +60 -0
  113. package/src/legacy/SectionHeader.tsx +68 -0
  114. package/src/legacy/SegmentedControl.tsx +74 -0
  115. package/src/legacy/SlugInput.tsx +29 -0
  116. package/src/legacy/Spinner.tsx +89 -0
  117. package/src/legacy/StatusDot.tsx +51 -0
  118. package/src/legacy/SurfaceListItem.tsx +32 -0
  119. package/src/legacy/Textarea.tsx +137 -0
  120. package/src/legacy/button.tsx +100 -0
  121. package/src/legacy/context-menu-divider.tsx +12 -0
  122. package/src/legacy/menu-item.tsx +66 -0
  123. package/src/legacy/selection-popover.tsx +212 -0
  124. package/src/legacy/server-switcher-menu.tsx +203 -0
  125. package/src/legacy/source.css +240 -0
  126. package/src/lib/cn.ts +1 -0
  127. package/src/lib/styled-props.ts +11 -0
  128. package/src/lib/theme/theme-context.ts +28 -0
  129. package/src/lib/theme/theme-provider.tsx +181 -0
  130. package/src/lib/theme/use-theme.ts +12 -0
  131. package/src/lib/tv.ts +29 -0
  132. package/src/lib/without-children.ts +6 -0
  133. package/src/styles.css +467 -0
  134. package/src/wip.ts +255 -0
package/src/index.ts ADDED
@@ -0,0 +1,404 @@
1
+ export { Button, buttonVariants } from "./components/button/index.ts";
2
+ export type { ButtonProps } from "./components/button/index.ts";
3
+
4
+ export { Checkbox } from "./components/checkbox/index.ts";
5
+ export type { CheckboxProps } from "./components/checkbox/index.ts";
6
+
7
+ export {
8
+ ContextMenu,
9
+ ContextMenuCheckboxItem,
10
+ ContextMenuCheckboxItemIndicator,
11
+ ContextMenuContent,
12
+ ContextMenuItem,
13
+ ContextMenuLabel,
14
+ ContextMenuPortal,
15
+ ContextMenuRadioGroup,
16
+ ContextMenuRadioItem,
17
+ ContextMenuRadioItemIndicator,
18
+ ContextMenuSeparator,
19
+ ContextMenuShortcut,
20
+ ContextMenuSubmenu,
21
+ ContextMenuSubmenuTrigger,
22
+ ContextMenuTrigger,
23
+ } from "./components/context-menu/index.ts";
24
+ export type {
25
+ ContextMenuCheckboxItemIndicatorProps,
26
+ ContextMenuCheckboxItemProps,
27
+ ContextMenuContentProps,
28
+ ContextMenuItemProps,
29
+ ContextMenuLabelProps,
30
+ ContextMenuPortalProps,
31
+ ContextMenuProps,
32
+ ContextMenuRadioGroupProps,
33
+ ContextMenuRadioItemIndicatorProps,
34
+ ContextMenuRadioItemProps,
35
+ ContextMenuSeparatorProps,
36
+ ContextMenuShortcutProps,
37
+ ContextMenuSubmenuProps,
38
+ ContextMenuSubmenuTriggerProps,
39
+ ContextMenuTriggerProps,
40
+ } from "./components/context-menu/index.ts";
41
+
42
+ export {
43
+ DropdownMenu,
44
+ DropdownMenuCheckboxItem,
45
+ DropdownMenuCheckboxItemIndicator,
46
+ DropdownMenuContent,
47
+ DropdownMenuItem,
48
+ DropdownMenuItemCount,
49
+ DropdownMenuLabel,
50
+ DropdownMenuPopup,
51
+ DropdownMenuPortal,
52
+ DropdownMenuRadioGroup,
53
+ DropdownMenuRadioItem,
54
+ DropdownMenuRadioItemIndicator,
55
+ DropdownMenuSeparator,
56
+ DropdownMenuShortcut,
57
+ DropdownMenuSubmenu,
58
+ DropdownMenuSubmenuTrigger,
59
+ DropdownMenuTrigger,
60
+ } from "./components/dropdown-menu/index.ts";
61
+ export type {
62
+ DropdownMenuCheckboxItemIndicatorProps,
63
+ DropdownMenuCheckboxItemProps,
64
+ DropdownMenuContentProps,
65
+ DropdownMenuItemCountProps,
66
+ DropdownMenuItemProps,
67
+ DropdownMenuLabelProps,
68
+ DropdownMenuPopupProps,
69
+ DropdownMenuPortalProps,
70
+ DropdownMenuProps,
71
+ DropdownMenuRadioGroupProps,
72
+ DropdownMenuRadioItemIndicatorProps,
73
+ DropdownMenuRadioItemProps,
74
+ DropdownMenuSeparatorProps,
75
+ DropdownMenuShortcutProps,
76
+ DropdownMenuSubmenuProps,
77
+ DropdownMenuSubmenuTriggerProps,
78
+ DropdownMenuTriggerProps,
79
+ } from "./components/dropdown-menu/index.ts";
80
+
81
+ export {
82
+ Tooltip,
83
+ TooltipContent,
84
+ TooltipPortal,
85
+ TooltipProvider,
86
+ TooltipTrigger,
87
+ } from "./components/tooltip/index.ts";
88
+ export type {
89
+ TooltipContentProps,
90
+ TooltipPortalProps,
91
+ TooltipProps,
92
+ TooltipProviderProps,
93
+ TooltipTriggerProps,
94
+ } from "./components/tooltip/index.ts";
95
+
96
+ export {
97
+ Popover,
98
+ PopoverArrow,
99
+ PopoverBackdrop,
100
+ PopoverClose,
101
+ PopoverContent,
102
+ PopoverDescription,
103
+ PopoverHeader,
104
+ PopoverPopup,
105
+ PopoverPortal,
106
+ PopoverSeparator,
107
+ PopoverTitle,
108
+ PopoverTrigger,
109
+ PopoverViewport,
110
+ } from "./components/popover/index.ts";
111
+ export type {
112
+ PopoverArrowProps,
113
+ PopoverBackdropProps,
114
+ PopoverCloseProps,
115
+ PopoverContentProps,
116
+ PopoverDescriptionProps,
117
+ PopoverHeaderProps,
118
+ PopoverPopupProps,
119
+ PopoverPortalProps,
120
+ PopoverProps,
121
+ PopoverSeparatorProps,
122
+ PopoverTitleProps,
123
+ PopoverTriggerProps,
124
+ PopoverViewportProps,
125
+ } from "./components/popover/index.ts";
126
+
127
+ export { Label, LabelAsterisk, LabelOptional, LabelSub } from "./components/label/index.ts";
128
+ export type {
129
+ LabelAsteriskProps,
130
+ LabelOptionalProps,
131
+ LabelProps,
132
+ LabelSubProps,
133
+ } from "./components/label/index.ts";
134
+
135
+ export { Input } from "./components/input/index.ts";
136
+ export type { InputProps } from "./components/input/index.ts";
137
+
138
+ export { InputGroup, InputGroupAddon, InputGroupInput } from "./components/input-group/index.ts";
139
+ export type {
140
+ InputGroupAddonProps,
141
+ InputGroupAddonTextProps,
142
+ InputGroupInputProps,
143
+ InputGroupProps,
144
+ } from "./components/input-group/index.ts";
145
+
146
+ export {
147
+ Combobox,
148
+ ComboboxChip,
149
+ ComboboxChipRemove,
150
+ ComboboxChips,
151
+ ComboboxClear,
152
+ ComboboxCollection,
153
+ ComboboxControl,
154
+ ComboboxContent,
155
+ ComboboxEmpty,
156
+ ComboboxGroup,
157
+ ComboboxGroupLabel,
158
+ ComboboxHeader,
159
+ ComboboxInput,
160
+ ComboboxInputGroup,
161
+ ComboboxItem,
162
+ ComboboxItemIndicator,
163
+ ComboboxLabel,
164
+ ComboboxList,
165
+ ComboboxPopup,
166
+ ComboboxPortal,
167
+ ComboboxRow,
168
+ ComboboxSeparator,
169
+ ComboboxTrigger,
170
+ ComboboxTriggerIndicator,
171
+ ComboboxValue,
172
+ } from "./components/combobox/index.ts";
173
+ export type {
174
+ ComboboxChipProps,
175
+ ComboboxChipRemoveProps,
176
+ ComboboxChipsProps,
177
+ ComboboxClearProps,
178
+ ComboboxCollectionProps,
179
+ ComboboxControlProps,
180
+ ComboboxContentProps,
181
+ ComboboxEmptyProps,
182
+ ComboboxGroupLabelProps,
183
+ ComboboxGroupProps,
184
+ ComboboxHeaderProps,
185
+ ComboboxInputGroupProps,
186
+ ComboboxInputProps,
187
+ ComboboxItemIndicatorProps,
188
+ ComboboxItemProps,
189
+ ComboboxLabelProps,
190
+ ComboboxListProps,
191
+ ComboboxPopupProps,
192
+ ComboboxPortalProps,
193
+ ComboboxProps,
194
+ ComboboxRowProps,
195
+ ComboboxSeparatorProps,
196
+ ComboboxTriggerIndicatorProps,
197
+ ComboboxTriggerProps,
198
+ ComboboxValueProps,
199
+ } from "./components/combobox/index.ts";
200
+
201
+ export {
202
+ Select,
203
+ SelectArrow,
204
+ SelectContent,
205
+ SelectGroup,
206
+ SelectGroupLabel,
207
+ SelectIcon,
208
+ SelectItem,
209
+ SelectItemIndicator,
210
+ SelectItemText,
211
+ SelectLabel,
212
+ SelectList,
213
+ SelectPopup,
214
+ SelectPortal,
215
+ SelectScrollDownArrow,
216
+ SelectScrollUpArrow,
217
+ SelectSeparator,
218
+ SelectTrigger,
219
+ SelectValue,
220
+ } from "./components/select/index.ts";
221
+ export type {
222
+ SelectArrowProps,
223
+ SelectContentProps,
224
+ SelectGroupLabelProps,
225
+ SelectGroupProps,
226
+ SelectIconProps,
227
+ SelectItemIndicatorProps,
228
+ SelectItemProps,
229
+ SelectItemTextProps,
230
+ SelectLabelProps,
231
+ SelectListProps,
232
+ SelectPopupProps,
233
+ SelectPortalProps,
234
+ SelectProps,
235
+ SelectScrollDownArrowProps,
236
+ SelectScrollUpArrowProps,
237
+ SelectSeparatorProps,
238
+ SelectTriggerProps,
239
+ SelectValueProps,
240
+ } from "./components/select/index.ts";
241
+
242
+ export { RadioGroup, RadioGroupIndicator, RadioGroupItem } from "./components/radio-group/index.ts";
243
+ export type {
244
+ RadioGroupIndicatorProps,
245
+ RadioGroupItemProps,
246
+ RadioGroupProps,
247
+ } from "./components/radio-group/index.ts";
248
+
249
+ export {
250
+ SegmentedControl,
251
+ SegmentedControlCount,
252
+ SegmentedControlItem,
253
+ SegmentedControlLabel,
254
+ } from "./components/segmented-control/index.ts";
255
+ export type {
256
+ SegmentedControlCountProps,
257
+ SegmentedControlItemProps,
258
+ SegmentedControlLabelProps,
259
+ SegmentedControlProps,
260
+ } from "./components/segmented-control/index.ts";
261
+
262
+ export { Textarea, TextareaCounter, TextareaGroup } from "./components/textarea/index.ts";
263
+ export type {
264
+ TextareaCounterProps,
265
+ TextareaGroupProps,
266
+ TextareaProps,
267
+ } from "./components/textarea/index.ts";
268
+
269
+ export { Badge } from "./components/badge/index.ts";
270
+ export type { BadgeProps } from "./components/badge/index.ts";
271
+
272
+ export {
273
+ Avatar,
274
+ AvatarBadge,
275
+ AvatarFallback,
276
+ AvatarGroup,
277
+ AvatarGroupCount,
278
+ AvatarImage,
279
+ type AvatarSize,
280
+ } from "./components/avatar/index.ts";
281
+ export type {
282
+ AvatarBadgeProps,
283
+ AvatarFallbackProps,
284
+ AvatarGroupCountProps,
285
+ AvatarGroupProps,
286
+ AvatarImageProps,
287
+ AvatarProps,
288
+ } from "./components/avatar/index.ts";
289
+
290
+ export { InlineCode } from "./components/inline-code/index.ts";
291
+ export type { InlineCodeProps } from "./components/inline-code/index.ts";
292
+
293
+ export { Kbd, KbdGroup } from "./components/kbd/index.ts";
294
+ export type { KbdGroupProps, KbdProps } from "./components/kbd/index.ts";
295
+
296
+ export { Status } from "./components/status/index.ts";
297
+ export type { StatusProps } from "./components/status/index.ts";
298
+
299
+ export { Spinner } from "./components/spinner/index.ts";
300
+ export type { SpinnerProps } from "./components/spinner/index.ts";
301
+
302
+ export { Banner, BannerAction, BannerDescription, BannerTitle } from "./components/banner/index.ts";
303
+ export type {
304
+ BannerActionProps,
305
+ BannerDescriptionProps,
306
+ BannerProps,
307
+ BannerStatus,
308
+ BannerTitleProps,
309
+ } from "./components/banner/index.ts";
310
+
311
+ export {
312
+ EmptyState,
313
+ EmptyStateActions,
314
+ EmptyStateContent,
315
+ EmptyStateDescription,
316
+ EmptyStateIcon,
317
+ EmptyStateTitle,
318
+ } from "./components/empty-state/index.ts";
319
+ export type {
320
+ EmptyStateActionsProps,
321
+ EmptyStateContentProps,
322
+ EmptyStateDescriptionProps,
323
+ EmptyStateIconProps,
324
+ EmptyStateProps,
325
+ EmptyStateTitleProps,
326
+ } from "./components/empty-state/index.ts";
327
+
328
+ export {
329
+ NotificationCenter,
330
+ NotificationCenterActionButton,
331
+ NotificationCenterCount,
332
+ NotificationCenterEmptyState,
333
+ NotificationCenterHeader,
334
+ NotificationCenterItem,
335
+ NotificationCenterItemActions,
336
+ NotificationCenterItemBody,
337
+ NotificationCenterItemContent,
338
+ NotificationCenterItemIcon,
339
+ NotificationCenterItemRow,
340
+ NotificationCenterItemTitle,
341
+ NotificationCenterList,
342
+ NotificationCenterPopup,
343
+ NotificationCenterScroller,
344
+ NotificationCenterTitle,
345
+ NotificationCenterTrigger,
346
+ } from "./components/notification-center/index.ts";
347
+ export type {
348
+ NotificationCenterActionButtonProps,
349
+ NotificationCenterCountProps,
350
+ NotificationCenterEmptyStateProps,
351
+ NotificationCenterHeaderProps,
352
+ NotificationCenterItemActionsProps,
353
+ NotificationCenterItemBodyProps,
354
+ NotificationCenterItemContentProps,
355
+ NotificationCenterItemIconProps,
356
+ NotificationCenterItemProps,
357
+ NotificationCenterItemRowProps,
358
+ NotificationCenterItemTitleProps,
359
+ NotificationCenterListProps,
360
+ NotificationCenterPopupProps,
361
+ NotificationCenterPortalProps,
362
+ NotificationCenterProps,
363
+ NotificationCenterScrollerProps,
364
+ NotificationCenterTitleProps,
365
+ NotificationCenterTriggerProps,
366
+ } from "./components/notification-center/index.ts";
367
+
368
+ export {
369
+ SortableTabsList,
370
+ SortableTabsTab,
371
+ Tabs,
372
+ TabsBackground,
373
+ TabsIndicator,
374
+ TabsLabel,
375
+ TabsList,
376
+ TabsPanel,
377
+ TabsTab,
378
+ useOrderedTabs,
379
+ } from "./components/tabs/index.ts";
380
+ export type {
381
+ OrderedTabItem,
382
+ SortableTabsListProps,
383
+ SortableTabsTabProps,
384
+ TabsBackgroundProps,
385
+ TabsIndicatorProps,
386
+ TabsLabelProps,
387
+ TabsListProps,
388
+ TabsPanelProps,
389
+ TabsProps,
390
+ TabsTabProps,
391
+ } from "./components/tabs/index.ts";
392
+
393
+ export { cn } from "./lib/cn.ts";
394
+ export { ThemeProvider } from "./lib/theme/theme-provider.tsx";
395
+ export type { ThemeProviderProps } from "./lib/theme/theme-provider.tsx";
396
+ export { useTheme, useThemeFamily } from "./lib/theme/use-theme.ts";
397
+ export type {
398
+ ResolvedThemeMode,
399
+ SetTheme,
400
+ SetThemeOptions,
401
+ Theme,
402
+ ThemeMode,
403
+ ThemeState,
404
+ } from "./lib/theme/theme-context.ts";
@@ -0,0 +1,28 @@
1
+ import type { HTMLAttributes } from "react";
2
+
3
+ type SpanPassthroughProps = HTMLAttributes<HTMLSpanElement> &
4
+ Record<`data-${string}`, string | undefined>;
5
+
6
+ export interface AttentionDotProps extends Omit<SpanPassthroughProps, "children"> {
7
+ size?: "sm" | "lg";
8
+ tone?: string;
9
+ }
10
+
11
+ const SIZE_CLASS: Record<NonNullable<AttentionDotProps["size"]>, string> = {
12
+ sm: "size-1",
13
+ lg: "size-2.5",
14
+ };
15
+
16
+ export default function AttentionDot({
17
+ size = "lg",
18
+ tone = "bg-brutal-pink",
19
+ className,
20
+ ...rest
21
+ }: AttentionDotProps) {
22
+ return (
23
+ <span
24
+ {...rest}
25
+ className={`inline-block shrink-0 rounded-full border border-black ${SIZE_CLASS[size]} ${tone} ${className ?? ""}`}
26
+ />
27
+ );
28
+ }
@@ -0,0 +1,87 @@
1
+ import type { HTMLAttributes, ReactNode } from "react";
2
+ import SurfaceListItem from "./SurfaceListItem.tsx";
3
+
4
+ export interface AvatarListRowProps {
5
+ avatar: ReactNode;
6
+ name: ReactNode;
7
+ subtitle?: ReactNode;
8
+ rightContent?: ReactNode;
9
+ onClick?: () => void;
10
+ selected?: boolean;
11
+ align?: "start" | "center";
12
+ actionContent?: ReactNode;
13
+ className?: string;
14
+ buttonProps?: HTMLAttributes<HTMLButtonElement> & Record<`data-${string}`, string | undefined>;
15
+ }
16
+
17
+ export default function AvatarListRow({
18
+ avatar,
19
+ name,
20
+ subtitle,
21
+ rightContent,
22
+ onClick,
23
+ selected = false,
24
+ align = "center",
25
+ actionContent,
26
+ className = "",
27
+ buttonProps,
28
+ }: AvatarListRowProps) {
29
+ const interactive = onClick !== undefined;
30
+ const itemsAlignClass = align === "start" ? "items-start" : "items-center";
31
+ const textColumn = (
32
+ <div className="min-w-0 flex-1">
33
+ {align === "start" ? (
34
+ <div className="flex min-w-0 flex-col gap-1">
35
+ <span className="truncate text-sm font-bold text-black">{name}</span>
36
+ {subtitle != null && subtitle !== false && (
37
+ <span className="flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 text-xs font-mono text-black/50">
38
+ {subtitle}
39
+ </span>
40
+ )}
41
+ </div>
42
+ ) : (
43
+ <div className="flex min-w-0 flex-wrap items-baseline gap-x-2">
44
+ <span className="truncate text-sm font-bold text-black">{name}</span>
45
+ {subtitle != null && subtitle !== false && (
46
+ <span className="text-xs font-mono text-black/50">{subtitle}</span>
47
+ )}
48
+ </div>
49
+ )}
50
+ </div>
51
+ );
52
+ const body = (
53
+ <>
54
+ {avatar}
55
+ {textColumn}
56
+ {rightContent != null && rightContent !== false && (
57
+ <div className="flex shrink-0 self-center items-center gap-1.5">{rightContent}</div>
58
+ )}
59
+ </>
60
+ );
61
+ const hasAction = actionContent != null && actionContent !== false;
62
+ return (
63
+ <SurfaceListItem
64
+ selected={selected}
65
+ interactive={interactive}
66
+ className={`group px-3 py-2 ${className}`}
67
+ >
68
+ <div className={`flex w-full min-w-0 gap-3 ${itemsAlignClass}`}>
69
+ {interactive ? (
70
+ <button
71
+ {...buttonProps}
72
+ type="button"
73
+ onClick={onClick}
74
+ className={`flex min-w-0 flex-1 gap-3 text-left ${itemsAlignClass}`}
75
+ >
76
+ {body}
77
+ </button>
78
+ ) : (
79
+ <div className={`flex min-w-0 flex-1 gap-3 ${itemsAlignClass}`}>{body}</div>
80
+ )}
81
+ {hasAction && (
82
+ <div className="flex shrink-0 self-center items-center gap-1.5">{actionContent}</div>
83
+ )}
84
+ </div>
85
+ </SurfaceListItem>
86
+ );
87
+ }
@@ -0,0 +1,157 @@
1
+ import { User } from "lucide-react";
2
+
3
+ export type AvatarContext =
4
+ | "profile-tile"
5
+ | "account-tile"
6
+ | "mention-card"
7
+ | "panel-header"
8
+ | "surface-list"
9
+ | "members-row"
10
+ | "creator-link"
11
+ | "sidebar-list"
12
+ | "compact-list"
13
+ | "preview-mini";
14
+
15
+ type ContextSpec = {
16
+ size: string;
17
+ border: string;
18
+ agentPixel: number;
19
+ gravatarSize: number;
20
+ gravatarIcon: number;
21
+ placeholderIcon: number;
22
+ };
23
+
24
+ const SPEC: Record<AvatarContext, ContextSpec> = {
25
+ "profile-tile": {
26
+ size: "size-16",
27
+ border: "border-2",
28
+ agentPixel: 60,
29
+ gravatarSize: 60,
30
+ gravatarIcon: 32,
31
+ placeholderIcon: 32,
32
+ },
33
+ "account-tile": {
34
+ size: "size-14",
35
+ border: "border-2",
36
+ agentPixel: 52,
37
+ gravatarSize: 52,
38
+ gravatarIcon: 24,
39
+ placeholderIcon: 24,
40
+ },
41
+ "mention-card": {
42
+ size: "size-12",
43
+ border: "border-2",
44
+ agentPixel: 44,
45
+ gravatarSize: 44,
46
+ gravatarIcon: 24,
47
+ placeholderIcon: 24,
48
+ },
49
+ "panel-header": {
50
+ size: "size-9",
51
+ border: "border-2",
52
+ agentPixel: 32,
53
+ gravatarSize: 32,
54
+ gravatarIcon: 16,
55
+ placeholderIcon: 18,
56
+ },
57
+ "surface-list": {
58
+ size: "size-8",
59
+ border: "border-2",
60
+ agentPixel: 28,
61
+ gravatarSize: 28,
62
+ gravatarIcon: 16,
63
+ placeholderIcon: 16,
64
+ },
65
+ "members-row": {
66
+ size: "size-7",
67
+ border: "border",
68
+ agentPixel: 26,
69
+ gravatarSize: 24,
70
+ gravatarIcon: 14,
71
+ placeholderIcon: 14,
72
+ },
73
+ "creator-link": {
74
+ size: "size-[22px]",
75
+ border: "border",
76
+ agentPixel: 20,
77
+ gravatarSize: 20,
78
+ gravatarIcon: 12,
79
+ placeholderIcon: 12,
80
+ },
81
+ "sidebar-list": {
82
+ size: "size-[18px]",
83
+ border: "border",
84
+ agentPixel: 16,
85
+ gravatarSize: 16,
86
+ gravatarIcon: 10,
87
+ placeholderIcon: 10,
88
+ },
89
+ "compact-list": {
90
+ size: "size-5",
91
+ border: "border",
92
+ agentPixel: 18,
93
+ gravatarSize: 18,
94
+ gravatarIcon: 12,
95
+ placeholderIcon: 12,
96
+ },
97
+ "preview-mini": {
98
+ size: "size-[14px]",
99
+ border: "border",
100
+ agentPixel: 14,
101
+ gravatarSize: 14,
102
+ gravatarIcon: 10,
103
+ placeholderIcon: 10,
104
+ },
105
+ };
106
+
107
+ export type AvatarSlotProps = {
108
+ context: AvatarContext;
109
+ type: "agent" | "human";
110
+ agentAvatarUrl?: string | null;
111
+ gravatarHash?: string | null;
112
+ humanAvatarUrl?: string | null;
113
+ email?: string | null;
114
+ humanPlaceholder?: boolean;
115
+ className?: string;
116
+ };
117
+
118
+ export default function AvatarSlot({
119
+ context,
120
+ type,
121
+ agentAvatarUrl,
122
+ humanAvatarUrl,
123
+ humanPlaceholder,
124
+ className = "",
125
+ }: AvatarSlotProps) {
126
+ const spec = SPEC[context];
127
+ const fallbackBg = type === "agent" ? "bg-brutal-cyan" : "bg-brutal-lavender";
128
+ const baseClass = `flex shrink-0 items-center justify-center overflow-hidden ${spec.size} ${spec.border} border-black ${fallbackBg}`;
129
+
130
+ if (type === "agent") {
131
+ return (
132
+ <div className={`${baseClass} ${className}`.trim()}>
133
+ {agentAvatarUrl ? (
134
+ <img src={agentAvatarUrl} alt="Agent avatar" className="h-full w-full object-cover" />
135
+ ) : (
136
+ <User size={spec.placeholderIcon} />
137
+ )}
138
+ </div>
139
+ );
140
+ }
141
+
142
+ const humanBase = `${baseClass} text-black`;
143
+
144
+ if (humanAvatarUrl && !humanPlaceholder) {
145
+ return (
146
+ <div className={`${humanBase} ${className}`.trim()}>
147
+ <img src={humanAvatarUrl} alt="" className="h-full w-full object-cover" />
148
+ </div>
149
+ );
150
+ }
151
+
152
+ return (
153
+ <div className={`${humanBase} ${className}`.trim()}>
154
+ <User size={humanPlaceholder ? spec.placeholderIcon : spec.gravatarIcon} />
155
+ </div>
156
+ );
157
+ }