@principal-ade/panel-layouts
v0.3.0
Published
Pre-built panel layout components and workspace management for the Panel Framework
Maintainers
Readme
@principal-ade/panel-layouts
Pre-built panel layout components and workspace management for the Panel Framework
This package provides ready-to-use panel layout components, workspace presets, and persistence hooks that work with @principal-ade/panel-framework-core. Built on top of @principal-ade/panels, it adds workspace management, persistence, and pre-configured layouts from the electron-app.
🎯 Purpose
While @principal-ade/panel-framework-core provides the foundation for how panels work (registration, lifecycle, events), this package handles how panels arrange on screen (layouts, resizing, workspaces).
This package = @principal-ade/panels (layout primitives) + persistence + workspace management + preset layouts
📦 What This Package Provides
Re-exported Components (from @principal-ade/panels)
We re-export the core layout components from @principal-ade/panels for convenience:
ConfigurablePanelLayout- Main layout component supporting 2 or 3 panel configurationsTabGroup- Tab-based panel groupingPanelConfigurator- Interactive UI for configuring layoutsAnimatedResizableLayout- Lower-level resizable layout primitive- Types:
PanelLayout,PanelSlot,PanelGroup,TabsConfig,TilesConfig
These components provide:
- Resizable panels with drag handles (powered by
react-resizable-panels) - Collapsible panels with animations
- Tab groups and tile arrangements
- Theme integration with
@principal-ade/industry-theme - 2-panel and 3-panel layout support
Our Value-Add: Hooks (Extracted from electron-app)
usePanelPersistence
NEW - Extracted from electron-app
Manages saving and loading panel sizes and collapsed states:
- Saves to user preferences (Electron) or localStorage (web)
- Supports both 2-panel and 3-panel layouts
- Debounced saving (500ms) to avoid excessive writes
- Handles collapse/expand animations
- Tracks last non-zero sizes for restoring after collapse
Source: /Users/griever/Developer/electron-app/src/renderer/hooks/usePanelPersistence.ts
useWorkspace
NEW - Convenience hook
Easy workspace management:
- Load and apply workspace presets
- Switch between workspaces
- Create custom workspaces
- React hooks API for workspace state
Our Value-Add: Services (Extracted from electron-app)
WorkspaceLayoutService
NEW - Extracted from electron-app
Manages workspace presets and configurations:
- CRUD operations for custom workspaces
- Built-in workspace presets (Feed View, Code Review, etc.)
- Per-repository workspace state tracking
- Workspace switching and persistence
Source: /Users/griever/Developer/electron-app/src/renderer/services/WorkspaceLayoutService.ts
Our Value-Add: Pre-built Layouts (Extracted from electron-app)
NEW - Ready-to-use layout configurations
Ready-to-use React components wrapping ConfigurablePanelLayout with preset configurations:
FeedViewLayout
Three-panel layout optimized for repository exploration:
- Left Panel (20%): Projects, Stars, Social, Graphs
- Middle Panel (80%): Commits, README, Signals
- Right Panel: Collapsed by default
Source: /Users/griever/Developer/electron-app/src/renderer/principal-window/views/FeedView/FeedView.tsx
Other Workspace Presets (to be extracted from electron-app)
ProjectManagementLayout- Project tracking and planningCodeReviewLayout- Git changes and diffsDocumentationLayout- README and markdown focusAgentWorkLayout- AI agent interactionQualityCheckLayout- Code quality metricsDrawingLayout- Excalidraw integrationPrincipalOfficeLayout- Executive dashboard
📋 Type Definitions
Re-exported from @principal-ade/panels
// Panel Layout Structure (from @principal-ade/panels)
interface PanelLayout {
left?: PanelSlot;
middle?: PanelSlot;
right?: PanelSlot;
}
// Panel Slot Configuration
type PanelSlot = string | null | PanelGroup;
interface PanelGroup {
type: 'tabs' | 'tiles';
panels: string[];
config?: TabsConfig | TilesConfig;
}
// Tabs Configuration
interface TabsConfig {
defaultActiveTab?: number;
tabPosition?: 'top' | 'bottom' | 'left' | 'right';
centered?: boolean;
activeTabIndex?: number;
onTabChange?: (index: number) => void;
}
// Tiles Configuration
interface TilesConfig {
direction?: 'horizontal' | 'vertical' | 'grid';
columns?: number;
rows?: number;
tileSizes?: number[];
}Our New Types
// Workspace Preset (NEW)
interface WorkspacePreset {
id: string;
name: string;
description?: string;
icon?: string;
layout: PanelLayout;
defaultSizes?: {
left?: number;
middle?: number;
right?: number;
};
collapsed?: {
left?: boolean;
right?: boolean;
};
}
// Panel Persistence Options (NEW)
interface PanelPersistenceOptions {
viewKey: string;
defaultSizes: PanelSizes | TwoPanelSizes;
collapsed: PanelCollapsed | { left?: boolean };
panelType: 'three-panel' | 'two-panel';
}🚀 Proposed Usage
import { PanelHarness, globalPanelRegistry } from '@principal-ade/panel-framework-core';
import {
FeedViewLayout,
usePanelPersistence,
WorkspaceLayoutService
} from '@principal-ade/panel-layouts';
// Register your panels
globalPanelRegistry.register({
metadata: { id: 'git-changes', name: 'Git Changes' },
component: GitChangesPanel,
});
function App() {
// Use persistence hook for saving layout state
const { sizes, collapsed, handleResize } = usePanelPersistence('my-app');
return (
<PanelHarness context={context} actions={actions} events={events}>
<FeedViewLayout
defaultSizes={sizes}
collapsed={collapsed}
onResize={handleResize}
/>
</PanelHarness>
);
}Using ConfigurablePanelLayout Directly
import { ConfigurablePanelLayout } from '@principal-ade/panel-layouts';
<ConfigurablePanelLayout
panels={[
{ id: 'git-changes', content: <GitChangesPanel /> },
{ id: 'readme', content: <ReadmePanel /> },
{ id: 'commits', content: <CommitsPanel /> },
]}
layout={{
left: {
type: 'tabs',
panels: ['git-changes'],
config: { defaultActiveTab: 0, tabPosition: 'top' }
},
middle: {
type: 'tabs',
panels: ['readme', 'commits'],
config: { defaultActiveTab: 0 }
},
right: null
}}
defaultSizes={{ left: 30, middle: 70, right: 0 }}
collapsed={{ left: false, right: true }}
collapsiblePanels={{ left: true, right: false }}
showCollapseButtons={true}
onPanelResize={(sizes) => console.log('Resized:', sizes)}
/>Using Workspace Presets
import { WorkspaceLayoutService } from '@principal-ade/panel-layouts';
// Get built-in workspaces
const workspaces = WorkspaceLayoutService.getBuiltInWorkspaces();
// Apply a workspace
WorkspaceLayoutService.applyWorkspace('code-review', repositoryPath);
// Create custom workspace
WorkspaceLayoutService.createCustomWorkspace({
id: 'my-workflow',
name: 'My Custom Workflow',
layout: { /* ... */ },
defaultSizes: { left: 25, middle: 50, right: 25 }
});📁 Package Structure
@principal-ade/panel-layouts/
├── src/
│ ├── index.ts # Main entry - re-exports from @principal-ade/panels + our code
│ ├── layouts/
│ │ ├── FeedViewLayout.tsx # Pre-built feed view
│ │ ├── ProjectManagementLayout.tsx # Project management preset
│ │ ├── CodeReviewLayout.tsx # Code review preset
│ │ ├── DocumentationLayout.tsx # Documentation preset
│ │ └── index.ts
│ ├── hooks/
│ │ ├── usePanelPersistence.ts # Layout state persistence (extracted)
│ │ ├── useWorkspace.ts # Workspace management hook
│ │ └── index.ts
│ ├── services/
│ │ ├── WorkspaceLayoutService.ts # Workspace CRUD operations (extracted)
│ │ └── index.ts
│ └── types/
│ ├── workspace.types.ts # Workspace types
│ ├── persistence.types.ts # Persistence types
│ └── index.ts
├── package.json
├── tsconfig.json
├── vite.config.ts
├── README.md
└── LICENSENote: We don't duplicate ConfigurablePanelLayout, TabGroup, etc. - we re-export them from @principal-ade/panels.
🔗 Dependencies
{
"peerDependencies": {
"@principal-ade/panel-framework-core": "^0.1.0",
"react": ">=18.0.0",
"react-dom": ">=18.0.0"
},
"dependencies": {
"@principal-ade/panels": "^1.0.39",
"@principal-ade/industry-theme": "^0.1.2",
"react-resizable-panels": "^3.0.0"
}
}Architecture:
- We depend on
@principal-ade/panelsfor layout primitives (ConfigurablePanelLayout, TabGroup, etc.) @principal-ade/panelsdepends onreact-resizable-panelsfor resizing functionality- We re-export components from
@principal-ade/panelsfor convenience - We add our own persistence, workspace management, and preset layouts on top
🎨 Design Principles
1. Layered Architecture
- @principal-ade/panel-framework-core: Panel registration, lifecycle, events
- @principal-ade/panels: Layout primitives, resizing, collapsing, theming
- @principal-ade/panel-layouts (this package): Persistence, workspaces, presets
2. Reuse Over Rebuild
We build on top of proven components (@principal-ade/panels) rather than reinventing the wheel. This allows us to:
- Focus on high-value features (workspaces, persistence)
- Get resizing, animations, and theming for free
- Maintain compatibility with existing electron-app code
3. Optional Dependency
Users can use @principal-ade/panel-framework-core + @principal-ade/panels directly if they don't need workspace management.
4. Composable
All components are composable - users can:
- Use pre-built layouts as-is (
FeedViewLayout) - Use
ConfigurablePanelLayoutwith custom configs - Use
@principal-ade/panelsdirectly for full control
5. Persistence-Ready
Built-in support for saving/loading layout state to:
- localStorage (web)
- User preferences (Electron via IPC)
- Remote storage (optional extension point)
📝 Implementation Steps
Phase 1: Package Setup and Re-exports
- ✅ Set up package structure with TypeScript and Vite
- ✅ Install
@principal-ade/panelsas a dependency - ✅ Create re-export index that exposes components from
@principal-ade/panels - ✅ Configure build to output ESM/CJS with CSS
What we're doing: Setting up the foundation and making @principal-ade/panels components available through our package.
Phase 2: Extract Persistence Hook (High Priority)
- Extract
usePanelPersistencefrom electron-app - Adapt for both web (localStorage) and Electron (IPC) environments
- Add type definitions
- Write unit tests
Source File:
/Users/griever/Developer/electron-app/src/renderer/hooks/usePanelPersistence.ts
What we're doing: Adding the state persistence layer that @principal-ade/panels doesn't provide.
Phase 3: Extract Workspace Service
- Extract
WorkspaceLayoutServicefrom electron-app - Adapt for both web and Electron environments
- Define built-in workspace presets
- Create
useWorkspaceconvenience hook - Write unit tests
Source File:
/Users/griever/Developer/electron-app/src/renderer/services/WorkspaceLayoutService.ts
What we're doing: Adding workspace management for quick layout switching.
Phase 4: Create Pre-built Layout Components
- Extract FeedView layout configuration
- Create React component wrappers for each preset
- Make them configurable and extensible
- Document each preset's use case
Source Files:
/Users/griever/Developer/electron-app/src/renderer/principal-window/views/FeedView/FeedView.tsx- Workspace definitions from WorkspaceLayoutService
What we're doing: Creating ready-to-use layout components for common use cases.
Phase 5: Documentation and Publishing
- Write comprehensive usage documentation
- Create example applications (web + Electron)
- Add migration guide from electron-app
- Publish to npm as
@principal-ade/panel-layouts
🔄 Integration with electron-app
Once published, the electron-app can replace its current implementation:
- import { ConfigurablePanelLayout } from '@principal-ade/panels';
- import { usePanelPersistence } from '../hooks/usePanelPersistence';
+ import { ConfigurablePanelLayout, usePanelPersistence } from '@principal-ade/panel-layouts';Benefits:
- Shared between web and desktop
- Community can contribute improvements
- Consistent across all applications
- Easier to maintain
📚 Related Packages
- @principal-ade/panel-framework-core - Core panel system (published)
- @principal-ade/panel-layouts - This package (to be implemented)
- @principal-ade/panels - Current layout implementation in electron-app
- @principal-ade/industry-theme - Theming system used by layouts
🤝 Contributing
This package is designed to be the standard layout system for Panel Framework applications. Contributions should focus on:
- Performance - Layouts should be fast and responsive
- Flexibility - Support various use cases and customization
- Accessibility - Keyboard navigation, screen reader support
- Documentation - Clear examples and API docs
📄 License
MIT
🚧 Current Status
Status: 🚧 In Active Development
This package is being actively developed with a focus on reusing @principal-ade/panels and adding workspace/persistence features.
Implementation Progress:
- ✅ README specification complete
- ✅ Package setup and build configuration (Vite + TypeScript)
- ✅ Re-exports from @principal-ade/panels (25+ components)
- ✅
usePanelPersistencehook extracted and adapted - ✅
LocalStoragePersistenceAdapterfor web apps - ✅ Storybook with interactive component stories
- ✅ ESLint + TypeScript linting configured
- ✅ Vitest test suite (14 tests passing)
- ⏳ Extract
WorkspaceLayoutService(next) - ⏳ Create pre-built layout components
- ⏳ Additional documentation and examples
- ⏳ Publish to npm
Architecture Decision:
We're reusing @principal-ade/[email protected] as a dependency rather than rebuilding layout components. This allows us to:
- Focus on high-value features (persistence, workspaces, presets)
- Leverage proven, tested layout components
- Maintain compatibility with existing electron-app code
What's Working Now:
# Development
npm run dev # Start Vite dev server
npm run storybook # Start Storybook on :6006
# Quality Checks
npm run type-check # TypeScript type checking ✅
npm run lint # ESLint (2 warnings) ✅
npm run test # Vitest (14/14 passing) ✅
# Build
npm run build # Build ESM + CJS + types ✅Package Contents:
- Re-exported: All components from @principal-ade/panels
- New:
usePanelPersistencehook with localStorage adapter - New: Comprehensive TypeScript types
- New: Interactive Storybook documentation
Reference Files (electron-app):
- Persistence:
/Users/griever/Developer/electron-app/src/renderer/hooks/usePanelPersistence.ts - Workspace Service:
/Users/griever/Developer/electron-app/src/renderer/services/WorkspaceLayoutService.ts - FeedView Layout:
/Users/griever/Developer/electron-app/src/renderer/principal-window/views/FeedView/FeedView.tsx
