2026-03-18 15:17:40 +01:00
import styles from './LayoutSection.module.css'
import { Sidebar } from '../../../design-system/layout/Sidebar/Sidebar'
2026-04-02 18:10:09 +02:00
import { SidebarTree } from '../../../design-system/layout/Sidebar/SidebarTree'
import type { SidebarTreeNode } from '../../../design-system/layout/Sidebar/SidebarTree'
import { StatusDot } from '../../../design-system/primitives/StatusDot/StatusDot'
import { Box , Settings , FileText , ChevronRight } from 'lucide-react'
2026-03-18 15:17:40 +01:00
import { TopBar } from '../../../design-system/layout/TopBar/TopBar'
2026-04-10 17:00:57 +02:00
import { SearchTrigger } from '../../../design-system/layout/TopBar/SearchTrigger'
import { AutoRefreshToggle } from '../../../design-system/layout/TopBar/AutoRefreshToggle'
2026-03-18 15:17:40 +01:00
// ── DemoCard helper ──────────────────────────────────────────────────────────
interface DemoCardProps {
id : string
title : string
description : string
children : React.ReactNode
}
function DemoCard ( { id , title , description , children } : DemoCardProps ) {
return (
< div id = { id } className = { styles . componentCard } >
< h3 className = { styles . componentTitle } > { title } < / h3 >
< p className = { styles . componentDesc } > { description } < / p >
< div className = { styles . demoArea } > { children } < / div >
< / div >
)
}
2026-04-02 18:10:09 +02:00
// ── Sample tree nodes ────────────────────────────────────────────────────────
2026-03-18 15:17:40 +01:00
2026-04-02 18:10:09 +02:00
const SAMPLE_APP_NODES : SidebarTreeNode [ ] = [
2026-03-18 15:17:40 +01:00
{
2026-03-18 17:50:41 +01:00
id : 'app1' ,
2026-04-02 18:10:09 +02:00
label : 'cameleer-prod' ,
2026-04-02 18:13:03 +02:00
icon : < StatusDot variant = "live" / > ,
2026-04-02 18:10:09 +02:00
badge : '14.3k' ,
path : '/apps/app1' ,
starrable : true ,
starKey : 'app:app1' ,
children : [
{ id : 'app1/r1' , label : 'order-ingest' , icon : < ChevronRight size = { 12 } / > , badge : '5,421' , path : '/apps/app1/r1' } ,
{ id : 'app1/r2' , label : 'payment-validate' , icon : < ChevronRight size = { 12 } / > , badge : '3,102' , path : '/apps/app1/r2' } ,
2026-03-18 17:50:41 +01:00
] ,
2026-03-18 15:17:40 +01:00
} ,
{
2026-03-18 17:50:41 +01:00
id : 'app2' ,
2026-04-02 18:10:09 +02:00
label : 'cameleer-staging' ,
2026-04-02 18:13:03 +02:00
icon : < StatusDot variant = "stale" / > ,
2026-04-02 18:10:09 +02:00
badge : '871' ,
path : '/apps/app2' ,
starrable : true ,
starKey : 'app:app2' ,
children : [
{ id : 'app2/r3' , label : 'notify-customer' , icon : < ChevronRight size = { 12 } / > , badge : '2,201' , path : '/apps/app2/r3' } ,
2026-03-18 17:50:41 +01:00
] ,
2026-03-18 15:17:40 +01:00
} ,
{
2026-03-18 17:50:41 +01:00
id : 'app3' ,
2026-04-02 18:10:09 +02:00
label : 'cameleer-dev' ,
2026-04-02 18:13:03 +02:00
icon : < StatusDot variant = "dead" / > ,
2026-04-02 18:10:09 +02:00
badge : '42' ,
path : '/apps/app3' ,
starrable : true ,
starKey : 'app:app3' ,
2026-03-18 15:17:40 +01:00
} ,
]
// ── LayoutSection ─────────────────────────────────────────────────────────────
export function LayoutSection() {
return (
< section id = "layout" className = { styles . section } >
< h2 className = { styles . sectionTitle } > Layout < / h2 >
{ /* 1. AppShell */ }
< DemoCard
id = "appshell"
title = "AppShell"
description = "Full-page shell that composes Sidebar + TopBar + main content area. Cannot be nested — shown as a structural diagram."
>
< div className = { styles . shellDiagram } >
< div className = { styles . shellDiagramTop } >
2026-03-19 16:33:34 +01:00
TopBar — breadcrumb · search · filters · time range · env badge · user avatar
2026-03-18 15:17:40 +01:00
< / div >
< div className = { styles . shellDiagramBody } >
< div className = { styles . shellDiagramSide } >
< span > Sidebar < / span >
< span style = { { fontWeight : 400 , fontSize : 10 , marginTop : 4 } } > Logo < / span >
< span style = { { fontWeight : 400 , fontSize : 10 } } > Search < / span >
< span style = { { fontWeight : 400 , fontSize : 10 } } > Navigation < / span >
2026-03-18 17:50:41 +01:00
< span style = { { fontWeight : 400 , fontSize : 10 } } > Applications tree < / span >
< span style = { { fontWeight : 400 , fontSize : 10 } } > Agents tree < / span >
< span style = { { fontWeight : 400 , fontSize : 10 } } > Starred < / span >
2026-03-18 15:17:40 +01:00
< / div >
< div className = { styles . shellDiagramMain } >
& lt ; children & gt ; — page content rendered here
< / div >
< / div >
< / div >
< / DemoCard >
{ /* 2. Sidebar */ }
< DemoCard
id = "sidebar"
title = "Sidebar"
2026-04-02 18:10:09 +02:00
description = "Composable navigation sidebar with sections, tree navigation, and icon-rail collapse mode."
2026-03-18 15:17:40 +01:00
>
< div className = { styles . sidebarPreview } >
2026-04-02 18:10:09 +02:00
< Sidebar >
< Sidebar.Header logo = { < span style = { { fontSize : 20 } } > & # x1F42A ; < / span > } title = "cameleer" version = "v3.2.1" / >
< Sidebar.Section label = "Applications" icon = { < Box size = { 14 } / > } open = { true } onToggle = { ( ) = > { } } active = { false } >
< SidebarTree nodes = { SAMPLE_APP_NODES } isStarred = { ( ) = > false } onToggleStar = { ( ) = > { } } / >
< / Sidebar.Section >
< Sidebar.Footer >
< Sidebar.FooterLink icon = { < Settings size = { 14 } / > } label = "Admin" / >
< Sidebar.FooterLink icon = { < FileText size = { 14 } / > } label = "API Docs" / >
< / Sidebar.Footer >
< / Sidebar >
2026-03-18 15:17:40 +01:00
< / div >
< / DemoCard >
{ /* 3. TopBar */ }
< DemoCard
id = "topbar"
title = "TopBar"
2026-04-10 17:00:57 +02:00
description = "Composable top navigation bar. Consumers pass children for the center slot (search, filters, etc.). Shell provides breadcrumb, theme toggle, env badge, and user menu."
2026-03-18 15:17:40 +01:00
>
< div className = { styles . topbarPreview } >
< TopBar
breadcrumb = { [
{ label : 'Dashboard' , href : '#' } ,
{ label : 'Applications' , href : '#' } ,
{ label : 'order-ingest' } ,
] }
environment = "production"
user = { { name : 'Hendrik' } }
2026-04-10 17:00:57 +02:00
>
< SearchTrigger onClick = { ( ) = > { } } / >
< AutoRefreshToggle active = { true } onChange = { ( ) = > { } } / >
< / TopBar >
2026-03-18 15:17:40 +01:00
< / div >
< / DemoCard >
< / section >
)
}