123 lines
4.0 KiB
Markdown
123 lines
4.0 KiB
Markdown
|
|
# Design System Update Instructions
|
||
|
|
|
||
|
|
These changes are needed in `@cameleer/design-system` to replace workarounds in cameleer3-server's UI.
|
||
|
|
|
||
|
|
## 1. Sidebar: Add `onNavigate` callback prop (HIGH PRIORITY)
|
||
|
|
|
||
|
|
### Problem
|
||
|
|
|
||
|
|
The Sidebar component navigates internally using React Router `<Link>` components with hardcoded paths (`/apps/:appId`, `/apps/:appId/:routeId`, `/agents/:appId/:instanceId`). The consuming app (cameleer3-server) now uses a different URL structure (`/exchanges/:appId`, `/runtime/:appId/:instanceId`) and needs to intercept and re-route sidebar navigation.
|
||
|
|
|
||
|
|
The current workaround wraps Sidebar in a `<div onClick={...} style={{ display: 'contents' }}>` that intercepts anchor clicks via event delegation and prevents default navigation. This is fragile — it depends on the Sidebar rendering `<a>` elements and breaks if the internal markup changes.
|
||
|
|
|
||
|
|
### Required Change
|
||
|
|
|
||
|
|
Add an optional `onNavigate` callback to `SidebarProps`:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
interface SidebarProps {
|
||
|
|
apps: SidebarApp[];
|
||
|
|
className?: string;
|
||
|
|
onNavigate?: (path: string) => void; // NEW
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Behavior:**
|
||
|
|
- When `onNavigate` is NOT provided: Sidebar works exactly as today (internal `<Link>` navigation). No breaking change.
|
||
|
|
- When `onNavigate` IS provided: Instead of using `<Link>` or `navigate()`, call `onNavigate(path)` with the path that would have been navigated to. The consuming app decides where to actually navigate.
|
||
|
|
|
||
|
|
**Example paths passed to `onNavigate`:**
|
||
|
|
- App click: `onNavigate('/apps/order-svc')`
|
||
|
|
- Route click: `onNavigate('/apps/order-svc/process-order')`
|
||
|
|
- Agent click: `onNavigate('/agents/order-svc/agent-1')`
|
||
|
|
|
||
|
|
The consuming app can then translate these paths to its own URL structure.
|
||
|
|
|
||
|
|
**Implementation hint:** In the Sidebar component, wherever you have `<Link to={path}>` or `navigate(path)`, check if `onNavigate` is defined. If yes, render a `<button>` or `<div>` with `onClick={() => onNavigate(path)}` instead of a `<Link>`. If no, keep the existing `<Link>` behavior.
|
||
|
|
|
||
|
|
### How the consumer will use it
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
<Sidebar
|
||
|
|
apps={sidebarApps}
|
||
|
|
onNavigate={(path) => {
|
||
|
|
// Translate /apps/x/y to /exchanges/x/y (current tab)
|
||
|
|
// Translate /agents/x/y to /runtime/x/y
|
||
|
|
const translated = translatePath(path);
|
||
|
|
navigate(translated);
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 2. DataTable: Add `fillHeight` prop (MEDIUM PRIORITY)
|
||
|
|
|
||
|
|
### Problem
|
||
|
|
|
||
|
|
When DataTable is used in a flex layout and needs to fill the remaining vertical space (with the table body scrolling and the pagination footer pinned at the bottom), the consuming app must wrap DataTable in manual flex containers:
|
||
|
|
|
||
|
|
```css
|
||
|
|
.tableSection {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
flex: 1;
|
||
|
|
min-height: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.tableScroll {
|
||
|
|
flex: 1;
|
||
|
|
min-height: 0;
|
||
|
|
overflow-y: auto;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
```jsx
|
||
|
|
<div className={styles.tableSection}>
|
||
|
|
<div className={styles.tableHeader}>...</div>
|
||
|
|
<div className={styles.tableScroll}>
|
||
|
|
<DataTable ... />
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
```
|
||
|
|
|
||
|
|
This pattern is repeated in 3 pages (Dashboard, RoutesMetrics, RouteDetail).
|
||
|
|
|
||
|
|
### Required Change
|
||
|
|
|
||
|
|
Add an optional `fillHeight` prop to `DataTableProps`:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
interface DataTableProps<T> {
|
||
|
|
// ... existing props
|
||
|
|
fillHeight?: boolean; // NEW
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Behavior when `fillHeight` is true:**
|
||
|
|
- The DataTable wrapper gets: `display: flex; flex-direction: column; flex: 1; min-height: 0`
|
||
|
|
- The scroll area (containing the `<table>`) gets: `flex: 1; min-height: 0; overflow-y: auto`
|
||
|
|
- The footer (pagination) gets: `flex-shrink: 0` (stays pinned at the bottom)
|
||
|
|
- The table header row should remain visible (sticky or outside the scroll area)
|
||
|
|
|
||
|
|
**When `fillHeight` is false/undefined:** No change to current behavior.
|
||
|
|
|
||
|
|
### How the consumer will use it
|
||
|
|
|
||
|
|
```jsx
|
||
|
|
<DataTable
|
||
|
|
columns={columns}
|
||
|
|
data={rows}
|
||
|
|
fillHeight
|
||
|
|
// ... other props
|
||
|
|
/>
|
||
|
|
```
|
||
|
|
|
||
|
|
No wrapper divs needed — DataTable manages its own height filling internally.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Version
|
||
|
|
|
||
|
|
After applying these changes, bump the package version (patch or minor) and publish. The cameleer3-server UI will then update its dependency and remove the workarounds.
|