-
Notifications
You must be signed in to change notification settings - Fork 7
Open
Description
Summary
Add support for grouping widgets into named sections within a dashboard layout.
Each section has an editable label and contains its own grid of widgets. Widgets
can be dragged between sections.
Motivation
Current dashboards use a single flat grid for all widgets. Users have expressed
the need to organize widgets into logical groups (e.g., "Performance",
"Security", "Inventory") with visible section headers. This improves scannability
and allows dashboard authors to create meaningful visual hierarchy.
Proposed Data Model
New Types
interface SectionConfig {
/** Unique identifier for the section */
id: string;
/** Display label (editable by users) */
label: string;
/** Sort order of the section within the dashboard */
order: number;
/** Whether the section is collapsed */
isCollapsed?: boolean;
}
interface SectionedTemplateConfig {
/** Section metadata */
sections: SectionConfig[];
/** Layouts keyed by section ID, then by breakpoint */
layouts: Record<string, ExtendedTemplateConfig>;
}
Example
const template: SectionedTemplateConfig = {
sections: [
{ id: 'performance', label: 'Performance', order: 0 },
{ id: 'security', label: 'Security', order: 1 },
],
layouts: {
performance: {
xl: [
{ i: 'cpu-widget#1', x: 0, y: 0, w: 2, h: 3, widgetType: 'cpu-widget',
title: 'CPU Usage' },
{ i: 'memory-widget#1', x: 2, y: 0, w: 2, h: 3, widgetType:
'memory-widget', title: 'Memory' },
],
// lg, md, sm...
},
security: {
xl: [
{ i: 'alerts-widget#1', x: 0, y: 0, w: 2, h: 4, widgetType:
'alerts-widget', title: 'Active Alerts' },
],
// lg, md, sm...
},
},
};
Proposed Component API
SectionedLayout
A new top-level component that renders multiple GridLayout instances, one per
section.
interface SectionedLayoutProps {
/** Widget mapping definition (shared across all sections) */
widgetMapping: WidgetMapping;
/** Sectioned template configuration */
template: SectionedTemplateConfig;
/** Callback when template changes (layout moves, section edits, cross-section
drags) */
onTemplateChange?: (template: SectionedTemplateConfig) => void;
/** Whether the layout is locked */
isLayoutLocked?: boolean;
/** Whether section labels are editable */
isSectionLabelEditable?: boolean;
/** Whether sections can be collapsed */
isSectionCollapsible?: boolean;
/** Whether widgets can be dragged between sections */
allowCrossSectionDrag?: boolean;
/** Analytics tracker */
analytics?: AnalyticsTracker;
}
SectionHeader
An internal component (also exported for standalone use) rendering the editable
section label.
interface SectionHeaderProps {
/** Section configuration */
section: SectionConfig;
/** Callback when label is edited */
onLabelChange?: (sectionId: string, newLabel: string) => void;
/** Callback when collapse is toggled */
onCollapseToggle?: (sectionId: string) => void;
/** Whether the label is editable */
isEditable?: boolean;
/** Whether the section is collapsible */
isCollapsible?: boolean;
}
Usage
<SectionedLayout
widgetMapping={widgetMapping}
template={sectionedTemplate}
onTemplateChange={setSectionedTemplate}
isSectionLabelEditable
isSectionCollapsible
allowCrossSectionDrag
/>
Implementation Considerations
Cross-Section Drag and Drop
- Each section contains its own GridLayout (and thus its own react-grid-layout
instance)
- Cross-section drag requires coordinating between two separate grid instances
- Approach: when a widget is dragged out of one section, remove it from the
source section's layout and add it to the target section's layout via drop
handlers
- react-grid-layout supports external drops via onDrop / isDroppable, which can
be leveraged here
Backwards Compatibility
- SectionedLayout is a new component — the existing GridLayout and WidgetLayout
remain unchanged
- Consumers using the flat ExtendedTemplateConfig are unaffected
- A utility function flatToSectioned(template, sectionId?) could help migrate
existing templates
Section Management
- Adding/removing/reordering sections should be handled via onTemplateChange
- Consider providing helper utilities: addSection, removeSection, reorderSections
- Empty sections could show a drop zone placeholder
Drawer Integration
- The WidgetDrawer should work with SectionedLayout — dragging a widget from the
drawer into a specific section
- The drawer's filtering (hiding already-used widgets) needs to account for
widgets across all sections
Acceptance Criteria
- New SectionedTemplateConfig type with sections and per-section layouts
- SectionedLayout component renders multiple grids with section headers
- Section labels are inline-editable when isSectionLabelEditable is true
- Sections can be collapsed/expanded when isSectionCollapsible is true
- Widgets can be dragged between sections when allowCrossSectionDrag is true
- WidgetDrawer integrates with sectioned layouts (drop into specific section)
- Existing GridLayout / WidgetLayout APIs remain unchanged
- Unit tests for section CRUD operations and cross-section drag
- Documentation example demonstrating sectioned layoutReactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels