@kodiak-finance/orderly-ui-scaffold 2.7.4
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 +586 -0
- package/dist/index.d.mts +489 -0
- package/dist/index.d.ts +489 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +21 -0
- package/dist/index.mjs.map +1 -0
- package/dist/styles.css +1 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
# Scaffold Component Integration Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Scaffold is a powerful layout component that provides a complete application scaffolding structure, including top navigation bar, sidebar, main content area, bottom navigation, and footer. This component supports responsive layouts for both desktop and mobile devices and offers rich customization options.
|
|
6
|
+
|
|
7
|
+
## Installation and Import
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { Scaffold, type ScaffoldProps } from "@orderly.network/ui-scaffold";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Basic Usage
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import React from 'react';
|
|
17
|
+
import { Scaffold } from "@orderly.network/ui-scaffold";
|
|
18
|
+
|
|
19
|
+
const App = () => {
|
|
20
|
+
return (
|
|
21
|
+
<Scaffold>
|
|
22
|
+
<div>Your main content here</div>
|
|
23
|
+
</Scaffold>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## ScaffoldProps Properties Detailed
|
|
29
|
+
|
|
30
|
+
### 1. leftSidebar (Optional)
|
|
31
|
+
|
|
32
|
+
- **Type**: `React.ReactNode`
|
|
33
|
+
- **Description**: Custom left sidebar component. If provided, the layout will use this component instead of the default sidebar component
|
|
34
|
+
- **Use Case**: When you need to completely customize the sidebar style and functionality
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
<Scaffold
|
|
38
|
+
leftSidebar={<CustomSidebar />}
|
|
39
|
+
>
|
|
40
|
+
{children}
|
|
41
|
+
</Scaffold>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 2. leftSideProps (Optional)
|
|
45
|
+
|
|
46
|
+
- **Type**: `SideBarProps`
|
|
47
|
+
- **Description**: Configuration properties for the default sidebar component
|
|
48
|
+
- **Main Properties**:
|
|
49
|
+
- `title`: Sidebar title
|
|
50
|
+
- `items`: Array of menu items
|
|
51
|
+
- `open`: Whether the sidebar is expanded
|
|
52
|
+
- `onOpenChange`: Callback for expansion state changes
|
|
53
|
+
- `onItemSelect`: Callback for menu item selection
|
|
54
|
+
- `current`: Currently selected menu item
|
|
55
|
+
- `maxWidth`: Maximum width when expanded (default: 185px)
|
|
56
|
+
- `minWidth`: Minimum width when collapsed (default: 98px)
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
const sidebarMenus = [
|
|
60
|
+
{ name: "Dashboard", href: "/dashboard", icon: <DashboardIcon /> },
|
|
61
|
+
{ name: "Trading", href: "/trading", icon: <TradingIcon /> },
|
|
62
|
+
{ name: "Portfolio", href: "/portfolio", icon: <PortfolioIcon /> }
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
<Scaffold
|
|
66
|
+
leftSideProps={{
|
|
67
|
+
title: "Navigation",
|
|
68
|
+
items: sidebarMenus,
|
|
69
|
+
current: "/dashboard",
|
|
70
|
+
onItemSelect: (item) => console.log('Selected:', item),
|
|
71
|
+
maxWidth: 200,
|
|
72
|
+
minWidth: 80
|
|
73
|
+
}}
|
|
74
|
+
>
|
|
75
|
+
{children}
|
|
76
|
+
</Scaffold>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 3. topBar (Optional)
|
|
80
|
+
|
|
81
|
+
- **Type**: `React.ReactNode`
|
|
82
|
+
- **Description**: Custom top navigation bar component
|
|
83
|
+
- **Use Case**: When you need to completely customize the top navigation bar
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
<Scaffold
|
|
87
|
+
topBar={<CustomTopBar />}
|
|
88
|
+
>
|
|
89
|
+
{children}
|
|
90
|
+
</Scaffold>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 4. mainNavProps (Optional)
|
|
94
|
+
|
|
95
|
+
- **Type**: `MainNavWidgetProps`
|
|
96
|
+
- **Description**: Configuration properties for the default main navigation component
|
|
97
|
+
- **Main Properties**:
|
|
98
|
+
- `leading`: Content on the left side of the navigation bar
|
|
99
|
+
- `trailing`: Content on the right side of the navigation bar
|
|
100
|
+
- `logo`: Brand logo configuration
|
|
101
|
+
- `mainMenus`: Array of main menu items
|
|
102
|
+
- `campaigns`: Campaign menu item
|
|
103
|
+
- `campaignPosition`: Campaign menu position
|
|
104
|
+
- `initialMenu`: Initial menu path
|
|
105
|
+
- `onItemClick`: Menu item click callback
|
|
106
|
+
- `leftNav`: Left navigation configuration for mobile drawer (only works on mobile)
|
|
107
|
+
- `customLeftNav`: Custom left navigation component to replace the default leftNav
|
|
108
|
+
- `customRender`: Function to customize the main navigation layout
|
|
109
|
+
- **Type**: `(components: MainNavComponents) => ReactNode`
|
|
110
|
+
- **Components**:
|
|
111
|
+
- `title`: Logo or title component (desktop & mobile)
|
|
112
|
+
- `languageSwitcher`: Language selection component (desktop & mobile)
|
|
113
|
+
- `subAccount`: Sub-account component (desktop & mobile)
|
|
114
|
+
- `linkDevice`: Device linking component (desktop & mobile)
|
|
115
|
+
- `chainMenu`: Chain selection menu (desktop & mobile)
|
|
116
|
+
- `walletConnect`: Wallet connection component (desktop & mobile)
|
|
117
|
+
- `mainNav`: Main navigation menu (desktop only)
|
|
118
|
+
- `accountSummary`: Account summary component (desktop only)
|
|
119
|
+
- `leftNav`: Left navigation component (mobile only)
|
|
120
|
+
- `scanQRCode`: QR code scanner component (mobile only)
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
<Scaffold
|
|
124
|
+
mainNavProps={{
|
|
125
|
+
logo: {
|
|
126
|
+
src: "/logo.png",
|
|
127
|
+
alt: "Company Logo"
|
|
128
|
+
},
|
|
129
|
+
mainMenus: [
|
|
130
|
+
{ name: "Trade", href: "/trade" },
|
|
131
|
+
{ name: "Portfolio", href: "/portfolio" }
|
|
132
|
+
],
|
|
133
|
+
leading: <BrandSection />,
|
|
134
|
+
trailing: <UserActions />,
|
|
135
|
+
onItemClick: ({ href, name }) => {
|
|
136
|
+
console.log(`Navigating to ${href}`);
|
|
137
|
+
},
|
|
138
|
+
leftNav: {
|
|
139
|
+
menus: [
|
|
140
|
+
{ name: "Dashboard", href: "/dashboard", icon: <DashboardIcon /> },
|
|
141
|
+
{ name: "Trading", href: "/trading", icon: <TradingIcon /> },
|
|
142
|
+
{ name: "Portfolio", href: "/portfolio", icon: <PortfolioIcon /> }
|
|
143
|
+
],
|
|
144
|
+
leading: <CustomLeftNavHeader />,
|
|
145
|
+
twitterUrl: "https://twitter.com/yourhandle",
|
|
146
|
+
telegramUrl: "https://t.me/yourgroup",
|
|
147
|
+
discordUrl: "https://discord.gg/yourserver",
|
|
148
|
+
duneUrl: "https://dune.com/youranalytics",
|
|
149
|
+
feedbackUrl: "https://feedback.yoursite.com"
|
|
150
|
+
},
|
|
151
|
+
// Custom layout for main navigation
|
|
152
|
+
customRender: (components) => {
|
|
153
|
+
// Mobile layout
|
|
154
|
+
if (isMobile) {
|
|
155
|
+
return (
|
|
156
|
+
<Flex width="100%" justify="between">
|
|
157
|
+
<Flex gapX={2}>
|
|
158
|
+
{components.leftNav}
|
|
159
|
+
{components.title}
|
|
160
|
+
</Flex>
|
|
161
|
+
<Flex gapX={2}>
|
|
162
|
+
{components.languageSwitcher}
|
|
163
|
+
{components.scanQRCode}
|
|
164
|
+
{components.linkDevice}
|
|
165
|
+
{components.chainMenu}
|
|
166
|
+
{components.walletConnect}
|
|
167
|
+
</Flex>
|
|
168
|
+
</Flex>
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Desktop layout
|
|
173
|
+
return (
|
|
174
|
+
<Flex width="100%" justify="between">
|
|
175
|
+
<Flex gapX={2}>
|
|
176
|
+
{components.title}
|
|
177
|
+
{components.mainNav}
|
|
178
|
+
</Flex>
|
|
179
|
+
<Flex gapX={2}>
|
|
180
|
+
{components.accountSummary}
|
|
181
|
+
{components.linkDevice}
|
|
182
|
+
{components.languageSwitcher}
|
|
183
|
+
{components.subAccount}
|
|
184
|
+
{components.chainMenu}
|
|
185
|
+
{components.walletConnect}
|
|
186
|
+
</Flex>
|
|
187
|
+
</Flex>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
}}
|
|
191
|
+
>
|
|
192
|
+
{children}
|
|
193
|
+
</Scaffold>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### 5. leftNav Configuration (Optional)
|
|
197
|
+
|
|
198
|
+
`leftNav` is a configuration property within `mainNavProps` that controls the mobile slide-out navigation drawer. It only appears on mobile devices and provides a comprehensive menu system.
|
|
199
|
+
|
|
200
|
+
#### LeftNavProps Properties
|
|
201
|
+
|
|
202
|
+
- **Type**: `LeftNavProps`
|
|
203
|
+
- **Description**: Configuration for the mobile left navigation drawer
|
|
204
|
+
- **Main Properties**:
|
|
205
|
+
- `menus`: Array of navigation menu items for the drawer
|
|
206
|
+
- `leading`: Custom content at the top of the drawer (below logo)
|
|
207
|
+
- `twitterUrl`: Twitter/X social media link
|
|
208
|
+
- `telegramUrl`: Telegram community link
|
|
209
|
+
- `discordUrl`: Discord community link
|
|
210
|
+
- `duneUrl`: Dune Analytics link
|
|
211
|
+
- `feedbackUrl`: Feedback form link (optional - if not provided, feedback section will not be displayed)
|
|
212
|
+
- `customLeftNav`: Custom component to replace the default leftNav trigger
|
|
213
|
+
|
|
214
|
+
#### LeftNavItem Properties
|
|
215
|
+
|
|
216
|
+
Each menu item in the `menus` array supports:
|
|
217
|
+
|
|
218
|
+
- `name`: Display name of the menu item
|
|
219
|
+
- `href`: Navigation URL
|
|
220
|
+
- `target`: Link target (e.g., "\_blank" for new window). If provided, will use `window.open()` instead of router navigation (optional)
|
|
221
|
+
- `icon`: Icon component to display (optional)
|
|
222
|
+
- `trailing`: Additional content on the right side (optional)
|
|
223
|
+
- `customRender`: Custom render function for complete control over item appearance
|
|
224
|
+
|
|
225
|
+
#### Usage Example
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
<Scaffold
|
|
229
|
+
mainNavProps={{
|
|
230
|
+
leftNav: {
|
|
231
|
+
menus: [
|
|
232
|
+
{
|
|
233
|
+
name: "Dashboard",
|
|
234
|
+
href: "/dashboard",
|
|
235
|
+
icon: <DashboardIcon />
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
name: "Trading",
|
|
239
|
+
href: "/trading",
|
|
240
|
+
icon: <TradingIcon />,
|
|
241
|
+
trailing: <NotificationBadge />
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
name: "Portfolio",
|
|
245
|
+
href: "/portfolio",
|
|
246
|
+
icon: <PortfolioIcon />,
|
|
247
|
+
customRender: ({ name, href, isActive }) => (
|
|
248
|
+
<div className={`custom-menu-item ${isActive ? 'active' : ''}`}>
|
|
249
|
+
<PortfolioIcon />
|
|
250
|
+
<span>{name}</span>
|
|
251
|
+
<SpecialBadge />
|
|
252
|
+
</div>
|
|
253
|
+
)
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
name: "External Link",
|
|
257
|
+
href: "https://external-site.com",
|
|
258
|
+
target: "_blank",
|
|
259
|
+
icon: <ExternalLinkIcon />
|
|
260
|
+
}
|
|
261
|
+
],
|
|
262
|
+
leading: (
|
|
263
|
+
<div className="px-3 py-2">
|
|
264
|
+
<Text className="text-sm text-gray-500">Quick Actions</Text>
|
|
265
|
+
</div>
|
|
266
|
+
),
|
|
267
|
+
twitterUrl: "https://twitter.com/yourhandle",
|
|
268
|
+
telegramUrl: "https://t.me/yourgroup",
|
|
269
|
+
discordUrl: "https://discord.gg/yourserver",
|
|
270
|
+
duneUrl: "https://dune.com/youranalytics",
|
|
271
|
+
feedbackUrl: "https://feedback.yoursite.com"
|
|
272
|
+
}
|
|
273
|
+
}}
|
|
274
|
+
>
|
|
275
|
+
{children}
|
|
276
|
+
</Scaffold>
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
#### Mobile Navigation Behavior
|
|
280
|
+
|
|
281
|
+
- **Trigger**: The leftNav appears as a hamburger menu icon on mobile devices
|
|
282
|
+
- **Drawer**: Slides out from the left side when triggered
|
|
283
|
+
- **Content Structure**:
|
|
284
|
+
1. Logo at the top
|
|
285
|
+
2. Leading content (if provided)
|
|
286
|
+
3. Sub-account selector (if user is logged in with trading enabled)
|
|
287
|
+
4. Menu items list (scrollable if needed)
|
|
288
|
+
5. Social media links at the bottom
|
|
289
|
+
6. Feedback link at the very bottom (only if `feedbackUrl` is provided)
|
|
290
|
+
- **Auto-close**: The drawer automatically closes when a menu item is selected
|
|
291
|
+
- **Navigation Behavior**:
|
|
292
|
+
- Items with `target` property will open in new window/tab using `window.open()`
|
|
293
|
+
- Items without `target` will use router navigation and close the drawer
|
|
294
|
+
|
|
295
|
+
#### Advanced Customization
|
|
296
|
+
|
|
297
|
+
You can provide a completely custom left navigation trigger:
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
<Scaffold
|
|
301
|
+
mainNavProps={{
|
|
302
|
+
customLeftNav: <CustomHamburgerButton />,
|
|
303
|
+
leftNav: {
|
|
304
|
+
// ... leftNav configuration
|
|
305
|
+
}
|
|
306
|
+
}}
|
|
307
|
+
>
|
|
308
|
+
{children}
|
|
309
|
+
</Scaffold>
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### 6. bottomNavProps (Optional)
|
|
313
|
+
|
|
314
|
+
- **Type**: `BottomNavProps`
|
|
315
|
+
- **Description**: Mobile bottom navigation configuration (only displayed on mobile devices)
|
|
316
|
+
- **Main Properties**:
|
|
317
|
+
- `mainMenus`: Array of bottom menu items
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
const bottomMenus = [
|
|
321
|
+
{
|
|
322
|
+
name: "Home",
|
|
323
|
+
href: "/home",
|
|
324
|
+
activeIcon: <HomeActiveIcon />,
|
|
325
|
+
inactiveIcon: <HomeInactiveIcon />
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
name: "Trade",
|
|
329
|
+
href: "/trade",
|
|
330
|
+
activeIcon: <TradeActiveIcon />,
|
|
331
|
+
inactiveIcon: <TradeInactiveIcon />
|
|
332
|
+
}
|
|
333
|
+
];
|
|
334
|
+
|
|
335
|
+
<Scaffold
|
|
336
|
+
bottomNavProps={{
|
|
337
|
+
mainMenus: bottomMenus,
|
|
338
|
+
}}
|
|
339
|
+
>
|
|
340
|
+
{children}
|
|
341
|
+
</Scaffold>
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### 7. footer (Optional)
|
|
345
|
+
|
|
346
|
+
- **Type**: `React.ReactNode`
|
|
347
|
+
- **Description**: Custom footer component
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
<Scaffold
|
|
351
|
+
footer={<CustomFooter />}
|
|
352
|
+
>
|
|
353
|
+
{children}
|
|
354
|
+
</Scaffold>
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### 8. footerProps (Optional)
|
|
358
|
+
|
|
359
|
+
- **Type**: `FooterProps`
|
|
360
|
+
- **Description**: Configuration properties for the default footer component
|
|
361
|
+
- **Main Properties**:
|
|
362
|
+
- `telegramUrl`: Telegram link
|
|
363
|
+
- `twitterUrl`: Twitter link
|
|
364
|
+
- `discordUrl`: Discord link
|
|
365
|
+
- `trailing`: Content on the right side of the footer
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
<Scaffold
|
|
369
|
+
footerProps={{
|
|
370
|
+
telegramUrl: "https://t.me/yourgroup",
|
|
371
|
+
twitterUrl: "https://twitter.com/yourhandle",
|
|
372
|
+
discordUrl: "https://discord.gg/yourserver",
|
|
373
|
+
trailing: <AdditionalFooterContent />
|
|
374
|
+
}}
|
|
375
|
+
>
|
|
376
|
+
{children}
|
|
377
|
+
</Scaffold>
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### 9. routerAdapter (Optional)
|
|
381
|
+
|
|
382
|
+
- **Type**: `RouterAdapter`
|
|
383
|
+
- **Description**: Router adapter for integrating with different routing libraries
|
|
384
|
+
- **Main Properties**:
|
|
385
|
+
- `onRouteChange`: Route change handler function
|
|
386
|
+
- `currentPath`: Current path
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
// React Router integration example
|
|
390
|
+
const routerAdapter = {
|
|
391
|
+
onRouteChange: (option) => {
|
|
392
|
+
if (option.target === '_blank') {
|
|
393
|
+
window.open(option.href, '_blank');
|
|
394
|
+
} else {
|
|
395
|
+
navigate(option.href);
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
currentPath: location.pathname
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
<Scaffold
|
|
402
|
+
routerAdapter={routerAdapter}
|
|
403
|
+
>
|
|
404
|
+
{children}
|
|
405
|
+
</Scaffold>
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### 10. classNames (Optional)
|
|
409
|
+
|
|
410
|
+
- **Type**: Style class name configuration object
|
|
411
|
+
- **Description**: Used to customize styles for various layout areas
|
|
412
|
+
- **Configurable Areas**:
|
|
413
|
+
- `root`: Root container (topNavbar + container + footer)
|
|
414
|
+
- `container`: Main container
|
|
415
|
+
- `content`: Content area
|
|
416
|
+
- `body`: Body area (leftSidebar + content)
|
|
417
|
+
- `leftSidebar`: Left sidebar
|
|
418
|
+
- `topNavbar`: Top navigation bar
|
|
419
|
+
- `footer`: Footer
|
|
420
|
+
|
|
421
|
+
```typescript
|
|
422
|
+
<Scaffold
|
|
423
|
+
classNames={{
|
|
424
|
+
root: "custom-root-class",
|
|
425
|
+
container: "custom-container-class",
|
|
426
|
+
content: "custom-content-class",
|
|
427
|
+
body: "custom-body-class",
|
|
428
|
+
leftSidebar: "custom-sidebar-class",
|
|
429
|
+
topNavbar: "custom-navbar-class",
|
|
430
|
+
footer: "custom-footer-class"
|
|
431
|
+
}}
|
|
432
|
+
>
|
|
433
|
+
{children}
|
|
434
|
+
</Scaffold>
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
## Complete Usage Example
|
|
438
|
+
|
|
439
|
+
```typescript
|
|
440
|
+
import React from 'react';
|
|
441
|
+
import { Scaffold } from "@orderly.network/ui-scaffold";
|
|
442
|
+
import { useNavigate, useLocation } from 'react-router-dom';
|
|
443
|
+
|
|
444
|
+
const App = () => {
|
|
445
|
+
const navigate = useNavigate();
|
|
446
|
+
const location = useLocation();
|
|
447
|
+
|
|
448
|
+
const sidebarMenus = [
|
|
449
|
+
{
|
|
450
|
+
name: "Dashboard",
|
|
451
|
+
href: "/dashboard",
|
|
452
|
+
icon: <DashboardIcon />
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
name: "Trading",
|
|
456
|
+
href: "/trading",
|
|
457
|
+
icon: <TradingIcon />
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
name: "Portfolio",
|
|
461
|
+
href: "/portfolio",
|
|
462
|
+
icon: <PortfolioIcon />
|
|
463
|
+
}
|
|
464
|
+
];
|
|
465
|
+
|
|
466
|
+
const bottomMenus = [
|
|
467
|
+
{
|
|
468
|
+
name: "Home",
|
|
469
|
+
href: "/home",
|
|
470
|
+
activeIcon: <HomeActiveIcon />,
|
|
471
|
+
inactiveIcon: <HomeInactiveIcon />
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
name: "Trade",
|
|
475
|
+
href: "/trade",
|
|
476
|
+
activeIcon: <TradeActiveIcon />,
|
|
477
|
+
inactiveIcon: <TradeInactiveIcon />
|
|
478
|
+
}
|
|
479
|
+
];
|
|
480
|
+
|
|
481
|
+
const routerAdapter = {
|
|
482
|
+
onRouteChange: (option) => {
|
|
483
|
+
if (option.target === '_blank') {
|
|
484
|
+
window.open(option.href, '_blank');
|
|
485
|
+
} else {
|
|
486
|
+
navigate(option.href);
|
|
487
|
+
}
|
|
488
|
+
},
|
|
489
|
+
currentPath: location.pathname
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
return (
|
|
493
|
+
<Scaffold
|
|
494
|
+
leftSideProps={{
|
|
495
|
+
title: "Navigation",
|
|
496
|
+
items: sidebarMenus,
|
|
497
|
+
current: location.pathname,
|
|
498
|
+
onItemSelect: (item) => {
|
|
499
|
+
if (item.href) {
|
|
500
|
+
navigate(item.href);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}}
|
|
504
|
+
mainNavProps={{
|
|
505
|
+
logo: {
|
|
506
|
+
src: "/logo.png",
|
|
507
|
+
alt: "Company Logo"
|
|
508
|
+
},
|
|
509
|
+
mainMenus: [
|
|
510
|
+
{ name: "Trade", href: "/trade" },
|
|
511
|
+
{ name: "Portfolio", href: "/portfolio" }
|
|
512
|
+
],
|
|
513
|
+
leading: <BrandSection />,
|
|
514
|
+
trailing: <UserActions />,
|
|
515
|
+
onItemClick: ({ href }) => navigate(href),
|
|
516
|
+
leftNav: {
|
|
517
|
+
menus: sidebarMenus, // Reuse the same menu items
|
|
518
|
+
twitterUrl: "https://twitter.com/yourhandle",
|
|
519
|
+
telegramUrl: "https://t.me/yourgroup",
|
|
520
|
+
discordUrl: "https://discord.gg/yourserver",
|
|
521
|
+
feedbackUrl: "https://feedback.yoursite.com"
|
|
522
|
+
}
|
|
523
|
+
}}
|
|
524
|
+
bottomNavProps={{
|
|
525
|
+
mainMenus: bottomMenus,
|
|
526
|
+
}}
|
|
527
|
+
footerProps={{
|
|
528
|
+
telegramUrl: "https://t.me/yourgroup",
|
|
529
|
+
twitterUrl: "https://twitter.com/yourhandle",
|
|
530
|
+
discordUrl: "https://discord.gg/yourserver"
|
|
531
|
+
}}
|
|
532
|
+
routerAdapter={routerAdapter}
|
|
533
|
+
classNames={{
|
|
534
|
+
content: "p-4",
|
|
535
|
+
leftSidebar: "border-r border-gray-200"
|
|
536
|
+
}}
|
|
537
|
+
>
|
|
538
|
+
<div className="min-h-screen">
|
|
539
|
+
{/* Your main application content */}
|
|
540
|
+
<h1>Welcome to your application</h1>
|
|
541
|
+
<p>This is the main content area.</p>
|
|
542
|
+
</div>
|
|
543
|
+
</Scaffold>
|
|
544
|
+
);
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
export default App;
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
## Responsive Behavior
|
|
551
|
+
|
|
552
|
+
The Scaffold component automatically detects device type and provides appropriate layouts:
|
|
553
|
+
|
|
554
|
+
- **Desktop**: Displays complete sidebar, top navigation bar, and footer
|
|
555
|
+
- **Mobile**: Hides sidebar, displays bottom navigation bar and left navigation drawer (leftNav), optimized for touch interaction
|
|
556
|
+
|
|
557
|
+
### Mobile Navigation Features
|
|
558
|
+
|
|
559
|
+
- **Left Navigation Drawer**: Accessed via hamburger menu icon, provides slide-out menu with complete navigation options
|
|
560
|
+
- **Bottom Navigation**: Fixed bottom bar for quick access to main sections
|
|
561
|
+
- **Responsive Top Bar**: Adapts to show essential controls and navigation elements
|
|
562
|
+
|
|
563
|
+
## Best Practices
|
|
564
|
+
|
|
565
|
+
1. **Router Integration**: Always provide `routerAdapter` to ensure navigation functionality works properly
|
|
566
|
+
2. **Responsive Design**: Provide `bottomNavProps` and `leftNav` configuration for optimal mobile experience
|
|
567
|
+
3. **Style Customization**: Use the `classNames` property for style customization instead of directly modifying component styles
|
|
568
|
+
4. **Menu State Management**: Ensure the `current` property is synchronized with actual route state
|
|
569
|
+
5. **Performance Optimization**: For large menu lists, consider using React.memo to optimize rendering performance
|
|
570
|
+
6. **Mobile Navigation**: Configure `leftNav` with social media links and feedback URL to provide comprehensive mobile navigation experience
|
|
571
|
+
|
|
572
|
+
## Important Notes
|
|
573
|
+
|
|
574
|
+
- The Scaffold component must be wrapped in `ScaffoldProvider` to work properly (automatically handled internally)
|
|
575
|
+
- Sidebar expand/collapse state is automatically saved to localStorage
|
|
576
|
+
- Mobile and desktop use different layout components to ensure good user experience on different devices
|
|
577
|
+
- The `leftNav` drawer is only available on mobile devices and provides a comprehensive navigation menu
|
|
578
|
+
- All navigation callbacks should properly handle route navigation logic
|
|
579
|
+
|
|
580
|
+
## Related Components
|
|
581
|
+
|
|
582
|
+
- `ScaffoldProvider`: Provides Scaffold context
|
|
583
|
+
- `useScaffoldContext`: Hook to get Scaffold state
|
|
584
|
+
- `MobileScaffold`: Mobile layout component
|
|
585
|
+
- `DesktopScaffold`: Desktop layout component
|
|
586
|
+
- `SubAccountWidget`: Sub-account selection component (exported from ui-scaffold)
|