@ttoss/layouts 0.4.37 → 0.5.1
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.
- package/README.md +138 -23
- package/dist/esm/index.js +69 -11
- package/dist/index.d.ts +8 -0
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @ttoss/layouts
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Professional layout components for React applications with responsive design and accessibility built-in.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -8,51 +8,166 @@
|
|
|
8
8
|
pnpm add @ttoss/layouts @ttoss/ui @emotion/react
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Available Layouts
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
### StackedLayout - Simple Vertical Layout
|
|
14
|
+
|
|
15
|
+
Perfect for traditional websites with header, main content, and footer.
|
|
14
16
|
|
|
15
17
|
```tsx
|
|
16
18
|
import { Layout, StackedLayout } from '@ttoss/layouts';
|
|
17
19
|
|
|
18
20
|
const App = () => (
|
|
19
21
|
<StackedLayout>
|
|
20
|
-
<Layout.Header>
|
|
21
|
-
<Layout.Main>
|
|
22
|
-
<Layout.Footer>
|
|
22
|
+
<Layout.Header>Navigation & Branding</Layout.Header>
|
|
23
|
+
<Layout.Main>Page Content</Layout.Main>
|
|
24
|
+
<Layout.Footer>Copyright & Links</Layout.Footer>
|
|
23
25
|
</StackedLayout>
|
|
24
26
|
);
|
|
25
27
|
```
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
### SidebarCollapseLayout - Dashboard & Admin Interfaces
|
|
30
|
+
|
|
31
|
+
Responsive sidebar that collapses on mobile, perfect for dashboards and admin panels.
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import { Layout, SidebarCollapseLayout } from '@ttoss/layouts';
|
|
35
|
+
|
|
36
|
+
const Dashboard = () => (
|
|
37
|
+
<SidebarCollapseLayout>
|
|
38
|
+
<Layout.Header showSidebarButton>App Header with Menu Toggle</Layout.Header>
|
|
39
|
+
<Layout.Sidebar>Navigation Menu</Layout.Sidebar>
|
|
40
|
+
<Layout.Main.Header>Page Title & Actions</Layout.Main.Header>
|
|
41
|
+
<Layout.Main>Dashboard Content</Layout.Main>
|
|
42
|
+
<Layout.Main.Footer>Status Bar</Layout.Main.Footer>
|
|
43
|
+
</SidebarCollapseLayout>
|
|
44
|
+
);
|
|
45
|
+
```
|
|
28
46
|
|
|
29
|
-
|
|
47
|
+
## Core Components
|
|
30
48
|
|
|
31
|
-
|
|
49
|
+
### Layout.Main Sub-Components
|
|
32
50
|
|
|
33
|
-
|
|
51
|
+
Enhanced main content area with optional header and footer sections.
|
|
34
52
|
|
|
35
53
|
```tsx
|
|
36
|
-
|
|
54
|
+
<Layout.Main.Header>
|
|
55
|
+
<h1>Page Title</h1>
|
|
56
|
+
<button>Action Button</button>
|
|
57
|
+
</Layout.Main.Header>
|
|
58
|
+
|
|
59
|
+
<Layout.Main>
|
|
60
|
+
Main content with consistent padding and overflow handling
|
|
61
|
+
</Layout.Main>
|
|
62
|
+
|
|
63
|
+
<Layout.Main.Footer>
|
|
64
|
+
<span>Last updated: Today</span>
|
|
65
|
+
</Layout.Main.Footer>
|
|
66
|
+
```
|
|
37
67
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
68
|
+
## Automatic Layout Composition
|
|
69
|
+
|
|
70
|
+
**Key Concept**: Layout components automatically detect and organize their child components by `displayName`, even when components are distributed across different files or routing structures.
|
|
71
|
+
|
|
72
|
+
### React Router Integration
|
|
73
|
+
|
|
74
|
+
Perfect for apps where layout components come from different routes:
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
// App.tsx - Layout wrapper
|
|
78
|
+
import { Layout, SidebarCollapseLayout } from '@ttoss/layouts';
|
|
79
|
+
import { Outlet } from 'react-router-dom';
|
|
80
|
+
|
|
81
|
+
const AppLayout = () => (
|
|
82
|
+
<SidebarCollapseLayout>
|
|
83
|
+
<AppHeader />
|
|
84
|
+
<AppSidebar />
|
|
85
|
+
<Outlet /> {/* Routes render here */}
|
|
86
|
+
</SidebarCollapseLayout>
|
|
42
87
|
);
|
|
43
88
|
|
|
44
|
-
|
|
89
|
+
// pages/Dashboard.tsx - Page-specific components
|
|
90
|
+
const Dashboard = () => (
|
|
91
|
+
<>
|
|
92
|
+
<Layout.Main.Header>
|
|
93
|
+
<h1>Dashboard</h1>
|
|
94
|
+
</Layout.Main.Header>
|
|
95
|
+
<Layout.Main>
|
|
96
|
+
<DashboardCharts />
|
|
97
|
+
</Layout.Main>
|
|
98
|
+
<Layout.Main.Footer>Last updated: {lastUpdate}</Layout.Main.Footer>
|
|
99
|
+
</>
|
|
100
|
+
);
|
|
101
|
+
```
|
|
45
102
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
103
|
+
The layout **automatically composes** itself by finding components with matching `displayName` properties, regardless of component hierarchy or file structure.
|
|
104
|
+
|
|
105
|
+
### Component Detection System
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
// These components can be anywhere in your component tree:
|
|
109
|
+
<Layout.Header /> // → Detected as "Header"
|
|
110
|
+
<Layout.Sidebar /> // → Detected as "Sidebar"
|
|
111
|
+
<Layout.Main /> // → Detected as "Main"
|
|
112
|
+
<Layout.Footer /> // → Detected as "Footer"
|
|
113
|
+
<Layout.Main.Header /> // → Detected as "MainHeader"
|
|
114
|
+
<Layout.Main.Footer /> // → Detected as "MainFooter"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Component Properties
|
|
118
|
+
|
|
119
|
+
### Responsive Behavior
|
|
120
|
+
|
|
121
|
+
- **Desktop**: Sidebar remains visible, toggleable via button
|
|
122
|
+
- **Mobile**: Sidebar becomes slide-out drawer, auto-closes on navigation
|
|
123
|
+
- **Accessible**: Full keyboard navigation and screen reader support
|
|
124
|
+
|
|
125
|
+
### Styling Integration
|
|
126
|
+
|
|
127
|
+
All components integrate seamlessly with `@ttoss/ui` theme system via `sx` prop:
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
<Layout.Header
|
|
131
|
+
sx={{
|
|
132
|
+
backgroundColor: 'brand.primary',
|
|
133
|
+
borderBottom: '2px solid',
|
|
134
|
+
}}
|
|
135
|
+
>
|
|
136
|
+
Custom styled header
|
|
137
|
+
</Layout.Header>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Advanced Usage
|
|
141
|
+
|
|
142
|
+
### Custom Components with displayName
|
|
143
|
+
|
|
144
|
+
Create reusable layout components by preserving the required `displayName`:
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
const AppHeader = ({ children, ...props }) => (
|
|
148
|
+
<Layout.Header {...props}>
|
|
149
|
+
<Logo />
|
|
150
|
+
{children}
|
|
151
|
+
<UserMenu />
|
|
152
|
+
</Layout.Header>
|
|
52
153
|
);
|
|
154
|
+
|
|
155
|
+
AppHeader.displayName = Layout.Header.displayName; // Required for layout detection
|
|
53
156
|
```
|
|
54
157
|
|
|
55
|
-
|
|
158
|
+
### Sidebar with Logo Slot
|
|
159
|
+
|
|
160
|
+
Add branding or controls to the sidebar area:
|
|
161
|
+
|
|
162
|
+
```tsx
|
|
163
|
+
<Layout.Header sidebarSlot={<CompanyLogo />} showSidebarButton>
|
|
164
|
+
Main header content
|
|
165
|
+
</Layout.Header>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Examples
|
|
169
|
+
|
|
170
|
+
View complete examples in [Storybook](https://storybook.ttoss.dev/?path=/story/layouts-layout).
|
|
56
171
|
|
|
57
172
|
## License
|
|
58
173
|
|
package/dist/esm/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
2
|
|
|
3
3
|
// src/components/Layout.tsx
|
|
4
|
-
import { Box as
|
|
4
|
+
import { Box as Box7, Container } from "@ttoss/ui";
|
|
5
5
|
|
|
6
6
|
// src/components/Footer.tsx
|
|
7
7
|
import { Box } from "@ttoss/ui";
|
|
@@ -2352,10 +2352,55 @@ var Header = ({
|
|
|
2352
2352
|
Header.displayName = "Header";
|
|
2353
2353
|
|
|
2354
2354
|
// src/components/Main.tsx
|
|
2355
|
+
import { Box as Box6 } from "@ttoss/ui";
|
|
2356
|
+
|
|
2357
|
+
// src/components/MainFooter.tsx
|
|
2355
2358
|
import { Box as Box4 } from "@ttoss/ui";
|
|
2356
2359
|
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
2357
|
-
var
|
|
2360
|
+
var MainFooter = props => {
|
|
2358
2361
|
return /* @__PURE__ */jsx6(Box4, {
|
|
2362
|
+
variant: "layout.main.footer",
|
|
2363
|
+
...props,
|
|
2364
|
+
sx: {
|
|
2365
|
+
paddingX: "10",
|
|
2366
|
+
paddingY: "3",
|
|
2367
|
+
borderTop: "sm",
|
|
2368
|
+
borderColor: "display.border.muted.default",
|
|
2369
|
+
backgroundColor: "navigation.background.primary.default",
|
|
2370
|
+
width: "full",
|
|
2371
|
+
...props.sx
|
|
2372
|
+
},
|
|
2373
|
+
children: props.children
|
|
2374
|
+
});
|
|
2375
|
+
};
|
|
2376
|
+
MainFooter.displayName = "MainFooter";
|
|
2377
|
+
|
|
2378
|
+
// src/components/MainHeader.tsx
|
|
2379
|
+
import { Box as Box5 } from "@ttoss/ui";
|
|
2380
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
2381
|
+
var MainHeader = props => {
|
|
2382
|
+
return /* @__PURE__ */jsx7(Box5, {
|
|
2383
|
+
variant: "layout.main.header",
|
|
2384
|
+
...props,
|
|
2385
|
+
as: "header",
|
|
2386
|
+
sx: {
|
|
2387
|
+
paddingX: "4",
|
|
2388
|
+
paddingY: "3",
|
|
2389
|
+
borderBottom: "sm",
|
|
2390
|
+
borderColor: "display.border.muted.default",
|
|
2391
|
+
backgroundColor: "navigation.background.primary.default",
|
|
2392
|
+
width: "full",
|
|
2393
|
+
...props.sx
|
|
2394
|
+
},
|
|
2395
|
+
children: props.children
|
|
2396
|
+
});
|
|
2397
|
+
};
|
|
2398
|
+
MainHeader.displayName = "MainHeader";
|
|
2399
|
+
|
|
2400
|
+
// src/components/Main.tsx
|
|
2401
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
2402
|
+
var Main = props => {
|
|
2403
|
+
return /* @__PURE__ */jsx8(Box6, {
|
|
2359
2404
|
variant: "layout.main",
|
|
2360
2405
|
...props,
|
|
2361
2406
|
as: "main",
|
|
@@ -2371,13 +2416,15 @@ var Main = props => {
|
|
|
2371
2416
|
});
|
|
2372
2417
|
};
|
|
2373
2418
|
Main.displayName = "Main";
|
|
2419
|
+
Main.Header = MainHeader;
|
|
2420
|
+
Main.Footer = MainFooter;
|
|
2374
2421
|
|
|
2375
2422
|
// src/components/Layout.tsx
|
|
2376
|
-
import { jsx as
|
|
2423
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
2377
2424
|
var Layout = ({
|
|
2378
2425
|
children
|
|
2379
2426
|
}) => {
|
|
2380
|
-
return /* @__PURE__ */
|
|
2427
|
+
return /* @__PURE__ */jsx9(Box7, {
|
|
2381
2428
|
variant: "layout.layout",
|
|
2382
2429
|
children
|
|
2383
2430
|
});
|
|
@@ -2397,7 +2444,9 @@ var semanticComponents = {
|
|
|
2397
2444
|
Header: "header",
|
|
2398
2445
|
Sidebar: "sidebar",
|
|
2399
2446
|
Footer: "footer",
|
|
2400
|
-
Main: "main"
|
|
2447
|
+
Main: "main",
|
|
2448
|
+
MainHeader: "mainHeader",
|
|
2449
|
+
MainFooter: "mainFooter"
|
|
2401
2450
|
};
|
|
2402
2451
|
var getSematicElements = ({
|
|
2403
2452
|
children
|
|
@@ -2416,7 +2465,7 @@ var getSematicElements = ({
|
|
|
2416
2465
|
};
|
|
2417
2466
|
|
|
2418
2467
|
// src/components/SidebarCollapseLayout.tsx
|
|
2419
|
-
import { jsx as
|
|
2468
|
+
import { jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
2420
2469
|
var SidebarCollapseLayout = ({
|
|
2421
2470
|
children,
|
|
2422
2471
|
...props
|
|
@@ -2424,11 +2473,13 @@ var SidebarCollapseLayout = ({
|
|
|
2424
2473
|
const {
|
|
2425
2474
|
header,
|
|
2426
2475
|
main,
|
|
2427
|
-
sidebar
|
|
2476
|
+
sidebar,
|
|
2477
|
+
mainFooter,
|
|
2478
|
+
mainHeader
|
|
2428
2479
|
} = getSematicElements({
|
|
2429
2480
|
children
|
|
2430
2481
|
});
|
|
2431
|
-
return /* @__PURE__ */
|
|
2482
|
+
return /* @__PURE__ */jsx10(LayoutProvider, {
|
|
2432
2483
|
children: /* @__PURE__ */jsxs3(Stack, {
|
|
2433
2484
|
...props,
|
|
2434
2485
|
sx: {
|
|
@@ -2444,7 +2495,14 @@ var SidebarCollapseLayout = ({
|
|
|
2444
2495
|
overflow: "hidden",
|
|
2445
2496
|
flexDirection: ["row"]
|
|
2446
2497
|
},
|
|
2447
|
-
children: [sidebar,
|
|
2498
|
+
children: [sidebar, /* @__PURE__ */jsxs3(Stack, {
|
|
2499
|
+
sx: {
|
|
2500
|
+
flex: 1,
|
|
2501
|
+
height: "full",
|
|
2502
|
+
overflow: "hidden"
|
|
2503
|
+
},
|
|
2504
|
+
children: [mainHeader, main, mainFooter]
|
|
2505
|
+
})]
|
|
2448
2506
|
})]
|
|
2449
2507
|
})
|
|
2450
2508
|
});
|
|
@@ -2452,7 +2510,7 @@ var SidebarCollapseLayout = ({
|
|
|
2452
2510
|
|
|
2453
2511
|
// src/components/StackedLayout.tsx
|
|
2454
2512
|
import { Stack as Stack2 } from "@ttoss/ui";
|
|
2455
|
-
import { jsx as
|
|
2513
|
+
import { jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2456
2514
|
var StackedLayout = ({
|
|
2457
2515
|
children,
|
|
2458
2516
|
...props
|
|
@@ -2464,7 +2522,7 @@ var StackedLayout = ({
|
|
|
2464
2522
|
} = getSematicElements({
|
|
2465
2523
|
children
|
|
2466
2524
|
});
|
|
2467
|
-
return /* @__PURE__ */
|
|
2525
|
+
return /* @__PURE__ */jsx11(LayoutProvider, {
|
|
2468
2526
|
children: /* @__PURE__ */jsxs4(Stack2, {
|
|
2469
2527
|
...props,
|
|
2470
2528
|
children: [header, main, footer]
|
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,14 @@ declare const Layout: {
|
|
|
21
21
|
Main: {
|
|
22
22
|
(props: BoxProps): react_jsx_runtime.JSX.Element;
|
|
23
23
|
displayName: string;
|
|
24
|
+
Header: {
|
|
25
|
+
(props: BoxProps): react_jsx_runtime.JSX.Element;
|
|
26
|
+
displayName: string;
|
|
27
|
+
};
|
|
28
|
+
Footer: {
|
|
29
|
+
(props: BoxProps): react_jsx_runtime.JSX.Element;
|
|
30
|
+
displayName: string;
|
|
31
|
+
};
|
|
24
32
|
};
|
|
25
33
|
Footer: {
|
|
26
34
|
(props: BoxProps): react_jsx_runtime.JSX.Element;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttoss/layouts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Layout components for React",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ttoss",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"sideEffects": false,
|
|
26
26
|
"peerDependencies": {
|
|
27
27
|
"react": ">=16.8.0",
|
|
28
|
-
"@ttoss/components": "^2.2.
|
|
28
|
+
"@ttoss/components": "^2.2.27",
|
|
29
29
|
"@ttoss/ui": "^5.9.2"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
"jest": "^30.0.4",
|
|
35
35
|
"react": "^19.1.0",
|
|
36
36
|
"tsup": "^8.5.0",
|
|
37
|
-
"@ttoss/
|
|
38
|
-
"@ttoss/ui": "^5.9.2",
|
|
39
|
-
"@ttoss/components": "^2.2.26",
|
|
37
|
+
"@ttoss/components": "^2.2.27",
|
|
40
38
|
"@ttoss/test-utils": "^2.1.26",
|
|
41
|
-
"@ttoss/react-icons": "^0.4.15"
|
|
39
|
+
"@ttoss/react-icons": "^0.4.15",
|
|
40
|
+
"@ttoss/config": "^1.35.6",
|
|
41
|
+
"@ttoss/ui": "^5.9.2"
|
|
42
42
|
},
|
|
43
43
|
"keywords": [
|
|
44
44
|
"React"
|