@orsetra/shared-ui 1.5.27 → 1.5.29
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.
|
@@ -33,6 +33,9 @@ import {
|
|
|
33
33
|
FileText,
|
|
34
34
|
Code,
|
|
35
35
|
Cloud,
|
|
36
|
+
ArrowRightLeft,
|
|
37
|
+
ArrowLeftRight,
|
|
38
|
+
Puzzle,
|
|
36
39
|
} from "lucide-react"
|
|
37
40
|
|
|
38
41
|
export interface MainMenuItem {
|
|
@@ -126,6 +129,9 @@ const ICON_MAP: Record<string, LucideIcon> = {
|
|
|
126
129
|
// API Manager
|
|
127
130
|
Braces,
|
|
128
131
|
GitMerge,
|
|
132
|
+
ArrowRightLeft,
|
|
133
|
+
ArrowLeftRight,
|
|
134
|
+
Puzzle,
|
|
129
135
|
Database,
|
|
130
136
|
// Access
|
|
131
137
|
Users,
|
|
@@ -21,7 +21,6 @@ import {
|
|
|
21
21
|
import { Menu } from "lucide-react"
|
|
22
22
|
import { Logo } from "../../ui/logo"
|
|
23
23
|
import { type SidebarMenus, type SubMenuItem, type MainMenuItem } from "./data"
|
|
24
|
-
import { SidebarFlyout } from "./sidebar-flyout"
|
|
25
24
|
import { Skeleton } from "../skeleton"
|
|
26
25
|
|
|
27
26
|
const SIDEBAR_STORAGE_KEY = "sidebar:state"
|
|
@@ -194,17 +193,11 @@ function Sidebar({ currentMenu, onMainMenuToggle, sidebarMenus = {}, main_base_u
|
|
|
194
193
|
|| []
|
|
195
194
|
|
|
196
195
|
const isCollapsed = state === "collapsed"
|
|
197
|
-
const [flyoutMenu, setFlyoutMenu] = React.useState<string | null>(null)
|
|
198
|
-
|
|
199
196
|
const filteredMainItems = React.useMemo(() => {
|
|
200
197
|
if (!isCollapsed || mainMenuItems.length === 0) return []
|
|
201
198
|
const navIds = new Set(currentNavigation.map((n) => n.id))
|
|
202
|
-
return mainMenuItems.filter((item) =>
|
|
203
|
-
|
|
204
|
-
const hasSubItems = (sidebarMenus[item.id]?.length ?? 0) > 0
|
|
205
|
-
return hasSubItems || !!item.href
|
|
206
|
-
})
|
|
207
|
-
}, [isCollapsed, mainMenuItems, currentNavigation, currentMenu, sidebarMenus])
|
|
199
|
+
return mainMenuItems.filter((item) => item.id !== currentMenu && !navIds.has(item.id) && !!item.href)
|
|
200
|
+
}, [isCollapsed, mainMenuItems, currentNavigation, currentMenu])
|
|
208
201
|
|
|
209
202
|
return (
|
|
210
203
|
<div
|
|
@@ -299,56 +292,33 @@ function Sidebar({ currentMenu, onMainMenuToggle, sidebarMenus = {}, main_base_u
|
|
|
299
292
|
return linkEl
|
|
300
293
|
})}
|
|
301
294
|
|
|
302
|
-
{/* Main menu items — only in collapsed mode, below secondary items */}
|
|
295
|
+
{/* Main menu items — only in collapsed mode, below secondary items, neutral color */}
|
|
303
296
|
{filteredMainItems.length > 0 && (
|
|
304
297
|
<>
|
|
305
298
|
<div className="border-t border-ui-border mx-1 my-2" />
|
|
306
299
|
{filteredMainItems.map((item) => {
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
300
|
+
const handleClick = (e: React.MouseEvent) => {
|
|
301
|
+
const href = item.href ?? ""
|
|
302
|
+
if (href.startsWith("http://") || href.startsWith("https://")) {
|
|
303
|
+
e.preventDefault()
|
|
304
|
+
window.location.href = new URL(href).pathname
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
const linkEl = (
|
|
311
308
|
<Link
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
if (href.startsWith("http://") || href.startsWith("https://")) {
|
|
317
|
-
e.preventDefault()
|
|
318
|
-
window.location.href = new URL(href).pathname
|
|
319
|
-
}
|
|
320
|
-
}}
|
|
321
|
-
className="flex items-center justify-center p-2 transition-colors border-l-4 border-transparent hover:bg-ui-background w-full"
|
|
309
|
+
key={item.id}
|
|
310
|
+
href={item.href ?? "#"}
|
|
311
|
+
onClick={handleClick}
|
|
312
|
+
className="flex items-center justify-center p-2 transition-colors border-l-4 border-transparent hover:bg-ui-background"
|
|
322
313
|
>
|
|
323
314
|
<item.icon className="h-4 w-4 flex-shrink-0" style={{ color: "#8d8d8d" }} />
|
|
324
315
|
</Link>
|
|
325
316
|
)
|
|
326
|
-
|
|
327
317
|
return (
|
|
328
|
-
<
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
onMouseLeave={() => setFlyoutMenu(null)}
|
|
333
|
-
>
|
|
334
|
-
{hasSubItems ? (
|
|
335
|
-
iconBtn
|
|
336
|
-
) : (
|
|
337
|
-
<Tooltip>
|
|
338
|
-
<TooltipTrigger asChild>{iconBtn}</TooltipTrigger>
|
|
339
|
-
<TooltipContent side="right" align="center">{item.label}</TooltipContent>
|
|
340
|
-
</Tooltip>
|
|
341
|
-
)}
|
|
342
|
-
|
|
343
|
-
{/* Flyout panel */}
|
|
344
|
-
{hasSubItems && flyoutMenu === item.id && (
|
|
345
|
-
<SidebarFlyout
|
|
346
|
-
label={item.label}
|
|
347
|
-
subItems={subItems}
|
|
348
|
-
onClose={() => setFlyoutMenu(null)}
|
|
349
|
-
/>
|
|
350
|
-
)}
|
|
351
|
-
</div>
|
|
318
|
+
<Tooltip key={item.id}>
|
|
319
|
+
<TooltipTrigger asChild>{linkEl}</TooltipTrigger>
|
|
320
|
+
<TooltipContent side="right" align="center">{item.label}</TooltipContent>
|
|
321
|
+
</Tooltip>
|
|
352
322
|
)
|
|
353
323
|
})}
|
|
354
324
|
</>
|
|
@@ -12,23 +12,23 @@ interface PageHeaderProps {
|
|
|
12
12
|
|
|
13
13
|
export function PageHeader({ title, description, backLink, actions, statusNode}: PageHeaderProps) {
|
|
14
14
|
return (
|
|
15
|
-
<div
|
|
16
|
-
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-
|
|
17
|
-
<div className="flex items-center
|
|
15
|
+
<div>
|
|
16
|
+
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
|
|
17
|
+
<div className="flex items-center gap-2.5 min-w-0">
|
|
18
18
|
{backLink && (
|
|
19
19
|
<Link href={backLink} className="flex-shrink-0">
|
|
20
|
-
<ArrowLeft className="h-
|
|
20
|
+
<ArrowLeft className="h-4 w-4 text-ibm-gray-60" />
|
|
21
21
|
</Link>
|
|
22
22
|
)}
|
|
23
23
|
<div className="min-w-0">
|
|
24
|
-
<div className="flex items-center
|
|
25
|
-
<h1 className="text-
|
|
26
|
-
{statusNode && <div className="
|
|
24
|
+
<div className="flex items-center gap-2.5">
|
|
25
|
+
<h1 className="text-base font-semibold text-ibm-gray-100 truncate leading-tight">{title}</h1>
|
|
26
|
+
{statusNode && <div className="flex-shrink-0">{statusNode}</div>}
|
|
27
27
|
</div>
|
|
28
|
-
{description && <p className="text-
|
|
28
|
+
{description && <p className="text-xs text-ibm-gray-60 truncate mt-0.5">{description}</p>}
|
|
29
29
|
</div>
|
|
30
30
|
</div>
|
|
31
|
-
{actions && <div className="flex items-center
|
|
31
|
+
{actions && <div className="flex items-center gap-2 flex-shrink-0">{actions}</div>}
|
|
32
32
|
</div>
|
|
33
33
|
</div>
|
|
34
34
|
)
|