You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/dynamic-plugins/frontend-plugin-wiring.md
+142-3Lines changed: 142 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -168,7 +168,6 @@ plugins:
168
168
Up to 3 levels of nested menu items are supported.
169
169
170
170
- <menu_item_name> - A unique name in the main sidebar navigation. This can represent either a standalone menu item or a parent menu item. If it represents a plugin menu item, the name must match the corresponding path in `dynamicRoutes`. For example, if `dynamicRoutes` defines `path: /my-plugin`, the `menu_item_name` must be `my-plugin`.
171
-
172
171
- Handling Complex Paths:
173
172
- For simple paths like `path: /my-plugin`, the `menu_item_name` should be `my-plugin`.
174
173
- For more complex paths, such as multi-segment paths like `path: /metrics/users/info`, the `menu_item_name` should represent the full path in dot notation (e.g., `metrics.users.info`).
@@ -334,13 +333,11 @@ Each mount point supports additional configuration:
334
333
- `if`- Used only in `*/cards` type which renders visible content. This is passed to `<EntitySwitch.Case if={<here>}`.
335
334
336
335
The following conditions are available:
337
-
338
336
- `allOf`: All conditions must be met
339
337
- `anyOf`: At least one condition must be met
340
338
- `oneOf`: Only one condition must be met
341
339
342
340
Conditions can be:
343
-
344
341
- `isKind`: Accepts a string or a list of string with entity kinds. For example `isKind: component` will render the component only for entity of `kind: Component`.
345
342
- `isType`: Accepts a string or a list of string with entity types. For example `isType: service` will render the component only for entities of `spec.type: 'service'`.
346
343
- `hasAnnotation`: Accepts a string or a list of string with annotation keys. For example `hasAnnotation: my-annotation` will render the component only for entities that have `metadata.annotations['my-annotation']` defined.
@@ -439,6 +436,148 @@ dynamicPlugins:
439
436
440
437
Users can configure multiple application providers by adding entries to the `mountPoints` field.
441
438
439
+
### Adding application drawers
440
+
441
+
The application drawer system allows plugins to create persistent side drawers that can be opened and closed independently. Multiple drawer plugins can coexist, with RHDH automatically managing which drawer is displayed. When a user opens a drawer, any previously open drawer is automatically closed, ensuring only one drawer is visible at a time.
442
+
443
+
> **Note**: The `application/internal/drawer-state` and `application/internal/drawer-content` mount points are for internal use only and are subject to change. These will be updated with the introduction of the new frontend system.
444
+
445
+
#### Architecture Overview
446
+
447
+
The drawer system uses three key mount points:
448
+
449
+
1. **`application/provider`**: Wraps the application with the plugin's context provider that manages drawer state
450
+
2. **`application/internal/drawer-state`**: Exposes minimal drawer state (open/closed, width, close function) to RHDH
451
+
3. **`application/internal/drawer-content`**: Provides the actual content to render inside the drawer
452
+
453
+
#### Configuration Example
454
+
455
+
Below is a complete example showing how to configure a drawer plugin:
456
+
457
+
```yaml
458
+
# app-config.yaml
459
+
dynamicPlugins:
460
+
frontend:
461
+
<package_name>: # plugin package name
462
+
mountPoints:
463
+
# 1. Provider: Manages the drawer's internal state
464
+
- mountPoint: application/provider
465
+
importName: MyDrawerProvider
466
+
467
+
# 2. State Exposer: Shares drawer state with RHDH
468
+
- mountPoint: application/internal/drawer-state
469
+
importName: MyDrawerStateExposer
470
+
471
+
# 3. Content: Defines what renders inside the drawer
472
+
- mountPoint: application/internal/drawer-content
473
+
importName: MyDrawerContent
474
+
config:
475
+
id: my-drawer # Unique identifier matching the context id
The provider component wraps the application and manages the drawer's full internal state (open/closed, width, toggle methods, etc.). This is a standard React context provider.
485
+
486
+
##### `application/internal/drawer-state`
487
+
488
+
The state exposer component reads from the plugin's context and exposes only the minimal state needed by RHDH to render and coordinate the drawer. This uses a callback pattern to avoid shared dependencies between plugins and RHDH.
489
+
490
+
**Key Points:**
491
+
492
+
- Component receives `onStateChange` callback from RHDH
493
+
- Exposes exactly 5 properties:
494
+
- `id`: Unique drawer identifier
495
+
- `isDrawerOpen`: Current open/closed state
496
+
- `drawerWidth`: Current drawer width in pixels
497
+
- `setDrawerWidth`: Function to update drawer width
498
+
- `closeDrawer`: Function RHDH calls to close this drawer
499
+
- Returns `null` (doesn't render anything, only acts as a bridge)
500
+
- RHDH detects state transitions (closed→open, open→closed) automatically
501
+
- When a drawer opens, RHDH automatically closes other open drawers by calling their `closeDrawer` function
502
+
503
+
##### `application/internal/drawer-content`
504
+
505
+
The content component defines what renders inside the drawer.
506
+
507
+
**Configuration:**
508
+
509
+
- `id` (required): Unique identifier that must match the `id` in the provider's context
510
+
- `props.resizable` (optional): Boolean enabling a resize handle on the drawer (default: `false`)
511
+
512
+
#### Automatic Drawer Coordination
513
+
514
+
RHDH automatically manages drawer visibility through state transition detection:
515
+
516
+
**When a drawer opens:**
517
+
518
+
1. Plugin's internal state changes (`isDrawerOpen` becomes `true`)
519
+
2. State exposer detects the change and calls `onStateChange`
520
+
3. RHDH receives the state update and sets this drawer as active
521
+
4. RHDH automatically calls `closeDrawer()` on all other open drawers
522
+
5. Only the most recently opened drawer remains visible
523
+
524
+
**Example Scenario:**
525
+
526
+
```yaml
527
+
# Both plugins configured, but only one drawer visible at a time
# Flow: User opens Quickstart → Quickstart drawer shows
559
+
# User opens Test Drawer → Quickstart auto-closes, Test drawer shows
560
+
# User opens Quickstart → test drawer auto-closes, Quickstart shows
561
+
```
562
+
563
+
#### Resizable Drawers
564
+
565
+
Enable user-resizable drawers with the `resizable` configuration:
566
+
567
+
```yaml
568
+
- mountPoint: application/drawer-content
569
+
importName: MyDrawerContent
570
+
config:
571
+
id: my-drawer
572
+
resizable: true # Adds a drag handle on the left edge
573
+
```
574
+
575
+
When `resizable: true`, users can:
576
+
577
+
- Drag the left edge of the drawer to resize
578
+
- Changes are managed by the plugin's `setDrawerWidth` function
579
+
- Typically constrained to min/max width limits defined by the plugin
580
+
442
581
## Customizing and Adding Entity tabs
443
582
444
583
Out of the box the frontend system provides an opinionated set of tabs for catalog entity views. This set of tabs can be further customized and extended as needed via the `entityTabs` configuration:
0 commit comments