@daemoniorum/layout
v0.1.1
Published
Unified admin layout system with tabs, sidebar, command palette, and floating panels
Maintainers
Readme
@daemoniorum/layout
Unified admin layout system with tabs, sidebar, command palette, and floating panels.
Features
- Tab-based navigation - Open, close, and switch between tabs with dirty state tracking
- Sidebar icon tray - Plugin navigation with tooltips and active states
- Command palette - Fuzzy search command palette (Cmd+K / Ctrl+K)
- Resizable panels - Drag-to-resize side panels
- Floating bubbles - Pop-out panels for chat, terminals, etc.
- Recent items - Automatic tracking of recently accessed items
- Mobile responsive - Collapsible sidebar on mobile devices
- Fully typed - Complete TypeScript definitions
Installation
npm install @daemoniorum/layout lucide-react
# or
pnpm add @daemoniorum/layout lucide-reactQuick Start
import { UnifiedLayout, UnifiedUIProvider, LayoutConfig } from '@daemoniorum/layout'
import { Home, Users, Settings, FileText } from 'lucide-react'
// Define your plugins
const config: LayoutConfig = {
appName: 'My Admin',
subtitle: 'Dashboard',
plugins: [
{
id: 'dashboard',
label: 'Dashboard',
icon: Home,
panelComponent: DashboardPanel,
tabRenderer: DashboardEditor,
},
{
id: 'users',
label: 'Users',
icon: Users,
panelComponent: UsersPanel,
tabRenderer: UserEditor,
},
{
id: 'settings',
label: 'Settings',
icon: Settings,
panelComponent: SettingsPanel,
},
],
}
function App() {
return (
<UnifiedUIProvider>
<UnifiedLayout config={config} />
</UnifiedUIProvider>
)
}API Reference
Components
<UnifiedLayout>
The main layout component.
<UnifiedLayout
config={config}
headerRight={<UserMenu />}
emptyState={<CustomEmptyState />}
/>Props:
config: LayoutConfig- Layout configuration (required)headerRight?: ReactNode- Content for the right side of the headeremptyState?: ReactNode- Custom empty state when no tabs are open
<UnifiedUIProvider>
Context provider for the layout state.
<UnifiedUIProvider
storagePrefix="my-app"
maxRecentItems={15}
defaultPanelWidth={400}
>
{children}
</UnifiedUIProvider>Props:
storagePrefix?: string- Prefix for localStorage keys (default:'unified-layout')maxRecentItems?: number- Maximum recent items to track (default:10)defaultPanelWidth?: number- Default panel width in pixels (default:320)
Hooks
useUnifiedUI()
Access the layout context.
function MyComponent() {
const {
// Tabs
tabs,
activeTabId,
openTab,
closeTab,
updateTab,
// Plugins
activePlugin,
setActivePlugin,
// Command palette
commandPaletteOpen,
setCommandPaletteOpen,
// Recent items
recentItems,
removeRecentItem,
clearRecentItems,
} = useUnifiedUI()
const handleOpenUser = (userId: string) => {
openTab({
plugin: 'users',
title: `User ${userId}`,
data: { id: userId },
dirty: false,
})
}
return <button onClick={() => handleOpenUser('123')}>Open User</button>
}useCommandPalette()
Control the command palette.
function SearchButton() {
const { isOpen, open, close, toggle } = useCommandPalette()
return (
<button onClick={toggle}>
{isOpen ? 'Close' : 'Open'} Search
</button>
)
}Types
LayoutConfig
interface LayoutConfig {
appName: string
subtitle?: string
logo?: ReactNode | string
plugins: PluginConfig[]
bubbles?: BubbleConfig[]
storagePrefix?: string
maxRecentItems?: number
commands?: Command[]
theme?: LayoutTheme
}PluginConfig
interface PluginConfig {
id: string
label: string
icon: LucideIcon
panelComponent?: ComponentType
tabRenderer?: ComponentType<{ tabId: string; data: unknown }>
}BubbleConfig
interface BubbleConfig {
type: string
title: string
icon: LucideIcon
component: ComponentType
}TabContent
interface TabContent {
id: string
plugin: string
title: string
data: unknown
dirty: boolean
}Styling
The components use Tailwind CSS classes with a dark theme. You can customize the appearance by:
- CSS Variables: Override the color values in your CSS
- Theme Config: Pass a
themeobject in the config - Class Overrides: Target the
.unified-*class prefixes
/* Example: Custom accent color */
.unified-layout {
--accent-primary: #your-color;
}Floating Bubbles
Add floating panels for chat, terminals, or other auxiliary tools:
const config: LayoutConfig = {
appName: 'My Admin',
plugins: [...],
bubbles: [
{
type: 'chat',
title: 'Chat',
icon: MessageSquare,
component: ChatPanel,
},
{
type: 'terminal',
title: 'Terminal',
icon: Terminal,
component: TerminalPanel,
},
],
}Custom Commands
Add custom commands to the command palette:
const config: LayoutConfig = {
appName: 'My Admin',
plugins: [...],
commands: [
{
id: 'create-user',
title: 'Create New User',
category: 'Actions',
shortcut: '⌘N',
action: () => openCreateUserModal(),
},
{
id: 'export-data',
title: 'Export Data',
category: 'Actions',
action: () => exportData(),
},
],
}License
MIT
