@taruvi/navkit 0.0.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/.claude/settings.local.json +9 -0
- package/README.md +757 -0
- package/adr.md +1414 -0
- package/eslint.config.js +23 -0
- package/index.html +13 -0
- package/package.json +39 -0
- package/src/App.styles.ts +65 -0
- package/src/App.tsx +111 -0
- package/src/NavkitContext.tsx +152 -0
- package/src/assets/logo-text.png +0 -0
- package/src/assets/nopfp.png +0 -0
- package/src/assets/taruvi-logo.png +0 -0
- package/src/components/AppLauncher/AppLauncher.styles.ts +59 -0
- package/src/components/AppLauncher/AppLauncher.tsx +74 -0
- package/src/components/MattermostChat/MattermostChat.tsx +132 -0
- package/src/components/MattermostChat/README.md +227 -0
- package/src/components/Profile/Profile.styles.ts +59 -0
- package/src/components/Profile/Profile.tsx +36 -0
- package/src/components/Profile/ProfileMenu.tsx +42 -0
- package/src/components/Search/Search.styles.ts +7 -0
- package/src/components/Search/Search.tsx +51 -0
- package/src/components/Shortucts/Shortcuts.styles.ts +29 -0
- package/src/components/Shortucts/Shortcuts.tsx +72 -0
- package/src/components/Shortucts/ShortcutsMenu.styles.ts +34 -0
- package/src/components/Shortucts/ShortcutsMenu.tsx +62 -0
- package/src/components/index.ts +8 -0
- package/src/styles/commonStyles.ts +42 -0
- package/src/styles/variables.ts +61 -0
- package/src/types.ts +38 -0
- package/tsconfig.app.json +28 -0
- package/tsconfig.json +7 -0
- package/tsconfig.node.json +26 -0
- package/vite.config.ts +13 -0
package/README.md
ADDED
|
@@ -0,0 +1,757 @@
|
|
|
1
|
+
# Taruvi Navkit
|
|
2
|
+
|
|
3
|
+
A modern, responsive, and highly performant navigation bar component library for the Taruvi ecosystem. Built with React 19, TypeScript, and Material-UI with automatic optimizations via React Compiler.
|
|
4
|
+
|
|
5
|
+
[](https://react.dev/)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](https://vite.dev/)
|
|
8
|
+
[](https://mui.com/)
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
### Core Components
|
|
13
|
+
|
|
14
|
+
- **App Launcher**: Grid-based application launcher with real-time search and filtering
|
|
15
|
+
- **Smart Shortcuts**: Quick access shortcuts with responsive desktop/mobile views and hamburger menu on mobile
|
|
16
|
+
- **User Profile**: Avatar-based profile menu with preferences access and logout functionality
|
|
17
|
+
- **Mattermost Chat Integration**: Embedded chat modal with JWT authentication and external link option
|
|
18
|
+
- **Click-Outside Detection**: Intelligent menu closing with mutually exclusive dropdown behavior
|
|
19
|
+
|
|
20
|
+
### Technical Highlights
|
|
21
|
+
|
|
22
|
+
- **Responsive Design**: Mobile-first approach with strategic breakpoints (900px for desktop)
|
|
23
|
+
- **Smart Navigation**: Context-aware navigation system (desk mode vs external mode)
|
|
24
|
+
- **Type-Safe**: Full TypeScript support with strict mode enabled
|
|
25
|
+
- **Optimized Performance**: React Compiler with automatic memoization + manual optimizations
|
|
26
|
+
- **Modern React**: Leverages React 19 features (startTransition, concurrent rendering)
|
|
27
|
+
- **Design System**: Centralized design tokens for consistent theming
|
|
28
|
+
- **Accessibility**: MUI components with built-in ARIA attributes and keyboard navigation
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
### Installation
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Clone or add as dependency
|
|
36
|
+
npm install @taruvi/navkit
|
|
37
|
+
|
|
38
|
+
# Install peer dependencies
|
|
39
|
+
npm install @mui/material @emotion/react @emotion/styled
|
|
40
|
+
npm install @fortawesome/fontawesome-svg-core @fortawesome/free-solid-svg-icons @fortawesome/free-regular-svg-icons @fortawesome/react-fontawesome
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Basic Setup
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import Navkit from '@taruvi/navkit'
|
|
47
|
+
import { TaruviClient } from '@taruvi-io/sdk'
|
|
48
|
+
|
|
49
|
+
function App() {
|
|
50
|
+
const client = new TaruviClient({
|
|
51
|
+
apiUrl: 'https://api.taruvi.io',
|
|
52
|
+
// ... other config
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
return <Navkit client={client} />
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export default App
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Development
|
|
62
|
+
|
|
63
|
+
### Development Scripts
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Start development server with HMR (Hot Module Replacement)
|
|
67
|
+
npm run dev
|
|
68
|
+
|
|
69
|
+
# Build for production (TypeScript check + Vite build)
|
|
70
|
+
npm run build
|
|
71
|
+
|
|
72
|
+
# Preview production build locally
|
|
73
|
+
npm run preview
|
|
74
|
+
|
|
75
|
+
# Run ESLint for code quality
|
|
76
|
+
npm run lint
|
|
77
|
+
|
|
78
|
+
# Test Mattermost integration in isolation
|
|
79
|
+
npm run test:mattermost
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Development Workflow
|
|
83
|
+
|
|
84
|
+
1. **Make changes** to source files in `src/`
|
|
85
|
+
2. **See updates instantly** with Vite's Fast Refresh (HMR)
|
|
86
|
+
3. **Type-check** automatically via TypeScript in your IDE
|
|
87
|
+
4. **Lint before commit** with `npm run lint`
|
|
88
|
+
5. **Build before deploy** with `npm run build`
|
|
89
|
+
|
|
90
|
+
## Usage
|
|
91
|
+
|
|
92
|
+
### Integration Patterns
|
|
93
|
+
|
|
94
|
+
#### Standalone App Integration
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
import Navkit from '@taruvi/navkit'
|
|
98
|
+
import { TaruviClient } from '@taruvi-io/sdk'
|
|
99
|
+
|
|
100
|
+
function App() {
|
|
101
|
+
const client = new TaruviClient({
|
|
102
|
+
apiUrl: process.env.VITE_API_URL,
|
|
103
|
+
tenantId: process.env.VITE_TENANT_ID,
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<>
|
|
108
|
+
<Navkit client={client} />
|
|
109
|
+
<main>{/* Your app content */}</main>
|
|
110
|
+
</>
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### Taruvi Desk Integration
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
import Navkit from '@taruvi/navkit'
|
|
119
|
+
import { useDesk } from '@taruvi-io/desk-sdk'
|
|
120
|
+
|
|
121
|
+
function DeskApp() {
|
|
122
|
+
const { client } = useDesk()
|
|
123
|
+
|
|
124
|
+
return <Navkit client={client} />
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Client Object Requirements
|
|
129
|
+
|
|
130
|
+
The `client` prop expects an object compatible with `@taruvi-io/sdk` that provides:
|
|
131
|
+
|
|
132
|
+
- **User** class for user data and apps
|
|
133
|
+
- `getApps()`: Fetch available applications
|
|
134
|
+
- `getData()`: Fetch user profile data (fullName, pfp, username, email)
|
|
135
|
+
|
|
136
|
+
- **Settings** class for site configuration
|
|
137
|
+
- `get()`: Fetch site settings (logo, frontendUrl, mattermostUrl, shortcuts)
|
|
138
|
+
|
|
139
|
+
- **Auth** class for authentication
|
|
140
|
+
- `isUserAuthenticated()`: Check authentication status
|
|
141
|
+
- JWT token management (future)
|
|
142
|
+
|
|
143
|
+
## Architecture
|
|
144
|
+
|
|
145
|
+
### Component Structure
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
Navkit (App.tsx)
|
|
149
|
+
├── NavkitProvider (NavkitContext) - React Context for global state
|
|
150
|
+
│ ├── State: appsList, userData, isUserAuthenticated, jwtToken, isDesk
|
|
151
|
+
│ ├── Refs: siteSettings, user, settings (SDK instances)
|
|
152
|
+
│ └── Functions: navigateToUrl, getData, authenticateUser
|
|
153
|
+
├── NavkitContent - Main UI component
|
|
154
|
+
├── AppLauncher - App grid with search
|
|
155
|
+
├── Profile - User avatar and name
|
|
156
|
+
│ └── ProfileMenu - Preferences and logout
|
|
157
|
+
├── Shortcuts - Quick action icons
|
|
158
|
+
│ └── ShortcutsMenu - Mobile dropdown
|
|
159
|
+
└── MattermostChat - Chat modal
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### State Management
|
|
163
|
+
|
|
164
|
+
Navkit uses React Context API for centralized state management:
|
|
165
|
+
|
|
166
|
+
- **NavigationContext** - Centralized provider for all app state and navigation logic
|
|
167
|
+
- **useNavigation hook** - Custom hook for consuming context in child components
|
|
168
|
+
- **Separate state variables** for granular updates (reduces unnecessary re-renders)
|
|
169
|
+
- **useRef for SDK instances** and siteSettings to prevent re-renders
|
|
170
|
+
- **startTransition** for batching multiple state updates on initial load (6+ renders → 1 render)
|
|
171
|
+
- **BroadcastChannel** for cross-tab synchronization (refreshes on profile updates)
|
|
172
|
+
- **React Compiler** for automatic memoization and optimization
|
|
173
|
+
|
|
174
|
+
#### Performance Optimizations
|
|
175
|
+
|
|
176
|
+
- Initial render count reduced from 6+ to 1 via `startTransition`
|
|
177
|
+
- SDK instances and siteSettings in refs prevent re-renders
|
|
178
|
+
- Separate state variables allow granular component updates
|
|
179
|
+
- React Compiler automatically memoizes components and callbacks
|
|
180
|
+
- BroadcastChannel enables real-time updates across tabs
|
|
181
|
+
|
|
182
|
+
### Navigation Modes
|
|
183
|
+
|
|
184
|
+
Navkit intelligently handles navigation based on context:
|
|
185
|
+
|
|
186
|
+
#### 1. Desk Mode (when `frontendUrl` is set)
|
|
187
|
+
|
|
188
|
+
- **When**: Running inside Taruvi Desk application
|
|
189
|
+
- **Behavior**: Relative navigation within the app
|
|
190
|
+
- **Examples**:
|
|
191
|
+
- `https://app.taruvi.io/mail` → navigates to `/mail`
|
|
192
|
+
- `/preferences` → navigates to `/preferences`
|
|
193
|
+
- **Detection**: Checks if `window.location.href` includes `frontendUrl`
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
// Site settings with frontendUrl
|
|
197
|
+
{
|
|
198
|
+
frontendUrl: 'https://desk.taruvi.io',
|
|
199
|
+
// ... other settings
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
#### 2. External Mode (no `frontendUrl`)
|
|
204
|
+
|
|
205
|
+
- **When**: Running in standalone app or `frontendUrl` not set
|
|
206
|
+
- **Behavior**: Opens URLs in new tab
|
|
207
|
+
- **Examples**:
|
|
208
|
+
- `https://mail.taruvi.io` → opens in new tab
|
|
209
|
+
- `https://external-app.com` → opens in new tab
|
|
210
|
+
- **Purpose**: Prevents navigating away from host application
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
// Site settings without frontendUrl
|
|
214
|
+
{
|
|
215
|
+
frontendUrl: '', // or null/undefined
|
|
216
|
+
// ... other settings
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
#### Navigation Hook
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
import { useNavigation } from './NavkitContext'
|
|
224
|
+
|
|
225
|
+
// In any child component
|
|
226
|
+
function MyComponent() {
|
|
227
|
+
const { navigateToUrl, isDesk, siteSettings } = useNavigation()
|
|
228
|
+
|
|
229
|
+
// Automatically detects mode and navigates appropriately
|
|
230
|
+
navigateToUrl('/app-name')
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Responsive Breakpoints
|
|
235
|
+
|
|
236
|
+
Navkit uses a mobile-first responsive design strategy:
|
|
237
|
+
|
|
238
|
+
#### Mobile (xs): < 900px
|
|
239
|
+
|
|
240
|
+
- **User name**: Hidden (avatar only)
|
|
241
|
+
- **Shortcuts**: Hamburger menu dropdown
|
|
242
|
+
- **App launcher**: Full-width (95vw)
|
|
243
|
+
- **Touch targets**: Minimum 44x44px
|
|
244
|
+
- **Optimizations**: Reduced clutter for small screens
|
|
245
|
+
|
|
246
|
+
#### Desktop (md+): ≥ 900px
|
|
247
|
+
|
|
248
|
+
- **User name**: Visible next to avatar
|
|
249
|
+
- **Shortcuts**: Inline horizontal layout
|
|
250
|
+
- **App launcher**: Fixed width (600px)
|
|
251
|
+
- **Enhanced UX**: More information density
|
|
252
|
+
|
|
253
|
+
#### Implementation Example
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
// Conditional rendering based on breakpoint
|
|
257
|
+
<Typography sx={{ display: { xs: 'none', md: 'block' } }}>
|
|
258
|
+
{userData.fullName}
|
|
259
|
+
</Typography>
|
|
260
|
+
|
|
261
|
+
// Responsive dimensions
|
|
262
|
+
container: {
|
|
263
|
+
width: { xs: '95vw', sm: '80vw', md: '70vw', lg: '600px' },
|
|
264
|
+
height: { xs: '90vh', md: '80vh' },
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
#### Testing Breakpoints
|
|
269
|
+
|
|
270
|
+
Test the following widths for complete coverage:
|
|
271
|
+
- **320px**: Minimum mobile (iPhone SE)
|
|
272
|
+
- **768px**: Tablet
|
|
273
|
+
- **900px**: Breakpoint threshold
|
|
274
|
+
- **1024px**: Small desktop
|
|
275
|
+
- **1920px**: Large desktop
|
|
276
|
+
|
|
277
|
+
## Configuration
|
|
278
|
+
|
|
279
|
+
### Site Settings
|
|
280
|
+
|
|
281
|
+
The component expects the following settings from the SDK:
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
interface SiteSettings {
|
|
285
|
+
logo: string // Navigation bar logo URL
|
|
286
|
+
frontendUrl: string // Base URL for desk mode navigation (optional)
|
|
287
|
+
mattermostUrl: string // Mattermost server URL (optional)
|
|
288
|
+
shortcuts: AppData[] // Quick action shortcuts
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Example
|
|
292
|
+
{
|
|
293
|
+
logo: 'https://cdn.taruvi.io/logo.png',
|
|
294
|
+
frontendUrl: 'https://desk.taruvi.io',
|
|
295
|
+
mattermostUrl: 'https://chat.taruvi.io',
|
|
296
|
+
shortcuts: [
|
|
297
|
+
{
|
|
298
|
+
id: '1',
|
|
299
|
+
appname: 'Mail',
|
|
300
|
+
icon: 'envelope',
|
|
301
|
+
url: '/mail'
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
id: '2',
|
|
305
|
+
appname: 'Calendar',
|
|
306
|
+
icon: 'calendar',
|
|
307
|
+
url: '/calendar'
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
id: '3',
|
|
311
|
+
appname: 'Chat',
|
|
312
|
+
icon: 'comments',
|
|
313
|
+
url: '#' // Special handling for chat
|
|
314
|
+
}
|
|
315
|
+
]
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### User Data
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
interface UserData {
|
|
323
|
+
fullName: string // Full display name
|
|
324
|
+
pfp: string // Profile picture URL
|
|
325
|
+
username: string // Username or handle
|
|
326
|
+
email: string // User email address
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Example
|
|
330
|
+
{
|
|
331
|
+
fullName: 'John Doe',
|
|
332
|
+
pfp: 'https://cdn.taruvi.io/avatars/johndoe.jpg',
|
|
333
|
+
username: 'johndoe',
|
|
334
|
+
email: 'john.doe@taruvi.io'
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### App Data
|
|
339
|
+
|
|
340
|
+
```typescript
|
|
341
|
+
interface AppData {
|
|
342
|
+
id: string // Unique app identifier
|
|
343
|
+
appname: string // Display name
|
|
344
|
+
icon: string // FontAwesome icon name (without 'fa-' prefix)
|
|
345
|
+
url: string // App URL or path
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Example
|
|
349
|
+
{
|
|
350
|
+
id: 'app-mail-001',
|
|
351
|
+
appname: 'Mail',
|
|
352
|
+
icon: 'envelope', // Renders as fa-envelope
|
|
353
|
+
url: 'https://mail.taruvi.io'
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
#### FontAwesome Icon Names
|
|
358
|
+
|
|
359
|
+
Icons use FontAwesome Free icon names without the `fa-` prefix:
|
|
360
|
+
- `envelope` → `fa-envelope`
|
|
361
|
+
- `calendar` → `fa-calendar`
|
|
362
|
+
- `home` → `fa-home`
|
|
363
|
+
- `cog` → `fa-cog`
|
|
364
|
+
|
|
365
|
+
See [FontAwesome Free Icons](https://fontawesome.com/search?o=r&m=free) for available icons.
|
|
366
|
+
|
|
367
|
+
## Styling
|
|
368
|
+
|
|
369
|
+
### Design System
|
|
370
|
+
|
|
371
|
+
Navkit uses a centralized design system with design tokens in [src/styles/variables.ts](src/styles/variables.ts):
|
|
372
|
+
|
|
373
|
+
#### Color Palette
|
|
374
|
+
|
|
375
|
+
```typescript
|
|
376
|
+
colours = {
|
|
377
|
+
text: {
|
|
378
|
+
primary: '#333333', // Main text
|
|
379
|
+
secondary: '#424242', // Secondary text
|
|
380
|
+
tertiary: '#9e9e9e', // Disabled/subtle text
|
|
381
|
+
},
|
|
382
|
+
bg: {
|
|
383
|
+
white: '#fff', // White background
|
|
384
|
+
light: '#f5f5f5', // Light grey background
|
|
385
|
+
avatar: '#E0E0E0', // Avatar placeholder
|
|
386
|
+
},
|
|
387
|
+
border: {
|
|
388
|
+
light: '#e0e0e0', // Border color
|
|
389
|
+
},
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
#### Spacing Scale
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
spacing = {
|
|
397
|
+
xs: '10px', // Extra small
|
|
398
|
+
sm: 1.5, // Small (12px with MUI 8px base)
|
|
399
|
+
md: 2, // Medium (16px)
|
|
400
|
+
lg: 3, // Large (24px)
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
#### Typography
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
typography = {
|
|
408
|
+
sizes: {
|
|
409
|
+
xs: '0.8125rem', // 13px
|
|
410
|
+
sm: '0.875rem', // 14px
|
|
411
|
+
md: '1.125rem', // 18px
|
|
412
|
+
},
|
|
413
|
+
weights: {
|
|
414
|
+
regular: 400,
|
|
415
|
+
semibold: 600,
|
|
416
|
+
},
|
|
417
|
+
}
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
#### Dimensions
|
|
421
|
+
|
|
422
|
+
```typescript
|
|
423
|
+
dimensions = {
|
|
424
|
+
navHeight: '60px',
|
|
425
|
+
avatarSize: 40,
|
|
426
|
+
iconSize: {
|
|
427
|
+
sm: '18px',
|
|
428
|
+
md: '24px',
|
|
429
|
+
lg: '1.25rem',
|
|
430
|
+
},
|
|
431
|
+
}
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### Customization Options
|
|
435
|
+
|
|
436
|
+
#### 1. Component-Specific Styles
|
|
437
|
+
|
|
438
|
+
Each component has a `.styles.ts` file:
|
|
439
|
+
|
|
440
|
+
```typescript
|
|
441
|
+
// Profile.styles.ts
|
|
442
|
+
import { colours, spacing, typography } from '../../styles/variables'
|
|
443
|
+
|
|
444
|
+
export const profileStyles = {
|
|
445
|
+
userName: {
|
|
446
|
+
fontSize: typography.sizes.sm,
|
|
447
|
+
color: colours.text.primary,
|
|
448
|
+
padding: spacing.xs,
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
#### 2. Design Tokens
|
|
454
|
+
|
|
455
|
+
Modify `src/styles/variables.ts` for global changes:
|
|
456
|
+
|
|
457
|
+
```typescript
|
|
458
|
+
// Change primary text color globally
|
|
459
|
+
export const colours = {
|
|
460
|
+
text: {
|
|
461
|
+
primary: '#000000', // Darker text
|
|
462
|
+
// ...
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
#### 3. MUI Theme Provider
|
|
468
|
+
|
|
469
|
+
Wrap Navkit with MUI ThemeProvider for advanced theming:
|
|
470
|
+
|
|
471
|
+
```tsx
|
|
472
|
+
import { createTheme, ThemeProvider } from '@mui/material/styles'
|
|
473
|
+
|
|
474
|
+
const theme = createTheme({
|
|
475
|
+
palette: {
|
|
476
|
+
primary: {
|
|
477
|
+
main: '#1976d2',
|
|
478
|
+
},
|
|
479
|
+
},
|
|
480
|
+
})
|
|
481
|
+
|
|
482
|
+
function App() {
|
|
483
|
+
return (
|
|
484
|
+
<ThemeProvider theme={theme}>
|
|
485
|
+
<Navkit client={client} />
|
|
486
|
+
</ThemeProvider>
|
|
487
|
+
)
|
|
488
|
+
}
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
## Tech Stack
|
|
492
|
+
|
|
493
|
+
### Core Dependencies
|
|
494
|
+
|
|
495
|
+
| Package | Version | Purpose |
|
|
496
|
+
|---------|---------|---------|
|
|
497
|
+
| **React** | 19.1.1 | UI framework with concurrent features |
|
|
498
|
+
| **React DOM** | 19.1.1 | DOM rendering |
|
|
499
|
+
| **TypeScript** | ~5.9.3 | Type safety and developer experience |
|
|
500
|
+
|
|
501
|
+
### Peer Dependencies
|
|
502
|
+
|
|
503
|
+
| Package | Version | Purpose |
|
|
504
|
+
|---------|---------|---------|
|
|
505
|
+
| **@mui/material** | ^5.0.0 | UI component library |
|
|
506
|
+
| **@emotion/react** | ^11.0.0 | CSS-in-JS (MUI dependency) |
|
|
507
|
+
| **@emotion/styled** | ^11.0.0 | Styled components (MUI dependency) |
|
|
508
|
+
| **@fortawesome/fontawesome-svg-core** | ^6.0.0 | Icon library core |
|
|
509
|
+
| **@fortawesome/free-solid-svg-icons** | ^6.0.0 | Solid icons |
|
|
510
|
+
| **@fortawesome/free-regular-svg-icons** | ^6.0.0 | Regular icons |
|
|
511
|
+
| **@fortawesome/react-fontawesome** | ^0.2.0 | React icon components |
|
|
512
|
+
| **@taruvi-io/sdk** | latest | Taruvi SDK for API integration |
|
|
513
|
+
|
|
514
|
+
### Development Dependencies
|
|
515
|
+
|
|
516
|
+
| Package | Version | Purpose |
|
|
517
|
+
|---------|---------|---------|
|
|
518
|
+
| **Vite** | 7.1.7 | Build tool and dev server |
|
|
519
|
+
| **@vitejs/plugin-react** | ^5.0.4 | Vite React plugin |
|
|
520
|
+
| **babel-plugin-react-compiler** | ^19.1.0-rc.3 | Automatic optimizations |
|
|
521
|
+
| **ESLint** | ^9.36.0 | Code linting |
|
|
522
|
+
| **typescript-eslint** | ^8.45.0 | TypeScript ESLint support |
|
|
523
|
+
|
|
524
|
+
### Why These Choices?
|
|
525
|
+
|
|
526
|
+
- **React 19**: Latest features (startTransition, concurrent rendering)
|
|
527
|
+
- **Vite**: Fast HMR (< 100ms), optimized builds
|
|
528
|
+
- **MUI**: Accessible, responsive, well-maintained
|
|
529
|
+
- **TypeScript**: Catch errors at compile time
|
|
530
|
+
- **React Compiler**: Automatic performance optimizations
|
|
531
|
+
|
|
532
|
+
## Performance Optimizations
|
|
533
|
+
|
|
534
|
+
### Automatic Optimizations
|
|
535
|
+
|
|
536
|
+
#### React Compiler
|
|
537
|
+
- **Automatic memoization** of components and values
|
|
538
|
+
- **Callback stabilization** without manual `useCallback`
|
|
539
|
+
- **Reduced re-renders** through intelligent optimization
|
|
540
|
+
- **No boilerplate** (no manual `useMemo`, `React.memo`)
|
|
541
|
+
|
|
542
|
+
#### Vite Build Pipeline
|
|
543
|
+
- **Code splitting**: Automatic chunking for optimal loading
|
|
544
|
+
- **Tree shaking**: Removes unused code in production
|
|
545
|
+
- **Minification**: Terser for JavaScript, CSS minification
|
|
546
|
+
- **Fast Refresh**: Sub-second HMR during development
|
|
547
|
+
|
|
548
|
+
### Manual Optimizations
|
|
549
|
+
|
|
550
|
+
#### State Management
|
|
551
|
+
```typescript
|
|
552
|
+
// Separate state variables for granular updates
|
|
553
|
+
const [showAppLauncher, setShowAppLauncher] = useState(false)
|
|
554
|
+
const [showProfileMenu, setShowProfileMenu] = useState(false)
|
|
555
|
+
|
|
556
|
+
// useRef for SDK instances (no re-renders)
|
|
557
|
+
const settings = useRef<any>(null)
|
|
558
|
+
|
|
559
|
+
// startTransition for batched updates
|
|
560
|
+
startTransition(() => {
|
|
561
|
+
setAppsList(apps)
|
|
562
|
+
setUserData(userData)
|
|
563
|
+
setSiteSettings(settings)
|
|
564
|
+
})
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
#### Performance Metrics
|
|
568
|
+
|
|
569
|
+
| Metric | Value | Target |
|
|
570
|
+
|--------|-------|--------|
|
|
571
|
+
| Initial renders | 1 | < 3 |
|
|
572
|
+
| Bundle size (gzipped) | ~150KB | < 200KB |
|
|
573
|
+
| Time to Interactive | < 1s | < 2s |
|
|
574
|
+
| First Contentful Paint | < 500ms | < 1s |
|
|
575
|
+
|
|
576
|
+
### Best Practices
|
|
577
|
+
|
|
578
|
+
1. **Avoid unnecessary renders**: Separate state variables
|
|
579
|
+
2. **Batch updates**: Use `startTransition` for multiple state changes
|
|
580
|
+
3. **Stable references**: Use `useRef` for non-rendering data
|
|
581
|
+
4. **Trust the compiler**: Let React Compiler handle optimization
|
|
582
|
+
|
|
583
|
+
## Browser Support
|
|
584
|
+
|
|
585
|
+
Modern browsers with ES2020+ support:
|
|
586
|
+
- Chrome/Edge 88+
|
|
587
|
+
- Firefox 78+
|
|
588
|
+
- Safari 14+
|
|
589
|
+
|
|
590
|
+
## Project Structure
|
|
591
|
+
|
|
592
|
+
```
|
|
593
|
+
taruvi-navkit/
|
|
594
|
+
├── docs/
|
|
595
|
+
│ └── adr/ # Architecture Decision Records
|
|
596
|
+
│ └── 001-navkit-architecture.md
|
|
597
|
+
├── src/
|
|
598
|
+
│ ├── components/
|
|
599
|
+
│ │ ├── AppLauncher/
|
|
600
|
+
│ │ ├── Profile/
|
|
601
|
+
│ │ ├── Shortucts/
|
|
602
|
+
│ │ ├── Search/
|
|
603
|
+
│ │ └── MattermostChat/
|
|
604
|
+
│ ├── styles/
|
|
605
|
+
│ │ └── variables.ts # Design tokens
|
|
606
|
+
│ ├── NavkitContext.tsx # React Context provider & hook
|
|
607
|
+
│ ├── App.tsx # Main Navkit component
|
|
608
|
+
│ ├── App.styles.ts
|
|
609
|
+
│ └── types.ts # TypeScript interfaces
|
|
610
|
+
├── package.json
|
|
611
|
+
├── tsconfig.json
|
|
612
|
+
├── vite.config.ts
|
|
613
|
+
└── README.md
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
## Build Configuration
|
|
617
|
+
|
|
618
|
+
### Vite
|
|
619
|
+
|
|
620
|
+
The project uses Vite 7 with:
|
|
621
|
+
- **@vitejs/plugin-react** for Fast Refresh
|
|
622
|
+
- **babel-plugin-react-compiler** for automatic optimizations
|
|
623
|
+
- HMR (Hot Module Replacement) enabled
|
|
624
|
+
- TypeScript support out of the box
|
|
625
|
+
|
|
626
|
+
### TypeScript
|
|
627
|
+
|
|
628
|
+
Strict mode enabled with:
|
|
629
|
+
- **noImplicitAny**: Require explicit types
|
|
630
|
+
- **strictNullChecks**: Catch null/undefined errors
|
|
631
|
+
- **esModuleInterop**: Better module compatibility
|
|
632
|
+
|
|
633
|
+
## Contributing
|
|
634
|
+
|
|
635
|
+
1. Follow the existing code style
|
|
636
|
+
2. Use TypeScript for all new files
|
|
637
|
+
3. Add/update ADRs for architectural decisions
|
|
638
|
+
4. Test responsive behavior on mobile and desktop
|
|
639
|
+
5. Ensure no console errors or warnings
|
|
640
|
+
|
|
641
|
+
## Troubleshooting
|
|
642
|
+
|
|
643
|
+
### Common Issues
|
|
644
|
+
|
|
645
|
+
#### Navigation not working
|
|
646
|
+
|
|
647
|
+
**Symptoms**: Clicks don't navigate, URLs incorrect
|
|
648
|
+
|
|
649
|
+
**Solutions**:
|
|
650
|
+
- Ensure `frontendUrl` is set in site settings for desk mode
|
|
651
|
+
- Check that URLs are valid (full URLs or relative paths starting with `/`)
|
|
652
|
+
- Verify SDK settings instance is being passed correctly
|
|
653
|
+
- Check console for navigation errors
|
|
654
|
+
|
|
655
|
+
```typescript
|
|
656
|
+
// Debug navigation
|
|
657
|
+
console.log('Settings:', await settings.get())
|
|
658
|
+
console.log('Is Desk?', await isDesk(settings))
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
#### Styles not applying
|
|
662
|
+
|
|
663
|
+
**Symptoms**: Components look unstyled or broken
|
|
664
|
+
|
|
665
|
+
**Solutions**:
|
|
666
|
+
- Check that MUI is installed as a peer dependency: `npm list @mui/material`
|
|
667
|
+
- Verify design tokens are imported in component styles
|
|
668
|
+
- Ensure `sx` prop is used (not `style`)
|
|
669
|
+
- Check for CSS conflicts from parent app
|
|
670
|
+
|
|
671
|
+
```bash
|
|
672
|
+
# Verify MUI installation
|
|
673
|
+
npm list @mui/material @emotion/react @emotion/styled
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
#### Click-outside not working
|
|
677
|
+
|
|
678
|
+
**Symptoms**: Menus don't close when clicking outside
|
|
679
|
+
|
|
680
|
+
**Solutions**:
|
|
681
|
+
- Check that menus have proper refs assigned
|
|
682
|
+
- Verify useEffect dependencies include all `show*` states
|
|
683
|
+
- Ensure no other click handlers are interfering with event propagation
|
|
684
|
+
- Check that `menuRef` is attached to menu container
|
|
685
|
+
|
|
686
|
+
#### App launcher empty
|
|
687
|
+
|
|
688
|
+
**Symptoms**: No apps showing in launcher
|
|
689
|
+
|
|
690
|
+
**Solutions**:
|
|
691
|
+
- Verify `user.getApps()` returns data
|
|
692
|
+
- Check console for API errors
|
|
693
|
+
- Ensure apps have required fields: `id`, `appname`, `icon`, `url`
|
|
694
|
+
- Test with mock data to isolate issue
|
|
695
|
+
|
|
696
|
+
```typescript
|
|
697
|
+
// Debug apps data
|
|
698
|
+
console.log('Apps:', await user.current.getApps())
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
#### Icons not showing
|
|
702
|
+
|
|
703
|
+
**Symptoms**: Icons appear as boxes or missing
|
|
704
|
+
|
|
705
|
+
**Solutions**:
|
|
706
|
+
- Verify FontAwesome packages installed
|
|
707
|
+
- Check icon names match FontAwesome free icons
|
|
708
|
+
- Ensure `library.add(fas, far)` is called
|
|
709
|
+
- Use correct icon name format (without `fa-` prefix)
|
|
710
|
+
|
|
711
|
+
```typescript
|
|
712
|
+
// Debug icon
|
|
713
|
+
<FontAwesomeIcon icon={["fas", "envelope"]} /> // Correct
|
|
714
|
+
<FontAwesomeIcon icon={["fas", "fa-envelope"]} /> // Wrong
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
### Getting Help
|
|
718
|
+
|
|
719
|
+
1. Check the [ADR documentation](./adr.md) for architecture details
|
|
720
|
+
2. Review [existing ADRs](./docs/adr/) for design decisions
|
|
721
|
+
3. Enable verbose logging in development
|
|
722
|
+
4. Contact the Taruvi development team for support
|
|
723
|
+
|
|
724
|
+
## License
|
|
725
|
+
|
|
726
|
+
Internal Taruvi project - All rights reserved
|
|
727
|
+
|
|
728
|
+
## Documentation
|
|
729
|
+
|
|
730
|
+
### Architecture Decision Records (ADRs)
|
|
731
|
+
|
|
732
|
+
- **[Comprehensive ADR](./adr.md)** - Complete architectural decisions and rationale
|
|
733
|
+
- **[ADR 001: Navkit Architecture](./docs/adr/001-navkit-architecture.md)** - Detailed component architecture
|
|
734
|
+
- **[Future Considerations](./adr.md#future-considerations)** - Planned enhancements
|
|
735
|
+
|
|
736
|
+
### Key Documentation Sections
|
|
737
|
+
|
|
738
|
+
| Topic | Location |
|
|
739
|
+
|-------|----------|
|
|
740
|
+
| Technology stack decisions | [adr.md - Tech Stack](./adr.md#technology-stack) |
|
|
741
|
+
| State management strategy | [adr.md - State Management](./adr.md#state-management-strategy) |
|
|
742
|
+
| Navigation system | [adr.md - Navigation System](./adr.md#navigation-system) |
|
|
743
|
+
| Responsive design | [adr.md - Responsive Design](./adr.md#responsive-design) |
|
|
744
|
+
| Performance optimizations | [adr.md - Performance](./adr.md#performance-optimizations) |
|
|
745
|
+
| Component architecture | [docs/adr/001](./docs/adr/001-navkit-architecture.md) |
|
|
746
|
+
|
|
747
|
+
### External Resources
|
|
748
|
+
|
|
749
|
+
- [React 19 Documentation](https://react.dev/)
|
|
750
|
+
- [Material-UI Documentation](https://mui.com/)
|
|
751
|
+
- [Vite Documentation](https://vite.dev/)
|
|
752
|
+
- [TypeScript Handbook](https://www.typescriptlang.org/docs/)
|
|
753
|
+
- [FontAwesome Icons](https://fontawesome.com/search?o=r&m=free)
|
|
754
|
+
|
|
755
|
+
## Support
|
|
756
|
+
|
|
757
|
+
For issues, questions, or feature requests, contact the Taruvi development team.
|