Skip to content

Commit edbbed5

Browse files
committed
feat: add AppShell and MetricWidget components with registration in ComponentRegistry
1 parent a71d308 commit edbbed5

8 files changed

Lines changed: 143 additions & 5 deletions

File tree

packages/layout/src/AppShell.tsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React from 'react';
2+
import {
3+
SidebarProvider,
4+
SidebarTrigger,
5+
SidebarInset,
6+
Sidebar
7+
} from '@object-ui/components';
8+
import { cn } from '@object-ui/components';
9+
10+
export interface AppShellProps {
11+
sidebar?: React.ReactNode;
12+
navbar?: React.ReactNode; // Top navbar content
13+
children: React.ReactNode;
14+
className?: string;
15+
defaultOpen?: boolean;
16+
}
17+
18+
export function AppShell({
19+
sidebar,
20+
navbar,
21+
children,
22+
className,
23+
defaultOpen = true,
24+
}: AppShellProps) {
25+
return (
26+
<SidebarProvider defaultOpen={defaultOpen}>
27+
{sidebar}
28+
<SidebarInset>
29+
<header className="flex h-16 shrink-0 items-center gap-2 border-b bg-background px-4">
30+
<SidebarTrigger className="-ml-1" />
31+
<div className="w-px h-4 bg-border mx-2" />
32+
{navbar}
33+
</header>
34+
<main className={cn("flex-1 overflow-auto p-4 md:p-6", className)}>
35+
{children}
36+
</main>
37+
</SidebarInset>
38+
</SidebarProvider>
39+
);
40+
}

packages/layout/src/index.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,24 @@
33
* Copyright (c) 2024-present ObjectStack Inc.
44
*/
55

6+
import { ComponentRegistry } from '@object-ui/core';
7+
68
export * from './PageHeader';
9+
export * from './AppShell';
10+
11+
import { PageHeader } from './PageHeader';
12+
import { AppShell } from './AppShell';
13+
14+
ComponentRegistry.register('page-header', PageHeader, {
15+
label: 'Page Header',
16+
category: 'Layout',
17+
inputs: [
18+
{ name: 'title', type: 'string' },
19+
{ name: 'description', type: 'string' }
20+
]
21+
});
22+
23+
ComponentRegistry.register('app-shell', AppShell, {
24+
label: 'App Shell',
25+
category: 'Layout',
26+
});

packages/plugin-dashboard/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"@object-ui/react": "workspace:*",
2626
"@object-ui/types": "workspace:*",
2727
"clsx": "^2.1.0",
28+
"lucide-react": "^0.563.0",
2829
"react": "^18.2.0",
2930
"react-dom": "^18.2.0",
3031
"tailwind-merge": "^2.2.1"
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import React from 'react';
2+
import { Card, CardContent, CardHeader, CardTitle } from '@object-ui/components';
3+
import { cn } from '@object-ui/components';
4+
import { ArrowDownIcon, ArrowUpIcon, MinusIcon } from 'lucide-react';
5+
6+
export interface MetricWidgetProps {
7+
label: string;
8+
value: string | number;
9+
trend?: {
10+
value: number;
11+
label?: string;
12+
direction?: 'up' | 'down' | 'neutral';
13+
};
14+
icon?: React.ReactNode;
15+
className?: string;
16+
description?: string;
17+
}
18+
19+
export const MetricWidget = ({
20+
label,
21+
value,
22+
trend,
23+
icon,
24+
className,
25+
description,
26+
...props
27+
}: MetricWidgetProps) => {
28+
return (
29+
<Card className={cn("h-full", className)} {...props}>
30+
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
31+
<CardTitle className="text-sm font-medium">
32+
{label}
33+
</CardTitle>
34+
{icon && <div className="h-4 w-4 text-muted-foreground">{icon}</div>}
35+
</CardHeader>
36+
<CardContent>
37+
<div className="text-2xl font-bold">{value}</div>
38+
{(trend || description) && (
39+
<p className="text-xs text-muted-foreground flex items-center mt-1">
40+
{trend && (
41+
<span className={cn(
42+
"flex items-center mr-2",
43+
trend.direction === 'up' && "text-green-500",
44+
trend.direction === 'down' && "text-red-500",
45+
trend.direction === 'neutral' && "text-yellow-500"
46+
)}>
47+
{trend.direction === 'up' && <ArrowUpIcon className="h-3 w-3 mr-1" />}
48+
{trend.direction === 'down' && <ArrowDownIcon className="h-3 w-3 mr-1" />}
49+
{trend.direction === 'neutral' && <MinusIcon className="h-3 w-3 mr-1" />}
50+
{trend.value}%
51+
</span>
52+
)}
53+
{description || trend?.label}
54+
</p>
55+
)}
56+
</CardContent>
57+
</Card>
58+
);
59+
};

packages/plugin-dashboard/src/index.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88

99
import { ComponentRegistry } from '@object-ui/core';
1010
import { DashboardRenderer } from './DashboardRenderer';
11+
import { MetricWidget } from './MetricWidget';
1112

12-
export { DashboardRenderer };
13+
export { DashboardRenderer, MetricWidget };
1314

1415
// Register dashboard component
1516
ComponentRegistry.register(
@@ -30,3 +31,17 @@ ComponentRegistry.register(
3031
}
3132
}
3233
);
34+
35+
// Register metric component
36+
ComponentRegistry.register(
37+
'metric',
38+
MetricWidget,
39+
{
40+
label: 'Metric Card',
41+
category: 'Dashboard',
42+
inputs: [
43+
{ name: 'label', type: 'string', label: 'Label' },
44+
{ name: 'value', type: 'string', label: 'Value' },
45+
]
46+
}
47+
);

packages/plugin-dashboard/tsconfig.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
"extends": "../../tsconfig.json",
33
"compilerOptions": {
44
"outDir": "./dist",
5-
"rootDir": "./src",
65
"declaration": true,
76
"declarationMap": true,
87
"composite": true,

packages/plugin-dashboard/vite.config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ export default defineConfig({
2626
'@object-ui/react',
2727
'@object-ui/types',
2828
'tailwind-merge',
29-
'clsx'
29+
'clsx',
30+
'lucide-react'
3031
],
3132
output: {
3233
globals: {

pnpm-lock.yaml

Lines changed: 5 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)