@sentry/junior-dashboard 0.272.0 → 0.273.0
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.
- package/dist/app.js +2 -2
- package/dist/client.js +69 -67
- package/dist/index.js +2 -2
- package/dist/tailwind.css +1 -1
- package/package.json +4 -4
- package/src/client/App.tsx +440 -430
- package/src/client/components/JuniorLogo.tsx +1 -1
- package/src/client/components/ProfileMenu.tsx +4 -41
- package/src/client/components/layout/DashboardChrome.tsx +9 -4
- package/src/client/components/layout/DashboardHeader.tsx +11 -51
- package/src/client/components/layout/NavRail.tsx +156 -0
- package/src/client/components/ui/sidebar.tsx +336 -0
- package/src/client/conversations/ConversationPage.tsx +3 -0
- package/src/client/conversations/PendingMailboxStack.tsx +22 -9
- package/src/client/conversations/TranscriptMessageShell.tsx +19 -8
- package/src/client/conversations/TranscriptMessageView.tsx +8 -1
- package/src/client/conversations/TranscriptTurnContextView.tsx +1 -1
- package/src/client/conversations/conversationOutbox.ts +19 -0
- package/src/client/conversations/eventTranscript.ts +6 -0
- package/src/client/conversations/queries.ts +1 -17
- package/src/client/conversations/transcript.ts +12 -2
- package/src/client/format.ts +8 -1
- package/src/client/review-desk/ReviewDeskPage.tsx +5 -1
- package/src/client/review-desk/queries.ts +4 -1
- package/src/client/types.ts +2 -0
|
@@ -4,7 +4,7 @@ export function JuniorLogo() {
|
|
|
4
4
|
<div className="relative grid size-10 shrink-0 select-none place-items-center overflow-visible">
|
|
5
5
|
<img
|
|
6
6
|
alt=""
|
|
7
|
-
className="relative size-11 max-w-none
|
|
7
|
+
className="relative -m-0.5 size-11 max-w-none object-contain opacity-90 drop-shadow-[0_0_7px_rgba(255,255,255,0.16)]"
|
|
8
8
|
draggable={false}
|
|
9
9
|
src="/_junior/dashboard/avatar.png"
|
|
10
10
|
/>
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Boxes,
|
|
3
|
-
ChevronDown,
|
|
4
|
-
LogOut,
|
|
5
|
-
Settings,
|
|
6
|
-
ShieldCheck,
|
|
7
|
-
UserRound,
|
|
8
|
-
} from "lucide-react";
|
|
1
|
+
import { Boxes, LogOut, Settings, ShieldCheck, UserRound } from "lucide-react";
|
|
9
2
|
import { useEffect, useRef, useState } from "react";
|
|
10
3
|
import { Link } from "react-router";
|
|
11
4
|
import type { PersonalSpendReport } from "@sentry/junior/api/schema";
|
|
@@ -25,7 +18,7 @@ type ProfileMenuProps = {
|
|
|
25
18
|
spend?: PersonalSpendReport;
|
|
26
19
|
userPages: PluginUserPageLink[];
|
|
27
20
|
/**
|
|
28
|
-
* `popover` is the desktop
|
|
21
|
+
* `popover` is the avatar control at the bottom of the desktop nav rail.
|
|
29
22
|
* `sheet-spend` is the vertical spend callout at the top of the mobile sheet.
|
|
30
23
|
* `sheet-links` is plain account destinations for the mobile nav sheet.
|
|
31
24
|
* `sheet-identity` is the quiet signed-in strip at the bottom of that sheet.
|
|
@@ -331,48 +324,18 @@ export function ProfileMenu({
|
|
|
331
324
|
<PopoverTrigger
|
|
332
325
|
aria-label={`${open ? "Close" : "Open"} profile menu for ${name}. Personal model spend: 7 days ${sevenDaySpend}, 30 days ${thirtyDaySpend}.`}
|
|
333
326
|
className={cn(
|
|
334
|
-
"
|
|
327
|
+
"grid size-10 cursor-pointer place-items-center rounded-lg border-0 bg-transparent text-dashboard-text transition-colors hover:bg-dashboard-fill-hover hover:text-dashboard-text focus-visible:outline focus-visible:outline-2 focus-visible:outline-dashboard-focus/70",
|
|
335
328
|
open && "bg-dashboard-fill-hover text-dashboard-text",
|
|
336
329
|
)}
|
|
337
330
|
closeDelay={HOVER_CLOSE_DELAY_MS}
|
|
338
331
|
delay={HOVER_OPEN_DELAY_MS}
|
|
339
332
|
openOnHover
|
|
340
333
|
>
|
|
341
|
-
<span className="hidden items-center gap-2 md:flex">
|
|
342
|
-
<span className="flex items-baseline gap-1 whitespace-nowrap tabular-nums">
|
|
343
|
-
<span className="text-xs font-medium tracking-[0.08em] text-dashboard-text-muted">
|
|
344
|
-
7d
|
|
345
|
-
</span>
|
|
346
|
-
<span className="text-xs font-semibold text-dashboard-text">
|
|
347
|
-
<SpendAmount value={spend?.sevenDaysUsd} />
|
|
348
|
-
</span>
|
|
349
|
-
</span>
|
|
350
|
-
<span
|
|
351
|
-
aria-hidden="true"
|
|
352
|
-
className="h-3 w-px bg-dashboard-fill-strong"
|
|
353
|
-
/>
|
|
354
|
-
<span className="flex items-baseline gap-1 whitespace-nowrap tabular-nums">
|
|
355
|
-
<span className="text-xs font-medium tracking-[0.08em] text-dashboard-text-muted">
|
|
356
|
-
30d
|
|
357
|
-
</span>
|
|
358
|
-
<span className="text-xs font-semibold text-dashboard-text">
|
|
359
|
-
<SpendAmount value={spend?.thirtyDaysUsd} />
|
|
360
|
-
</span>
|
|
361
|
-
</span>
|
|
362
|
-
</span>
|
|
363
334
|
<ProfileAvatar user={identity.user} />
|
|
364
|
-
<ChevronDown
|
|
365
|
-
aria-hidden="true"
|
|
366
|
-
className={cn(
|
|
367
|
-
"hidden text-dashboard-text-muted transition-[color,transform] group-hover:text-dashboard-text md:block",
|
|
368
|
-
open && "rotate-180 text-dashboard-text",
|
|
369
|
-
)}
|
|
370
|
-
size={14}
|
|
371
|
-
strokeWidth={2}
|
|
372
|
-
/>
|
|
373
335
|
</PopoverTrigger>
|
|
374
336
|
<PopoverContent
|
|
375
337
|
align="end"
|
|
338
|
+
side="right"
|
|
376
339
|
className="w-64 rounded-xl border-0 bg-dashboard-surface-raised/95 p-1.5 shadow-2xl shadow-black/75 backdrop-blur-xl"
|
|
377
340
|
id="profile-popover"
|
|
378
341
|
>
|
|
@@ -102,9 +102,10 @@ export function DashboardChromeProvider(props: { children: ReactNode }) {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
/**
|
|
105
|
-
* Sticky shell chrome:
|
|
105
|
+
* Sticky shell chrome: mobile header, secondary navigation slot, and banner.
|
|
106
106
|
* One bottom border closes the header and page links, so page link
|
|
107
|
-
* underlines sit on it. Banners render below that border.
|
|
107
|
+
* underlines sit on it. Banners render below that border. On desktop the
|
|
108
|
+
* header is hidden, so the border shows only under page links.
|
|
108
109
|
*/
|
|
109
110
|
export function DashboardChrome(props: {
|
|
110
111
|
banner?: ReactNode;
|
|
@@ -117,9 +118,13 @@ export function DashboardChrome(props: {
|
|
|
117
118
|
|
|
118
119
|
return (
|
|
119
120
|
<div className="sticky top-0 z-30 bg-dashboard-bg/95 pt-[env(safe-area-inset-top)]">
|
|
120
|
-
<div className="border-b border-dashboard-border-strong">
|
|
121
|
+
<div className="border-b border-dashboard-border-strong md:border-b-0 md:has-[[data-secondary-slot]>*]:border-b">
|
|
121
122
|
{props.header}
|
|
122
|
-
<div
|
|
123
|
+
<div
|
|
124
|
+
className="hidden md:block"
|
|
125
|
+
data-secondary-slot=""
|
|
126
|
+
ref={chrome.secondarySlotRef}
|
|
127
|
+
/>
|
|
123
128
|
</div>
|
|
124
129
|
{props.banner}
|
|
125
130
|
</div>
|
|
@@ -3,7 +3,6 @@ import { useEffect, useRef, type ReactNode, type RefObject } from "react";
|
|
|
3
3
|
import { Link, NavLink } from "react-router";
|
|
4
4
|
|
|
5
5
|
import { getDashboardAgentName } from "../../agentName";
|
|
6
|
-
import { JuniorLogo } from "../JuniorLogo";
|
|
7
6
|
import { Sheet, SheetClose, SheetContent } from "../ui/sheet";
|
|
8
7
|
import { useSheet } from "../ui/useSheet";
|
|
9
8
|
import {
|
|
@@ -31,7 +30,10 @@ function NavCount(props: { count?: number }) {
|
|
|
31
30
|
);
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Render the mobile shell header and navigation sheet. Desktop navigation
|
|
35
|
+
* lives in `NavRail`.
|
|
36
|
+
*/
|
|
35
37
|
export function DashboardHeader(props: {
|
|
36
38
|
/** Back target used on mobile conversation detail. */
|
|
37
39
|
mobileBackTo?: string;
|
|
@@ -45,8 +47,6 @@ export function DashboardHeader(props: {
|
|
|
45
47
|
mobileSpend?: ReactNode;
|
|
46
48
|
navItems: DashboardHeaderNavItem[];
|
|
47
49
|
onMobileNavigationOpenChange(open: boolean): void;
|
|
48
|
-
/** Compact desktop header control. */
|
|
49
|
-
profile?: ReactNode;
|
|
50
50
|
version?: string;
|
|
51
51
|
workspaceActive: boolean;
|
|
52
52
|
}) {
|
|
@@ -63,13 +63,6 @@ export function DashboardHeader(props: {
|
|
|
63
63
|
onOpenChangeRef.current(true);
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
-
const navLinkClass = ({ isActive }: { isActive: boolean }) =>
|
|
67
|
-
cn(
|
|
68
|
-
"shrink-0 whitespace-nowrap rounded-lg px-3 py-2 font-sans text-sm font-medium tracking-normal no-underline transition-colors",
|
|
69
|
-
isActive
|
|
70
|
-
? "bg-dashboard-accent/[0.1] text-dashboard-accent-text"
|
|
71
|
-
: cn("hover:bg-dashboard-fill-soft", dashboardInteractiveTextClass),
|
|
72
|
-
);
|
|
73
66
|
const sheetLinkClass = ({ isActive }: { isActive: boolean }) =>
|
|
74
67
|
cn(
|
|
75
68
|
"rounded-lg px-3 py-3 font-sans text-sm font-medium no-underline transition-colors",
|
|
@@ -92,19 +85,12 @@ export function DashboardHeader(props: {
|
|
|
92
85
|
}, [props.mobileNavigationOpen]);
|
|
93
86
|
|
|
94
87
|
return (
|
|
95
|
-
<header className="relative bg-dashboard-bg">
|
|
96
|
-
<div
|
|
97
|
-
className={cn(
|
|
98
|
-
"grid w-full min-w-0 grid-cols-[2.5rem_minmax(0,1fr)_2.5rem] items-center gap-x-2 px-3 py-2 md:gap-x-5 md:gap-y-3 md:px-7 md:py-3",
|
|
99
|
-
props.profile
|
|
100
|
-
? "md:grid-cols-[auto_minmax(0,1fr)_auto]"
|
|
101
|
-
: "md:grid-cols-[auto_minmax(0,1fr)]",
|
|
102
|
-
)}
|
|
103
|
-
>
|
|
88
|
+
<header className="relative bg-dashboard-bg md:hidden">
|
|
89
|
+
<div className="grid w-full min-w-0 grid-cols-[2.5rem_minmax(0,1fr)_2.5rem] items-center gap-x-2 px-3 py-2">
|
|
104
90
|
{conversationMode && props.mobileBackTo ? (
|
|
105
91
|
<Link
|
|
106
92
|
aria-label="Back to conversations"
|
|
107
|
-
className="grid size-10 place-items-center rounded-lg text-dashboard-text no-underline transition-colors hover:bg-dashboard-fill-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-dashboard-focus/70
|
|
93
|
+
className="grid size-10 place-items-center rounded-lg text-dashboard-text no-underline transition-colors hover:bg-dashboard-fill-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-dashboard-focus/70"
|
|
108
94
|
to={props.mobileBackTo}
|
|
109
95
|
>
|
|
110
96
|
<ArrowLeft aria-hidden="true" size={20} strokeWidth={2} />
|
|
@@ -115,7 +101,7 @@ export function DashboardHeader(props: {
|
|
|
115
101
|
aria-expanded={props.mobileNavigationOpen}
|
|
116
102
|
aria-hidden={props.mobileNavigationOpen || undefined}
|
|
117
103
|
aria-label="Open navigation"
|
|
118
|
-
className="grid size-10 cursor-pointer place-items-center rounded-lg border-0 bg-transparent text-dashboard-text transition-colors hover:bg-dashboard-fill-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-dashboard-focus/70
|
|
104
|
+
className="grid size-10 cursor-pointer place-items-center rounded-lg border-0 bg-transparent text-dashboard-text transition-colors hover:bg-dashboard-fill-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-dashboard-focus/70"
|
|
119
105
|
onClick={() => props.onMobileNavigationOpenChange(true)}
|
|
120
106
|
tabIndex={props.mobileNavigationOpen ? -1 : undefined}
|
|
121
107
|
type="button"
|
|
@@ -124,7 +110,7 @@ export function DashboardHeader(props: {
|
|
|
124
110
|
</button>
|
|
125
111
|
)}
|
|
126
112
|
{conversationMode ? (
|
|
127
|
-
<div className="col-start-2 row-start-1 flex min-w-0 items-center gap-2
|
|
113
|
+
<div className="col-start-2 row-start-1 flex min-w-0 items-center gap-2">
|
|
128
114
|
{mobileTitle ? (
|
|
129
115
|
<h1 className="m-0 min-w-0 truncate text-left font-display text-sm font-medium text-dashboard-text">
|
|
130
116
|
{mobileTitle}
|
|
@@ -136,42 +122,16 @@ export function DashboardHeader(props: {
|
|
|
136
122
|
<Link
|
|
137
123
|
aria-label={`${getDashboardAgentName()} home`}
|
|
138
124
|
className={cn(
|
|
139
|
-
"col-start-2 row-start-1 min-w-0 max-w-full items-center justify-self-center text-inherit no-underline
|
|
125
|
+
"col-start-2 row-start-1 min-w-0 max-w-full items-center justify-self-center text-inherit no-underline",
|
|
140
126
|
conversationMode ? "hidden" : "flex",
|
|
141
127
|
)}
|
|
142
128
|
to="/"
|
|
143
129
|
>
|
|
144
|
-
<span className="truncate font-sans text-sm font-semibold
|
|
130
|
+
<span className="truncate font-sans text-sm font-semibold">
|
|
145
131
|
{getDashboardAgentName()}
|
|
146
132
|
</span>
|
|
147
|
-
<span className="hidden md:block">
|
|
148
|
-
<JuniorLogo />
|
|
149
|
-
</span>
|
|
150
133
|
</Link>
|
|
151
|
-
<nav
|
|
152
|
-
aria-label="Primary"
|
|
153
|
-
className="hidden min-w-0 items-center gap-1 md:col-start-2 md:flex md:justify-self-start"
|
|
154
|
-
>
|
|
155
|
-
<Link
|
|
156
|
-
aria-current={props.workspaceActive ? "page" : undefined}
|
|
157
|
-
className={navLinkClass({ isActive: props.workspaceActive })}
|
|
158
|
-
to="/"
|
|
159
|
-
>
|
|
160
|
-
Conversations
|
|
161
|
-
</Link>
|
|
162
|
-
{props.navItems.map((item) => (
|
|
163
|
-
<NavLink className={navLinkClass} key={item.key} to={item.to}>
|
|
164
|
-
{item.label}
|
|
165
|
-
<NavCount count={item.count} />
|
|
166
|
-
</NavLink>
|
|
167
|
-
))}
|
|
168
|
-
</nav>
|
|
169
134
|
{conversationMode ? <MobileHeaderActionsSlot /> : null}
|
|
170
|
-
{props.profile ? (
|
|
171
|
-
<div className="col-start-3 hidden justify-self-end md:block">
|
|
172
|
-
{props.profile}
|
|
173
|
-
</div>
|
|
174
|
-
) : null}
|
|
175
135
|
</div>
|
|
176
136
|
{props.mobileNavigationOpen ? (
|
|
177
137
|
<MobileNavigationSheet
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Boxes,
|
|
3
|
+
Brain,
|
|
4
|
+
CodeXml,
|
|
5
|
+
Gauge,
|
|
6
|
+
Inbox,
|
|
7
|
+
MessagesSquare,
|
|
8
|
+
Zap,
|
|
9
|
+
type LucideIcon,
|
|
10
|
+
} from "lucide-react";
|
|
11
|
+
import type { CSSProperties, ReactNode } from "react";
|
|
12
|
+
import { Link, useMatch } from "react-router";
|
|
13
|
+
|
|
14
|
+
import { getDashboardAgentName } from "../../agentName";
|
|
15
|
+
import { JuniorLogo } from "../JuniorLogo";
|
|
16
|
+
import {
|
|
17
|
+
Sidebar,
|
|
18
|
+
SidebarContent,
|
|
19
|
+
SidebarFooter,
|
|
20
|
+
SidebarGroup,
|
|
21
|
+
SidebarHeader,
|
|
22
|
+
SidebarMenu,
|
|
23
|
+
SidebarMenuBadge,
|
|
24
|
+
SidebarMenuButton,
|
|
25
|
+
SidebarMenuItem,
|
|
26
|
+
SidebarProvider,
|
|
27
|
+
} from "../ui/sidebar";
|
|
28
|
+
import type { DashboardHeaderNavItem } from "./DashboardHeader";
|
|
29
|
+
|
|
30
|
+
// Plugin primary pages without an entry here use the generic plugin icon.
|
|
31
|
+
const NAV_ICONS: Record<string, LucideIcon> = {
|
|
32
|
+
automations: Zap,
|
|
33
|
+
code: CodeXml,
|
|
34
|
+
"memory:memories": Brain,
|
|
35
|
+
review: Inbox,
|
|
36
|
+
system: Gauge,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// 56px rail with 40px targets, so the icons keep their size from the top bar.
|
|
40
|
+
const RAIL_STYLE = { "--sidebar-width-icon": "3.5rem" } as CSSProperties;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Lay out the desktop nav rail beside the page. The rail is always the
|
|
44
|
+
* collapsed (icon) shadcn sidebar, and the provider's spacer keeps page
|
|
45
|
+
* content clear of it.
|
|
46
|
+
*/
|
|
47
|
+
export function NavRailProvider(props: { children: ReactNode }) {
|
|
48
|
+
return (
|
|
49
|
+
<SidebarProvider open={false} style={RAIL_STYLE}>
|
|
50
|
+
{props.children}
|
|
51
|
+
</SidebarProvider>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function RailItem(props: {
|
|
56
|
+
active: boolean;
|
|
57
|
+
count?: number;
|
|
58
|
+
icon: LucideIcon;
|
|
59
|
+
label: string;
|
|
60
|
+
to: string;
|
|
61
|
+
}) {
|
|
62
|
+
const Icon = props.icon;
|
|
63
|
+
const label = props.count
|
|
64
|
+
? `${props.label} ${props.count.toLocaleString("en-US")}`
|
|
65
|
+
: props.label;
|
|
66
|
+
return (
|
|
67
|
+
<SidebarMenuItem>
|
|
68
|
+
<SidebarMenuButton
|
|
69
|
+
aria-label={label}
|
|
70
|
+
className="justify-center rounded-lg text-dashboard-text-muted group-data-[collapsible=icon]:size-10! group-data-[collapsible=icon]:p-0! data-active:bg-dashboard-accent/[0.12] data-active:font-normal data-active:text-dashboard-accent-text [&_svg]:size-5"
|
|
71
|
+
isActive={props.active}
|
|
72
|
+
render={
|
|
73
|
+
<Link
|
|
74
|
+
aria-current={props.active ? "page" : undefined}
|
|
75
|
+
to={props.to}
|
|
76
|
+
/>
|
|
77
|
+
}
|
|
78
|
+
tooltip={{ children: label, size: "compact", sideOffset: 6 }}
|
|
79
|
+
>
|
|
80
|
+
<Icon aria-hidden="true" strokeWidth={1.9} />
|
|
81
|
+
</SidebarMenuButton>
|
|
82
|
+
{props.count ? (
|
|
83
|
+
<SidebarMenuBadge
|
|
84
|
+
aria-hidden="true"
|
|
85
|
+
className="-top-2 -right-1.5 h-4 min-w-4 rounded-full bg-dashboard-accent px-1 text-2xs font-semibold leading-none normal-nums text-dashboard-text-inverse ring-2 ring-sidebar group-data-[collapsible=icon]:flex peer-data-[size=default]/menu-button:-top-2 peer-data-active/menu-button:text-dashboard-text-inverse peer-hover/menu-button:text-dashboard-text-inverse"
|
|
86
|
+
>
|
|
87
|
+
{props.count > 99 ? "99+" : props.count.toLocaleString("en-US")}
|
|
88
|
+
</SidebarMenuBadge>
|
|
89
|
+
) : null}
|
|
90
|
+
</SidebarMenuItem>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function RailNavItem(props: { item: DashboardHeaderNavItem }) {
|
|
95
|
+
const active = useMatch({ end: false, path: props.item.to }) !== null;
|
|
96
|
+
return (
|
|
97
|
+
<RailItem
|
|
98
|
+
active={active}
|
|
99
|
+
count={props.item.count}
|
|
100
|
+
icon={NAV_ICONS[props.item.key] ?? Boxes}
|
|
101
|
+
label={props.item.label}
|
|
102
|
+
to={props.item.to}
|
|
103
|
+
/>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Desktop primary navigation as a shadcn icon sidebar. Mobile keeps the top
|
|
109
|
+
* bar and navigation sheet in `DashboardHeader`.
|
|
110
|
+
*/
|
|
111
|
+
export function NavRail(props: {
|
|
112
|
+
navItems: DashboardHeaderNavItem[];
|
|
113
|
+
profile?: ReactNode;
|
|
114
|
+
workspaceActive: boolean;
|
|
115
|
+
}) {
|
|
116
|
+
return (
|
|
117
|
+
<Sidebar
|
|
118
|
+
className="border-dashboard-border-strong pt-[env(safe-area-inset-top)]"
|
|
119
|
+
collapsible="icon"
|
|
120
|
+
>
|
|
121
|
+
<SidebarHeader className="items-center pt-3 pb-4">
|
|
122
|
+
<Link
|
|
123
|
+
aria-label={`${getDashboardAgentName()} home`}
|
|
124
|
+
className="grid place-items-center text-inherit no-underline"
|
|
125
|
+
to="/"
|
|
126
|
+
>
|
|
127
|
+
<JuniorLogo />
|
|
128
|
+
</Link>
|
|
129
|
+
</SidebarHeader>
|
|
130
|
+
{/* Stock icon mode hides overflow; the rail stays collapsed, so let
|
|
131
|
+
plugin pages scroll on short windows. */}
|
|
132
|
+
<SidebarContent className="group-data-[collapsible=icon]:overflow-auto">
|
|
133
|
+
<SidebarGroup className="items-center py-0">
|
|
134
|
+
<nav aria-label="Primary" className="w-full">
|
|
135
|
+
<SidebarMenu className="items-center gap-1.5">
|
|
136
|
+
<RailItem
|
|
137
|
+
active={props.workspaceActive}
|
|
138
|
+
icon={MessagesSquare}
|
|
139
|
+
label="Conversations"
|
|
140
|
+
to="/"
|
|
141
|
+
/>
|
|
142
|
+
{props.navItems.map((item) => (
|
|
143
|
+
<RailNavItem item={item} key={item.key} />
|
|
144
|
+
))}
|
|
145
|
+
</SidebarMenu>
|
|
146
|
+
</nav>
|
|
147
|
+
</SidebarGroup>
|
|
148
|
+
</SidebarContent>
|
|
149
|
+
{props.profile ? (
|
|
150
|
+
<SidebarFooter className="items-center pb-3">
|
|
151
|
+
{props.profile}
|
|
152
|
+
</SidebarFooter>
|
|
153
|
+
) : null}
|
|
154
|
+
</Sidebar>
|
|
155
|
+
);
|
|
156
|
+
}
|