Blocks · @jengacore/app-frame
App frame
Sidebar, top bar, ⌘K palette, theme and product signature wired together. Mount once in the root layout.
Install
terminal
npx shadcn@latest add @jengacore/app-frameWithout the namespace configured: npx shadcn@latest add https://ui.jengacore.com/r/<new-york-v4|base-nova>/app-frame.json
Source
components/blocks/app-frame.tsx
"use client"
import * as React from "react"
import { Bell, LayoutGrid, Settings } from "lucide-react"
import { Button } from "@/components/ui/button"
import { AppSidebar, useSidebarCollapsed, type NavGroup } from "@/components/jc/app-sidebar"
import { AppMain, AppShell, AppTopbar, type Crumb } from "@/components/jc/app-shell"
import { CommandPalette, useCommandShortcut, type PaletteAction } from "@/components/jc/command-palette"
import type { Environment } from "@/components/jc/env-chip"
import { useProduct, useTheme, type Product } from "@/components/jc/theme"
const DEFAULT_NAV: NavGroup[] = [
{
label: "Workspace",
items: [
{ label: "Overview", icon: LayoutGrid, href: "#", current: true },
{ label: "Settings", icon: Settings, href: "#" },
],
},
]
/**
* The frame for a jengacore product, wired: sidebar (collapsible, remembered), top bar with breadcrumbs and
* environment, ⌘K palette with Appearance, theme and product signature. Mount once in the root layout.
*/
export function AppFrame({
product,
env,
nav = DEFAULT_NAV,
crumbs = [{ label: "Overview" }],
user = { name: "Aline Uwase", role: "Operations", initials: "AU" },
pages = [],
actions = [],
linkAs,
children,
}: {
product: Product
env?: Environment
nav?: NavGroup[]
crumbs?: Crumb[]
user?: { name: string; role: string; initials: string }
pages?: PaletteAction[]
actions?: PaletteAction[]
linkAs?: React.ComponentProps<typeof AppSidebar>["linkAs"]
children: React.ReactNode
}) {
const { setTheme } = useTheme()
useProduct(product)
const [collapsed, setCollapsed] = useSidebarCollapsed()
const [open, setOpen] = React.useState(false)
useCommandShortcut(setOpen)
return (
<AppShell
sidebar={
<AppSidebar
product={product}
groups={nav}
user={user}
collapsed={collapsed}
onCollapsedChange={setCollapsed}
onSearch={() => setOpen(true)}
linkAs={linkAs}
/>
}
>
<AppTopbar
crumbs={crumbs}
env={env}
actions={
<Button variant="ghost" size="icon" aria-label="Notifications">
<Bell />
</Button>
}
/>
<AppMain>{children}</AppMain>
<CommandPalette open={open} onOpenChange={setOpen} product={product} pages={pages} actions={actions} onTheme={setTheme} />
</AppShell>
)
}