@orsetra/shared-ui 1.0.60 → 1.0.62

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.
@@ -30,3 +30,4 @@ export {
30
30
  // Skeleton is exported from ../ui to avoid duplicate exports
31
31
  export { RootLayoutWrapper, ibmPlexSans, ibmPlexMono } from './root-layout-wrapper'
32
32
  export { LayoutContainer } from './layout-container'
33
+ export { PageWithSidePanel } from './page-with-side-panel'
@@ -0,0 +1,110 @@
1
+ "use client"
2
+
3
+ import { ReactNode, useState } from "react"
4
+ import { X, ChevronLeft } from "lucide-react"
5
+ import { Button } from "../ui/button"
6
+
7
+ interface PageWithSidePanelProps {
8
+ children: ReactNode
9
+ sidePanel?: ReactNode
10
+ sidePanelHeader?: ReactNode
11
+ sidePanelWidth?: "sm" | "md" | "lg"
12
+ closable?: boolean
13
+ defaultOpen?: boolean
14
+ showBorder?: boolean
15
+ onClose?: () => void
16
+ onOpen?: () => void
17
+ }
18
+
19
+ const PANEL_WIDTHS = {
20
+ sm: "w-64", // 256px
21
+ md: "w-72", // 288px
22
+ lg: "w-80", // 320px
23
+ }
24
+
25
+ const PANEL_PADDING = {
26
+ sm: "lg:pr-64",
27
+ md: "lg:pr-72",
28
+ lg: "lg:pr-80",
29
+ }
30
+
31
+ export function PageWithSidePanel({
32
+ children,
33
+ sidePanel,
34
+ sidePanelHeader,
35
+ sidePanelWidth = "md",
36
+ closable = false,
37
+ defaultOpen = true,
38
+ showBorder = true,
39
+ onClose,
40
+ onOpen
41
+ }: PageWithSidePanelProps) {
42
+ const [isOpen, setIsOpen] = useState(defaultOpen)
43
+ const panelWidthClass = PANEL_WIDTHS[sidePanelWidth]
44
+ const panelPaddingClass = PANEL_PADDING[sidePanelWidth]
45
+
46
+ const handleClose = () => {
47
+ setIsOpen(false)
48
+ onClose?.()
49
+ }
50
+
51
+ const handleOpen = () => {
52
+ setIsOpen(true)
53
+ onOpen?.()
54
+ }
55
+
56
+ return (
57
+ <div className="min-h-screen bg-white overflow-hidden">
58
+ {/* Main content */}
59
+ <div className={`w-full px-6 py-8 transition-all duration-300 ${sidePanel && isOpen ? panelPaddingClass : ''}`}>
60
+ {children}
61
+ </div>
62
+
63
+ {/* Side panel - fixed */}
64
+ {sidePanel && (
65
+ <>
66
+ <div
67
+ className={`hidden lg:block ${panelWidthClass} flex-shrink-0 fixed top-14 bottom-0 right-0 bg-white flex flex-col ${showBorder ? 'border-l border-ibm-gray-40' : ''} transition-transform duration-300 ease-in-out ${
68
+ isOpen ? 'translate-x-0' : 'translate-x-full'
69
+ }`}
70
+ >
71
+ {/* Header */}
72
+ {(sidePanelHeader || closable) && (
73
+ <div className="flex items-center justify-between p-4 border-b border-ibm-gray-20 flex-shrink-0">
74
+ <div className="flex-1">
75
+ {sidePanelHeader}
76
+ </div>
77
+ {closable && (
78
+ <Button
79
+ variant="ghost"
80
+ size="xs"
81
+ onClick={handleClose}
82
+ className="h-8 w-8 p-0 ml-2"
83
+ >
84
+ <X className="h-4 w-4" />
85
+ </Button>
86
+ )}
87
+ </div>
88
+ )}
89
+
90
+ {/* Content */}
91
+ <div className="flex-1 overflow-y-auto">
92
+ {sidePanel}
93
+ </div>
94
+ </div>
95
+
96
+ {/* Toggle button - shown when panel is closed */}
97
+ {closable && !isOpen && (
98
+ <button
99
+ onClick={handleOpen}
100
+ className="hidden lg:flex fixed top-1/2 right-0 -translate-y-1/2 items-center justify-center w-8 h-16 bg-white border border-ibm-gray-40 border-r-0 rounded-l-lg shadow-md hover:bg-ibm-gray-10 transition-colors duration-200"
101
+ aria-label="Open side panel"
102
+ >
103
+ <ChevronLeft className="h-5 w-5 text-ibm-gray-70" />
104
+ </button>
105
+ )}
106
+ </>
107
+ )}
108
+ </div>
109
+ )
110
+ }
@@ -145,8 +145,8 @@ export function MainSidebar({
145
145
  </button>
146
146
 
147
147
  {isMinimized && hoveredMenu === item.id && sidebarMenus[item.id] && sidebarMenus[item.id].length > 0 && (
148
- <div className="absolute left-full top-0 ml-2 bg-gray-50 rounded-lg shadow-xl z-50 min-w-[200px] py-2">
149
- <div className="px-4 py-2 bg-gray-50">
148
+ <div className="absolute left-full top-0 ml-2 bg-white rounded-lg shadow-xl z-50 min-w-[200px] py-2">
149
+ <div className="px-4 py-2">
150
150
  <h3 className="text-sm font-semibold text-text-primary">{item.label}</h3>
151
151
  </div>
152
152
  <div className="py-1">
@@ -272,7 +272,7 @@ function Sidebar({ currentMenu, onMainMenuToggle, sidebarMenus = {}, main_base_u
272
272
  </nav>
273
273
 
274
274
  {/* Footer - Menu Paramètres */}
275
- <div className="relative border-t border-ui-border px-3 py-3" ref={settingsRef}>
275
+ <div className="relative border-ui-border px-3 py-3" ref={settingsRef}>
276
276
  {/* Dropdown vers le haut */}
277
277
  {settingsOpen && (
278
278
  <div className="absolute bottom-full left-2 right-2 mb-1 bg-white border border-ui-border rounded-none shadow-lg z-50">
@@ -4,32 +4,28 @@ import type { ReactNode } from "react"
4
4
 
5
5
  interface PageHeaderProps {
6
6
  title: string
7
- description?: string
8
7
  backLink?: string
9
8
  actions?: ReactNode
10
9
  statusNode?: ReactNode
11
10
  }
12
11
 
13
- export function PageHeader({ title, description, backLink, actions, statusNode}: PageHeaderProps) {
12
+ export function PageHeader({ title, backLink, actions, statusNode}: PageHeaderProps) {
14
13
  return (
15
- <div className="mb-4 sm:mb-8">
16
- <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
14
+ <div className="sticky top-0 z-10 bg-white border-b border-gray-200 -mx-6 px-6 py-3 mb-6">
15
+ <div className="flex items-center justify-between gap-4">
17
16
  <div className="flex items-center space-x-3 min-w-0">
18
17
  {backLink && (
19
18
  <Link href={backLink} className="flex-shrink-0">
20
- <ArrowLeft className="h-5 w-5 sm:h-6 sm:w-6 text-text-secondary" />
19
+ <ArrowLeft className="h-4 w-4 text-text-secondary" />
21
20
  </Link>
22
21
  )}
23
- <div className="min-w-0">
24
- <div className="flex items-center space-x-3">
25
- <h1 className="text-xl sm:text-2xl font-semibold text-text-primary truncate">{title}</h1>
26
- {statusNode && <div className="mt-2 flex-shrink-0">{statusNode}</div>}
27
- </div>
28
- {description && <p className="text-sm sm:text-base text-text-secondary line-clamp-2">{description}</p>}
22
+ <div className="flex items-center space-x-3 min-w-0">
23
+ <h2 className="text-base font-semibold text-text-primary truncate">{title}</h2>
24
+ {statusNode && <div className="flex-shrink-0">{statusNode}</div>}
29
25
  </div>
30
26
  </div>
31
- {actions && <div className="flex items-center space-x-2 sm:space-x-4 flex-shrink-0">{actions}</div>}
27
+ {actions && <div className="flex items-center space-x-2 flex-shrink-0">{actions}</div>}
32
28
  </div>
33
29
  </div>
34
30
  )
35
- }
31
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orsetra/shared-ui",
3
- "version": "1.0.60",
3
+ "version": "1.0.62",
4
4
  "description": "Shared UI components for Orsetra platform",
5
5
  "main": "./index.ts",
6
6
  "types": "./index.ts",