@orsetra/shared-ui 1.5.14 → 1.5.16

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.
@@ -39,7 +39,7 @@ export interface MainMenuItem {
39
39
  id: string
40
40
  label: string
41
41
  icon: LucideIcon
42
- href?: string
42
+ href: string
43
43
  }
44
44
 
45
45
  export interface SubMenuItem {
@@ -69,7 +69,7 @@ export interface ApiMainMenuItem {
69
69
  id: string
70
70
  label: string
71
71
  icon: string
72
- href?: string
72
+ href: string
73
73
  }
74
74
 
75
75
  export interface ApiSubMenuItem {
@@ -300,13 +300,18 @@ function Sidebar({ currentMenu, onMainMenuToggle, sidebarMenus = {}, main_base_u
300
300
  <>
301
301
  <div className="border-t border-ui-border mx-1 my-2" />
302
302
  {filteredMainItems.map((item) => {
303
- const href = item.href!.startsWith('http://') || item.href!.startsWith('https://')
304
- ? new URL(item.href!).pathname
305
- : item.href!
303
+ const handleClick = (e: React.MouseEvent) => {
304
+ const href = item.href
305
+ if (href.startsWith('http://') || href.startsWith('https://')) {
306
+ e.preventDefault()
307
+ window.location.href = new URL(href).pathname
308
+ }
309
+ }
306
310
  const linkEl = (
307
311
  <Link
308
312
  key={item.id}
309
- href={href}
313
+ href={ item.href}
314
+ onClick={handleClick}
310
315
  className="flex items-center justify-center p-2 transition-colors border-l-4 border-transparent hover:bg-ui-background"
311
316
  >
312
317
  <item.icon
@@ -52,6 +52,7 @@ export { ScrollArea, ScrollBar } from './scroll-area'
52
52
  export { Select, SelectGroup, SelectValue, SelectTrigger, SelectContent, SelectLabel, SelectItem, SelectSeparator } from './select'
53
53
  export { Sheet, SheetTrigger, SheetContent, SheetHeader, SheetFooter, SheetTitle, SheetDescription } from './sheet'
54
54
  export { SidePanel, SidePanelTrigger, SidePanelClose, SidePanelContent, SidePanelHeader, SidePanelTitle, SidePanelDescription, SidePanelBody, SidePanelFooter } from './side-panel'
55
+ export { PushPanel, type PushPanelProps } from './push-panel'
55
56
  export { Skeleton } from './skeleton'
56
57
  export { Slider } from './slider'
57
58
  export { Toaster } from './toaster'
@@ -0,0 +1,94 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { X } from "lucide-react"
5
+ import { cn } from "../../lib/utils"
6
+
7
+ export interface PushPanelProps {
8
+ open: boolean
9
+ onOpenChange: (open: boolean) => void
10
+ title: React.ReactNode
11
+ description?: React.ReactNode
12
+ headerActions?: React.ReactNode
13
+ children: React.ReactNode
14
+ actions?: React.ReactNode
15
+ width?: string
16
+ className?: string
17
+ }
18
+
19
+ /**
20
+ * Inline push panel that slides in from the right and compresses the main
21
+ * content area, rather than overlaying it as a modal.
22
+ *
23
+ * Usage: place as a flex sibling next to the page content.
24
+ *
25
+ * ```tsx
26
+ * <div className="flex items-start min-h-screen">
27
+ * <div className="flex-1 min-w-0">{page content}</div>
28
+ * <PushPanel open={open} onOpenChange={setOpen} title="Details">
29
+ * {detail content}
30
+ * </PushPanel>
31
+ * </div>
32
+ * ```
33
+ */
34
+ export function PushPanel({
35
+ open,
36
+ onOpenChange,
37
+ title,
38
+ description,
39
+ headerActions,
40
+ children,
41
+ actions,
42
+ width = "w-[480px]",
43
+ className,
44
+ }: PushPanelProps) {
45
+ return (
46
+ <div
47
+ className={cn(
48
+ "hidden lg:flex flex-col flex-shrink-0 sticky top-0 self-start",
49
+ "h-[calc(100vh-3.5rem)] overflow-hidden",
50
+ "transition-[width] duration-300 ease-in-out",
51
+ "border-l border-ibm-gray-20 bg-white",
52
+ open ? width : "w-0",
53
+ className
54
+ )}
55
+ >
56
+ {/* Fixed-width inner wrapper prevents content reflow during animation */}
57
+ <div className={cn("flex flex-col h-full", width)}>
58
+
59
+ {/* Header */}
60
+ <div className="flex items-start justify-between px-5 py-3.5 flex-shrink-0 border-b border-ibm-gray-20">
61
+ <div className="flex-1 min-w-0 pr-3">
62
+ <p className="text-sm font-semibold text-ibm-gray-100 truncate">{title}</p>
63
+ {description && (
64
+ <p className="text-[11px] text-ibm-gray-50 mt-0.5 truncate">{description}</p>
65
+ )}
66
+ </div>
67
+ <div className="flex items-center gap-1.5 flex-shrink-0">
68
+ {headerActions}
69
+ <button
70
+ type="button"
71
+ onClick={() => onOpenChange(false)}
72
+ className="p-1 text-ibm-gray-40 hover:text-ibm-gray-70 hover:bg-ibm-gray-10 transition-colors rounded-sm"
73
+ >
74
+ <X className="h-4 w-4" />
75
+ <span className="sr-only">Close</span>
76
+ </button>
77
+ </div>
78
+ </div>
79
+
80
+ {/* Scrollable body */}
81
+ <div className="flex-1 overflow-y-auto px-5 py-4">
82
+ {children}
83
+ </div>
84
+
85
+ {/* Footer */}
86
+ {actions && (
87
+ <div className="flex items-center gap-2 px-5 py-3 flex-shrink-0 border-t border-ibm-gray-10">
88
+ {actions}
89
+ </div>
90
+ )}
91
+ </div>
92
+ </div>
93
+ )
94
+ }
@@ -59,7 +59,7 @@ const SidePanel = ({
59
59
  <SidePanelOverlay />
60
60
  <DialogPrimitive.Content
61
61
  className={cn(
62
- "fixed z-50 bg-white shadow-lg transition-transform data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:ease-out data-[state=closed]:ease-in data-[state=open]:duration-300 data-[state=closed]:duration-200 flex flex-col",
62
+ "fixed z-50 bg-white shadow-lg !translate-x-0 !translate-y-0 transition-transform data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:ease-out data-[state=closed]:ease-in data-[state=open]:duration-300 data-[state=closed]:duration-200 flex flex-col",
63
63
  side === "right" &&
64
64
  "inset-y-0 right-0 h-full w-full border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right",
65
65
  side === "left" &&
@@ -124,7 +124,7 @@ const SidePanelContent = React.forwardRef<
124
124
  <DialogPrimitive.Content
125
125
  ref={ref}
126
126
  className={cn(
127
- "fixed z-50 bg-white shadow-lg transition-transform data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:ease-out data-[state=closed]:ease-in data-[state=open]:duration-300 data-[state=closed]:duration-200 flex flex-col",
127
+ "fixed z-50 bg-white shadow-lg !translate-x-0 !translate-y-0 transition-transform data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:ease-out data-[state=closed]:ease-in data-[state=open]:duration-300 data-[state=closed]:duration-200 flex flex-col",
128
128
  side === "right" &&
129
129
  "inset-y-0 right-0 h-full w-full border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right",
130
130
  side === "left" &&
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orsetra/shared-ui",
3
- "version": "1.5.14",
3
+ "version": "1.5.16",
4
4
  "description": "Shared UI components for Orsetra platform",
5
5
  "main": "./index.ts",
6
6
  "types": "./index.ts",