@object-ui/layout 0.5.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,110 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import React from 'react';
3
+ import { AppShell, PageHeader, ResponsiveGrid } from '@object-ui/layout';
4
+ import { Card, CardContent, CardHeader, CardTitle, Button } from '@object-ui/components';
5
+
6
+ /**
7
+ * AppShell responsive layout stories.
8
+ * Demonstrates the shell + responsive grid working together.
9
+ *
10
+ * Part of Q1 2026 roadmap §1.3 — Responsive layout stories in Storybook.
11
+ */
12
+ const meta = {
13
+ title: 'Layout/AppShell',
14
+ component: AppShell,
15
+ parameters: {
16
+ layout: 'fullscreen',
17
+ docs: {
18
+ description: {
19
+ component:
20
+ 'The application shell provides a sidebar + main content area. ' +
21
+ 'Combine with ResponsiveGrid for fully responsive page layouts.',
22
+ },
23
+ },
24
+ },
25
+ tags: ['autodocs'],
26
+ } satisfies Meta<typeof AppShell>;
27
+
28
+ export default meta;
29
+ type Story = StoryObj<typeof meta>;
30
+
31
+ function SampleSidebar() {
32
+ return (
33
+ <nav className="p-4 space-y-2" aria-label="Main navigation">
34
+ {['Dashboard', 'Contacts', 'Tasks', 'Reports', 'Settings'].map((item) => (
35
+ <div
36
+ key={item}
37
+ className="px-3 py-2 rounded-md text-sm hover:bg-accent cursor-pointer"
38
+ >
39
+ {item}
40
+ </div>
41
+ ))}
42
+ </nav>
43
+ );
44
+ }
45
+
46
+ function MetricCard({ title, value }: { title: string; value: string }) {
47
+ return (
48
+ <Card>
49
+ <CardHeader className="pb-2">
50
+ <CardTitle className="text-sm font-medium text-muted-foreground">{title}</CardTitle>
51
+ </CardHeader>
52
+ <CardContent>
53
+ <div className="text-2xl font-bold">{value}</div>
54
+ </CardContent>
55
+ </Card>
56
+ );
57
+ }
58
+
59
+ export const ResponsiveDashboard: Story = {
60
+ name: 'Responsive Dashboard',
61
+ args: {
62
+ sidebar: <SampleSidebar />,
63
+ children: (
64
+ <div className="p-6 space-y-6">
65
+ <PageHeader
66
+ title="Dashboard"
67
+ description="Key metrics overview"
68
+ action={<Button size="sm">Export</Button>}
69
+ />
70
+ <ResponsiveGrid columns={{ xs: 1, sm: 2, xl: 4 }} gap={4}>
71
+ <MetricCard title="Revenue" value="$45,231" />
72
+ <MetricCard title="Users" value="2,350" />
73
+ <MetricCard title="Orders" value="1,247" />
74
+ <MetricCard title="Growth" value="+12.5%" />
75
+ </ResponsiveGrid>
76
+ <ResponsiveGrid columns={{ xs: 1, lg: 2 }} gap={4}>
77
+ <Card>
78
+ <CardHeader><CardTitle>Recent Activity</CardTitle></CardHeader>
79
+ <CardContent><div className="h-48 bg-muted rounded" /></CardContent>
80
+ </Card>
81
+ <Card>
82
+ <CardHeader><CardTitle>Analytics</CardTitle></CardHeader>
83
+ <CardContent><div className="h-48 bg-muted rounded" /></CardContent>
84
+ </Card>
85
+ </ResponsiveGrid>
86
+ </div>
87
+ ),
88
+ },
89
+ };
90
+
91
+ export const MinimalShell: Story = {
92
+ name: 'Minimal (No Sidebar)',
93
+ args: {
94
+ children: (
95
+ <div className="p-6">
96
+ <PageHeader title="Settings" description="Manage your preferences" />
97
+ <ResponsiveGrid columns={{ xs: 1, md: 2 }} gap={4}>
98
+ <Card>
99
+ <CardHeader><CardTitle>Profile</CardTitle></CardHeader>
100
+ <CardContent><div className="h-32 bg-muted rounded" /></CardContent>
101
+ </Card>
102
+ <Card>
103
+ <CardHeader><CardTitle>Security</CardTitle></CardHeader>
104
+ <CardContent><div className="h-32 bg-muted rounded" /></CardContent>
105
+ </Card>
106
+ </ResponsiveGrid>
107
+ </div>
108
+ ),
109
+ },
110
+ };
@@ -0,0 +1,110 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import React from 'react';
3
+ import { ResponsiveGrid } from '@object-ui/layout';
4
+ import { Card, CardContent, CardHeader, CardTitle } from '@object-ui/components';
5
+
6
+ /**
7
+ * ResponsiveGrid stories demonstrating spec-aligned responsive layouts.
8
+ * Uses BreakpointColumnMapSchema to configure columns per breakpoint.
9
+ *
10
+ * Part of Q1 2026 roadmap §1.3 — Responsive layout stories in Storybook.
11
+ */
12
+ const meta = {
13
+ title: 'Layout/ResponsiveGrid',
14
+ component: ResponsiveGrid,
15
+ parameters: {
16
+ layout: 'padded',
17
+ docs: {
18
+ description: {
19
+ component:
20
+ 'A responsive grid layout that consumes @objectstack/spec BreakpointColumnMapSchema. ' +
21
+ 'Columns adjust automatically at each breakpoint using pure Tailwind CSS.',
22
+ },
23
+ },
24
+ },
25
+ tags: ['autodocs'],
26
+ } satisfies Meta<typeof ResponsiveGrid>;
27
+
28
+ export default meta;
29
+ type Story = StoryObj<typeof meta>;
30
+
31
+ /** Placeholder card for demos */
32
+ function DemoCard({ label }: { label: string }) {
33
+ return (
34
+ <Card>
35
+ <CardHeader className="p-4">
36
+ <CardTitle className="text-sm">{label}</CardTitle>
37
+ </CardHeader>
38
+ <CardContent className="p-4 pt-0">
39
+ <div className="h-16 rounded bg-muted" />
40
+ </CardContent>
41
+ </Card>
42
+ );
43
+ }
44
+
45
+ const items = Array.from({ length: 6 }, (_, i) => (
46
+ <DemoCard key={i} label={`Card ${i + 1}`} />
47
+ ));
48
+
49
+ // --- Stories ---
50
+
51
+ export const Default: Story = {
52
+ args: {
53
+ columns: { xs: 1, sm: 2, lg: 3 },
54
+ gap: 4,
55
+ children: items,
56
+ },
57
+ };
58
+
59
+ export const SingleColumn: Story = {
60
+ args: {
61
+ columns: { xs: 1 },
62
+ gap: 4,
63
+ children: items.slice(0, 3),
64
+ },
65
+ };
66
+
67
+ export const TwoColumns: Story = {
68
+ args: {
69
+ columns: { xs: 1, sm: 2 },
70
+ gap: 4,
71
+ children: items.slice(0, 4),
72
+ },
73
+ };
74
+
75
+ export const FourColumnGrid: Story = {
76
+ args: {
77
+ columns: { xs: 1, sm: 2, md: 3, lg: 4 },
78
+ gap: 4,
79
+ children: items,
80
+ },
81
+ };
82
+
83
+ export const DashboardLayout: Story = {
84
+ name: 'Dashboard Layout (1 → 2 → 4)',
85
+ args: {
86
+ columns: { xs: 1, sm: 2, xl: 4 },
87
+ gap: 6,
88
+ children: Array.from({ length: 8 }, (_, i) => (
89
+ <DemoCard key={i} label={`Metric ${i + 1}`} />
90
+ )),
91
+ },
92
+ };
93
+
94
+ export const CompactGap: Story = {
95
+ name: 'Compact Gap (gap-2)',
96
+ args: {
97
+ columns: { xs: 2, md: 3 },
98
+ gap: 2,
99
+ children: items,
100
+ },
101
+ };
102
+
103
+ export const WideGap: Story = {
104
+ name: 'Wide Gap (gap-8)',
105
+ args: {
106
+ columns: { xs: 1, md: 2 },
107
+ gap: 8,
108
+ children: items.slice(0, 4),
109
+ },
110
+ };