@idealyst/mcp-server 1.2.114 → 1.2.116

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/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  storageGuides,
8
8
  toolDefinitions,
9
9
  translateGuides
10
- } from "./chunk-7WPOVADU.js";
10
+ } from "./chunk-TLA6ZBC5.js";
11
11
 
12
12
  // src/index.ts
13
13
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -2174,11 +2174,13 @@ For tab navigators:
2174
2174
 
2175
2175
  \`\`\`tsx
2176
2176
  type TabBarScreenOptions = {
2177
- tabBarIcon?: (props: {
2177
+ // String form (simplest): just the icon name
2178
+ // Function form: render function (see warning below about size param)
2179
+ tabBarIcon?: string | ((props: {
2178
2180
  focused: boolean;
2179
2181
  color: string;
2180
2182
  size: string | number
2181
- }) => React.ReactElement;
2183
+ }) => React.ReactElement);
2182
2184
 
2183
2185
  tabBarLabel?: string; // Tab label
2184
2186
  tabBarBadge?: string | number; // Badge count
@@ -2186,9 +2188,11 @@ type TabBarScreenOptions = {
2186
2188
  } & ScreenOptions;
2187
2189
  \`\`\`
2188
2190
 
2191
+ > **tabBarIcon WARNING:** The function form receives \`{ size: number }\` from native tab bars, but Idealyst's Icon component expects a Size token (\`'xs' | 'sm' | 'md' | 'lg' | 'xl'\`). **Do NOT pass the size param to Icon.** Use a fixed size token instead.
2192
+
2189
2193
  > **Nested navigators:** When a Stack is nested inside a Tab, the **stack's root route** still uses \`TabBarScreenOptions\` for its \`options\` (it needs tabBarIcon/tabBarLabel for the tab bar). Type it as \`options: TabBarScreenOptions\` on the stack wrapper route.
2190
2194
 
2191
- Example:
2195
+ Example (string form -- simplest):
2192
2196
  \`\`\`tsx
2193
2197
  {
2194
2198
  path: "home",
@@ -2196,8 +2200,23 @@ Example:
2196
2200
  component: HomeScreen,
2197
2201
  options: {
2198
2202
  tabBarLabel: "Home",
2199
- tabBarIcon: ({ focused, color }) => (
2200
- <Icon name="home" color={color} />
2203
+ tabBarIcon: "home", // Just the icon name -- layout renders it automatically
2204
+ tabBarBadge: 5
2205
+ }
2206
+ }
2207
+ \`\`\`
2208
+
2209
+ Example (function form -- for focused/unfocused variants):
2210
+ \`\`\`tsx
2211
+ {
2212
+ path: "home",
2213
+ type: 'screen',
2214
+ component: HomeScreen,
2215
+ options: {
2216
+ tabBarLabel: "Home",
2217
+ // Ignore the size param -- use a Size token ('sm', 'md', etc.) instead
2218
+ tabBarIcon: ({ focused }) => (
2219
+ <Icon name={focused ? 'home' : 'home-outline'} size="sm" />
2201
2220
  ),
2202
2221
  tabBarBadge: 5
2203
2222
  }
@@ -2409,7 +2428,7 @@ Section-based navigation with a tab bar.
2409
2428
  component: HomeScreen,
2410
2429
  options: {
2411
2430
  tabBarLabel: "Home",
2412
- tabBarIcon: ({ color }) => <Icon name="home" color={color} />
2431
+ tabBarIcon: "home", // String form: just the icon name
2413
2432
  }
2414
2433
  },
2415
2434
  {
@@ -2418,7 +2437,10 @@ Section-based navigation with a tab bar.
2418
2437
  component: SearchScreen,
2419
2438
  options: {
2420
2439
  tabBarLabel: "Search",
2421
- tabBarIcon: ({ color }) => <Icon name="search" color={color} />
2440
+ // Function form: use focused for icon variants. Ignore size param.
2441
+ tabBarIcon: ({ focused }) => (
2442
+ <Icon name={focused ? 'magnify' : 'magnify'} size="sm" />
2443
+ ),
2422
2444
  }
2423
2445
  },
2424
2446
  ]
@@ -2446,34 +2468,110 @@ Section-based navigation with a tab bar.
2446
2468
 
2447
2469
  ## Drawer Navigator
2448
2470
 
2449
- Side menu navigation, primarily for desktop/tablet.
2471
+ Side menu navigation with a persistent sidebar. Ideal for dashboards and admin panels.
2450
2472
 
2451
2473
  ### Configuration
2452
2474
 
2453
2475
  \`\`\`tsx
2454
- {
2476
+ import { NavigatorParam } from '@idealyst/navigation';
2477
+
2478
+ const AppRouter: NavigatorParam = {
2455
2479
  path: "/",
2456
2480
  type: 'navigator',
2457
2481
  layout: 'drawer',
2458
2482
  routes: [
2459
- { path: "dashboard", type: 'screen', component: DashboardScreen },
2460
- { path: "users", type: 'screen', component: UsersScreen },
2461
- { path: "settings", type: 'screen', component: SettingsScreen },
2483
+ {
2484
+ path: "",
2485
+ type: 'screen',
2486
+ component: DashboardScreen,
2487
+ options: { title: 'Dashboard', tabBarLabel: 'Dashboard' }
2488
+ },
2489
+ {
2490
+ path: "users",
2491
+ type: 'screen',
2492
+ component: UsersScreen,
2493
+ options: { title: 'Users', tabBarLabel: 'Users' }
2494
+ },
2495
+ {
2496
+ path: "settings",
2497
+ type: 'screen',
2498
+ component: SettingsScreen,
2499
+ options: { title: 'Settings', tabBarLabel: 'Settings' }
2500
+ },
2462
2501
  ]
2502
+ };
2503
+ \`\`\`
2504
+
2505
+ > **Route options:** Drawer routes use \`TabBarScreenOptions\` \u2014 set \`tabBarLabel\` for the sidebar label and \`title\` for the screen title. Both are displayed in the default sidebar.
2506
+
2507
+ ### Custom Sidebar Component
2508
+
2509
+ You can provide a custom sidebar via \`sidebarComponent\`. The component receives \`DrawerSidebarProps\` which includes:
2510
+ - \`currentPath\`: The current URL/route path \u2014 use this for active state highlighting
2511
+ - \`insets\`: Safe area insets (mobile only, for notch/status bar padding)
2512
+
2513
+ \`\`\`tsx
2514
+ import { DrawerSidebarProps, useNavigator } from '@idealyst/navigation';
2515
+ import { View, Text, Pressable, Icon } from '@idealyst/components';
2516
+
2517
+ // currentPath is available both as a prop AND from useNavigator()
2518
+ function CustomSidebar({ currentPath, insets }: DrawerSidebarProps) {
2519
+ const { navigate } = useNavigator();
2520
+
2521
+ const navItems = [
2522
+ { path: '/', label: 'Dashboard', icon: 'view-dashboard' as const },
2523
+ { path: '/projects', label: 'Projects', icon: 'folder' as const },
2524
+ { path: '/settings', label: 'Settings', icon: 'cog' as const },
2525
+ ];
2526
+
2527
+ return (
2528
+ <View style={{ flex: 1, paddingTop: insets?.top ?? 0 }} background="secondary">
2529
+ <Text typography="h6" weight="bold" padding="lg">My App</Text>
2530
+ {navItems.map((item) => {
2531
+ const isActive = currentPath === item.path
2532
+ || (item.path !== '/' && currentPath.startsWith(item.path + '/'));
2533
+ return (
2534
+ <Pressable key={item.path} onPress={() => navigate({ path: item.path })}>
2535
+ <View
2536
+ style={{ flexDirection: 'row', alignItems: 'center' }}
2537
+ padding="md"
2538
+ gap="md"
2539
+ background={isActive ? 'primary' : 'transparent'}
2540
+ >
2541
+ <Icon name={item.icon} size="md" intent={isActive ? 'primary' : undefined} />
2542
+ <Text weight={isActive ? 'semibold' : 'normal'}>{item.label}</Text>
2543
+ </View>
2544
+ </Pressable>
2545
+ );
2546
+ })}
2547
+ </View>
2548
+ );
2463
2549
  }
2550
+
2551
+ const AppRouter: NavigatorParam = {
2552
+ path: "/",
2553
+ type: 'navigator',
2554
+ layout: 'drawer',
2555
+ sidebarComponent: CustomSidebar,
2556
+ routes: [...]
2557
+ };
2464
2558
  \`\`\`
2465
2559
 
2560
+ > **TIP:** \`currentPath\` is available both as a prop in \`DrawerSidebarProps\` AND from \`useNavigator()\`. Either approach works: \`const { navigate, currentPath } = useNavigator()\` or use the prop.
2561
+
2466
2562
  ### Platform Behavior
2467
2563
 
2468
2564
  **Mobile:**
2469
- - Slide-out drawer
2470
- - Swipe gesture to open
2565
+ - Slide-out drawer with swipe gesture
2471
2566
  - Overlay when open
2567
+ - Custom \`sidebarComponent\` receives \`DrawerSidebarProps\` with \`currentPath\` and safe area \`insets\`
2472
2568
 
2473
2569
  **Web:**
2474
- - Sidebar navigation
2475
- - Can be persistent or overlay
2476
- - Responsive behavior
2570
+ - Fixed 240px left sidebar with navigation items
2571
+ - Items show \`tabBarLabel\` (or \`title\`) from route options
2572
+ - Active route is highlighted
2573
+ - If \`sidebarComponent\` is provided, it replaces the default sidebar
2574
+ - Custom sidebar receives \`DrawerSidebarProps\` with \`currentPath\`
2477
2575
 
2478
2576
  ### Use Cases
2479
2577
  - Admin panels
@@ -2570,9 +2668,92 @@ const appRouter: RouteParam = {
2570
2668
 
2571
2669
  On web, navigators can use custom layout components to add headers, sidebars, and other UI around route content.
2572
2670
 
2671
+ ## IMPORTANT: Layout Component File Structure
2672
+
2673
+ Layout components are **web-only**. Native ignores \`layoutComponent\` entirely. You must create platform-specific files so the native build doesn't import web-only code:
2674
+
2675
+ \`\`\`
2676
+ layouts/
2677
+ AppLayout.web.tsx \u2190 Real layout with Outlet from @idealyst/navigation
2678
+ AppLayout.native.tsx \u2190 No-op mock (return null)
2679
+ index.web.ts \u2190 export { AppLayout } from './AppLayout.web'
2680
+ index.native.ts \u2190 export { AppLayout } from './AppLayout.native'
2681
+ \`\`\`
2682
+
2683
+ ### Example Files
2684
+
2685
+ **\`AppLayout.web.tsx\`** \u2014 The real layout:
2686
+ \`\`\`tsx
2687
+ import React from 'react';
2688
+ import { Outlet, useNavigator } from '@idealyst/navigation';
2689
+ import type { StackLayoutProps } from '@idealyst/navigation';
2690
+ import { View, Text, Pressable, Icon } from '@idealyst/components';
2691
+
2692
+ export function AppLayout({ routes, currentPath, options }: StackLayoutProps) {
2693
+ const { navigate } = useNavigator();
2694
+ return (
2695
+ <View style={{ flex: 1, flexDirection: 'row' }}>
2696
+ <View style={{ width: 240, borderRightWidth: 1, borderRightColor: '#e0e0e0' }}>
2697
+ {routes.map((route) => (
2698
+ <Pressable key={route.fullPath} onPress={() => navigate({ path: route.fullPath })}>
2699
+ <Text style={{ padding: 12, fontWeight: currentPath === route.fullPath ? 'bold' : 'normal' }}>
2700
+ {route.options?.title || route.path}
2701
+ </Text>
2702
+ </Pressable>
2703
+ ))}
2704
+ </View>
2705
+ <View style={{ flex: 1 }}>
2706
+ <Outlet />
2707
+ </View>
2708
+ </View>
2709
+ );
2710
+ }
2711
+ \`\`\`
2712
+
2713
+ **\`AppLayout.native.tsx\`** \u2014 No-op mock (native uses its own navigator UI):
2714
+ \`\`\`tsx
2715
+ export function AppLayout() {
2716
+ return null;
2717
+ }
2718
+ \`\`\`
2719
+
2720
+ **\`index.web.ts\`**:
2721
+ \`\`\`ts
2722
+ export { AppLayout } from './AppLayout.web';
2723
+ \`\`\`
2724
+
2725
+ **\`index.native.ts\`**:
2726
+ \`\`\`ts
2727
+ export { AppLayout } from './AppLayout.native';
2728
+ \`\`\`
2729
+
2730
+ **\`AppRouter.ts\`** \u2014 Wiring:
2731
+ \`\`\`tsx
2732
+ import { AppLayout } from './layouts';
2733
+ import type { NavigatorParam } from '@idealyst/navigation';
2734
+
2735
+ const appRouter: NavigatorParam = {
2736
+ path: '/',
2737
+ type: 'navigator',
2738
+ layout: 'stack',
2739
+ layoutComponent: AppLayout, // Web only \u2014 native ignores this
2740
+ routes: [
2741
+ { path: '', type: 'screen', component: HomeScreen },
2742
+ { path: 'settings', type: 'screen', component: SettingsScreen },
2743
+ ],
2744
+ };
2745
+ \`\`\`
2746
+
2747
+ > **Key rules:**
2748
+ > - Import \`Outlet\` from \`@idealyst/navigation\` (NOT from \`react-router-dom\`)
2749
+ > - Layout props do NOT include \`children\` \u2014 content renders via \`<Outlet />\`
2750
+ > - Always create both \`.web.tsx\` and \`.native.tsx\` files with platform index files
2751
+
2573
2752
  ## GeneralLayout Component
2574
2753
 
2575
- The built-in \`GeneralLayout\` provides header and sidebar functionality:
2754
+ > **Note:** \`GeneralLayout\` is a reference pattern shown in documentation. For production apps, build custom layouts using Idealyst components (\`View\`, \`Text\`, \`Pressable\`, \`Icon\`) with \`<Outlet />\` from \`@idealyst/navigation\`. The examples below illustrate the configuration API.
2755
+
2756
+ The \`GeneralLayout\` demonstrates header and sidebar configuration:
2576
2757
 
2577
2758
  ### Basic Usage
2578
2759
 
@@ -2589,7 +2770,7 @@ import { GeneralLayout } from '@idealyst/navigation';
2589
2770
  content: <NavigationMenu />,
2590
2771
  }}
2591
2772
  >
2592
- {children}
2773
+ <Outlet />
2593
2774
  </GeneralLayout>
2594
2775
  \`\`\`
2595
2776
 
@@ -2687,36 +2868,32 @@ const router: NavigatorParam = {
2687
2868
  ### Stack Layout Component
2688
2869
 
2689
2870
  \`\`\`tsx
2690
- import { GeneralLayout } from '@idealyst/navigation';
2871
+ import { Outlet } from '@idealyst/navigation';
2691
2872
  import type { StackLayoutProps } from '@idealyst/navigation';
2692
2873
 
2693
2874
  export const CustomStackLayout: React.FC<StackLayoutProps> = ({
2694
- children,
2695
2875
  options,
2696
2876
  routes,
2697
2877
  currentPath
2698
2878
  }) => {
2699
2879
  return (
2700
- <GeneralLayout
2701
- header={{
2702
- enabled: true,
2703
- content: (
2704
- <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
2705
- <Text>{options?.headerTitle || 'My App'}</Text>
2706
- {options?.headerRight}
2707
- </View>
2708
- )
2709
- }}
2710
- sidebar={{
2711
- enabled: true,
2712
- collapsible: true,
2713
- content: (
2880
+ <View style={{ flex: 1 }}>
2881
+ {/* Header */}
2882
+ <View style={{ height: 56, flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16 }}>
2883
+ <Text>{options?.headerTitle || 'My App'}</Text>
2884
+ <View style={{ marginLeft: 'auto' }}>{options?.headerRight}</View>
2885
+ </View>
2886
+ <View style={{ flex: 1, flexDirection: 'row' }}>
2887
+ {/* Sidebar */}
2888
+ <View style={{ width: 240 }}>
2714
2889
  <NavigationMenu routes={routes} currentPath={currentPath} />
2715
- )
2716
- }}
2717
- >
2718
- {children}
2719
- </GeneralLayout>
2890
+ </View>
2891
+ {/* Content \u2014 rendered via Outlet, NOT children */}
2892
+ <View style={{ flex: 1 }}>
2893
+ <Outlet />
2894
+ </View>
2895
+ </View>
2896
+ </View>
2720
2897
  );
2721
2898
  };
2722
2899
  \`\`\`
@@ -2724,10 +2901,10 @@ export const CustomStackLayout: React.FC<StackLayoutProps> = ({
2724
2901
  ### Tab Layout Component
2725
2902
 
2726
2903
  \`\`\`tsx
2904
+ import { Outlet } from '@idealyst/navigation';
2727
2905
  import type { TabLayoutProps } from '@idealyst/navigation';
2728
2906
 
2729
2907
  export const CustomTabLayout: React.FC<TabLayoutProps> = ({
2730
- children,
2731
2908
  routes,
2732
2909
  currentPath
2733
2910
  }) => {
@@ -2739,8 +2916,8 @@ export const CustomTabLayout: React.FC<TabLayoutProps> = ({
2739
2916
  <View style={{ flexDirection: 'row', borderBottom: '1px solid #ccc' }}>
2740
2917
  {routes.map(route => (
2741
2918
  <Pressable
2742
- key={route.path}
2743
- onPress={() => navigator.navigate({ path: route.fullPath, vars: {} })}
2919
+ key={route.fullPath}
2920
+ onPress={() => navigator.navigate({ path: route.fullPath })}
2744
2921
  style={{
2745
2922
  padding: 16,
2746
2923
  borderBottom: currentPath === route.fullPath ? '2px solid blue' : 'none'
@@ -2751,9 +2928,9 @@ export const CustomTabLayout: React.FC<TabLayoutProps> = ({
2751
2928
  ))}
2752
2929
  </View>
2753
2930
 
2754
- {/* Content */}
2931
+ {/* Content \u2014 rendered via Outlet, NOT children */}
2755
2932
  <View style={{ flex: 1 }}>
2756
- {children}
2933
+ <Outlet />
2757
2934
  </View>
2758
2935
  </View>
2759
2936
  );
@@ -2762,6 +2939,8 @@ export const CustomTabLayout: React.FC<TabLayoutProps> = ({
2762
2939
 
2763
2940
  ## Layout Props Reference
2764
2941
 
2942
+ > **IMPORTANT:** Layout props do NOT include \`children\`. Route content is rendered via \`<Outlet />\` imported from \`@idealyst/navigation\`.
2943
+
2765
2944
  ### StackLayoutProps
2766
2945
 
2767
2946
  \`\`\`tsx
@@ -2769,8 +2948,8 @@ type StackLayoutProps = {
2769
2948
  options?: NavigatorOptions; // Navigator options
2770
2949
  routes: RouteWithFullPath[]; // All routes with full paths
2771
2950
  currentPath: string; // Current active path
2772
- children?: React.ReactNode; // Route content
2773
2951
  };
2952
+ // Content renders via <Outlet /> from @idealyst/navigation \u2014 NOT via children
2774
2953
  \`\`\`
2775
2954
 
2776
2955
  ### TabLayoutProps
@@ -2780,8 +2959,8 @@ type TabLayoutProps = {
2780
2959
  options?: NavigatorOptions; // Navigator options
2781
2960
  routes: RouteWithFullPath<TabBarScreenOptions>[]; // Tab routes
2782
2961
  currentPath: string; // Current active path
2783
- children?: React.ReactNode; // Route content
2784
2962
  };
2963
+ // Content renders via <Outlet /> from @idealyst/navigation \u2014 NOT via children
2785
2964
  \`\`\`
2786
2965
 
2787
2966
  ## Real-World Examples
@@ -2789,41 +2968,35 @@ type TabLayoutProps = {
2789
2968
  ### Dashboard Layout
2790
2969
 
2791
2970
  \`\`\`tsx
2971
+ import { Outlet } from '@idealyst/navigation';
2972
+
2792
2973
  export const DashboardLayout: React.FC<StackLayoutProps> = ({
2793
- children,
2794
2974
  routes,
2795
- currentPath
2975
+ currentPath,
2976
+ options
2796
2977
  }) => {
2978
+ const { navigate } = useNavigator();
2797
2979
  return (
2798
- <GeneralLayout
2799
- header={{
2800
- enabled: true,
2801
- height: 72,
2802
- content: (
2803
- <View style={{
2804
- flexDirection: 'row',
2805
- justifyContent: 'space-between',
2806
- alignItems: 'center',
2807
- padding: 16
2808
- }}>
2809
- <Text typography="h5" weight="bold">Dashboard</Text>
2810
- <View style={{ flexDirection: 'row', gap: 16 }}>
2811
- <NotificationBell />
2812
- <UserAvatar />
2813
- </View>
2814
- </View>
2815
- )
2816
- }}
2817
- sidebar={{
2818
- enabled: true,
2819
- collapsible: true,
2820
- position: 'left',
2821
- expandedWidth: 260,
2822
- content: <DashboardSidebar routes={routes} currentPath={currentPath} />
2823
- }}
2824
- >
2825
- {children}
2826
- </GeneralLayout>
2980
+ <View style={{ flex: 1 }}>
2981
+ {/* Header */}
2982
+ <View style={{ height: 72, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', padding: 16, borderBottomWidth: 1, borderBottomColor: '#e0e0e0' }}>
2983
+ <Text typography="h5" weight="bold">Dashboard</Text>
2984
+ <View style={{ flexDirection: 'row', gap: 16 }}>
2985
+ <NotificationBell />
2986
+ <UserAvatar />
2987
+ </View>
2988
+ </View>
2989
+ <View style={{ flex: 1, flexDirection: 'row' }}>
2990
+ {/* Sidebar */}
2991
+ <View style={{ width: 260 }}>
2992
+ <DashboardSidebar routes={routes} currentPath={currentPath} />
2993
+ </View>
2994
+ {/* Content via Outlet */}
2995
+ <View style={{ flex: 1 }}>
2996
+ <Outlet />
2997
+ </View>
2998
+ </View>
2999
+ </View>
2827
3000
  );
2828
3001
  };
2829
3002
  \`\`\`
@@ -2831,27 +3004,21 @@ export const DashboardLayout: React.FC<StackLayoutProps> = ({
2831
3004
  ### Admin Panel Layout
2832
3005
 
2833
3006
  \`\`\`tsx
2834
- export const AdminLayout: React.FC<StackLayoutProps> = ({ children }) => {
3007
+ import { Outlet } from '@idealyst/navigation';
3008
+
3009
+ export const AdminLayout: React.FC<StackLayoutProps> = ({ options }) => {
2835
3010
  return (
2836
- <GeneralLayout
2837
- header={{
2838
- enabled: true,
2839
- content: <AdminHeader />,
2840
- style: { backgroundColor: '#1a1a1a', color: '#fff' }
2841
- }}
2842
- sidebar={{
2843
- enabled: true,
2844
- collapsible: true,
2845
- position: 'left',
2846
- initiallyExpanded: true,
2847
- content: <AdminNavigationMenu />,
2848
- style: { backgroundColor: '#2a2a2a' }
2849
- }}
2850
- >
2851
- <View style={{ padding: 24 }}>
2852
- {children}
3011
+ <View style={{ flex: 1 }}>
3012
+ <AdminHeader />
3013
+ <View style={{ flex: 1, flexDirection: 'row' }}>
3014
+ <View style={{ width: 240, backgroundColor: '#2a2a2a' }}>
3015
+ <AdminNavigationMenu />
3016
+ </View>
3017
+ <View style={{ flex: 1, padding: 24 }}>
3018
+ <Outlet />
3019
+ </View>
2853
3020
  </View>
2854
- </GeneralLayout>
3021
+ </View>
2855
3022
  );
2856
3023
  };
2857
3024
  \`\`\`
@@ -3759,18 +3926,18 @@ Every layout component receives these props:
3759
3926
 
3760
3927
  \`\`\`tsx
3761
3928
  type LayoutProps = {
3762
- children: React.ReactNode; // The route content (renders via <Outlet />)
3763
3929
  options?: NavigatorOptions; // headerTitle, headerLeft, headerRight, etc.
3764
3930
  routes: RouteWithFullPath[]; // All child routes with their full paths
3765
3931
  currentPath: string; // Currently active route path
3766
3932
  };
3933
+ // Content renders via <Outlet /> from @idealyst/navigation \u2014 NOT via children
3767
3934
  \`\`\`
3768
3935
 
3769
3936
  **This gives you everything you need to build any navigation UI:**
3770
3937
  - \`options\` - What to show in headers
3771
3938
  - \`routes\` - What tabs/menu items to render
3772
3939
  - \`currentPath\` - Which one is active
3773
- - \`children\` - Where to render the screen content
3940
+ - \`<Outlet />\` - Where to render the screen content (import from @idealyst/navigation)
3774
3941
 
3775
3942
  ## Stack Navigator Parity
3776
3943
 
@@ -3783,10 +3950,9 @@ type LayoutProps = {
3783
3950
  ### Web Implementation
3784
3951
 
3785
3952
  \`\`\`tsx
3786
- import { Outlet } from 'react-router-dom';
3787
- import { View, Text, IconButton, Pressable } from '@idealyst/components';
3788
- import { useNavigator } from '@idealyst/navigation';
3953
+ import { Outlet, useNavigator } from '@idealyst/navigation';
3789
3954
  import type { StackLayoutProps } from '@idealyst/navigation';
3955
+ import { View, Text, IconButton, Pressable } from '@idealyst/components';
3790
3956
 
3791
3957
  export function StackLayout({ options, currentPath }: StackLayoutProps) {
3792
3958
  const { canGoBack, goBack } = useNavigator();
@@ -3863,10 +4029,9 @@ export function StackLayout({ options, currentPath }: StackLayoutProps) {
3863
4029
  ### Web Implementation
3864
4030
 
3865
4031
  \`\`\`tsx
3866
- import { Outlet } from 'react-router-dom';
3867
- import { View, Text, Pressable, Icon, Badge } from '@idealyst/components';
3868
- import { useNavigator } from '@idealyst/navigation';
4032
+ import { Outlet, useNavigator } from '@idealyst/navigation';
3869
4033
  import type { TabLayoutProps } from '@idealyst/navigation';
4034
+ import { View, Text, Pressable, Icon, Badge } from '@idealyst/components';
3870
4035
 
3871
4036
  export function TabLayout({ routes, currentPath }: TabLayoutProps) {
3872
4037
  const { navigate } = useNavigator();
@@ -3903,10 +4068,12 @@ export function TabLayout({ routes, currentPath }: TabLayoutProps) {
3903
4068
  >
3904
4069
  {/* Icon with optional badge */}
3905
4070
  <View style={{ position: 'relative' }}>
3906
- {options?.tabBarIcon?.({
4071
+ {typeof options?.tabBarIcon === 'string' ? (
4072
+ <Icon name={options.tabBarIcon as any} size="sm" intent={isActive ? 'primary' : undefined} />
4073
+ ) : options?.tabBarIcon?.({
3907
4074
  focused: isActive,
3908
4075
  color: isActive ? '#007AFF' : '#8E8E93',
3909
- size: 24,
4076
+ size: 'sm',
3910
4077
  })}
3911
4078
  {options?.tabBarBadge && (
3912
4079
  <Badge
@@ -3951,10 +4118,9 @@ export function TabLayout({ routes, currentPath }: TabLayoutProps) {
3951
4118
  On web, drawers are typically persistent sidebars. Here's how to build both:
3952
4119
 
3953
4120
  \`\`\`tsx
3954
- import { Outlet } from 'react-router-dom';
3955
- import { View, Text, Pressable, Icon } from '@idealyst/components';
3956
- import { useNavigator } from '@idealyst/navigation';
4121
+ import { Outlet, useNavigator } from '@idealyst/navigation';
3957
4122
  import type { StackLayoutProps } from '@idealyst/navigation';
4123
+ import { View, Text, Pressable, Icon } from '@idealyst/components';
3958
4124
 
3959
4125
  export function DrawerLayout({ routes, currentPath, options }: StackLayoutProps) {
3960
4126
  const { navigate } = useNavigator();
@@ -4028,29 +4194,26 @@ The \`GeneralLayout\` component simplifies building layouts:
4028
4194
  \`\`\`tsx
4029
4195
  import { GeneralLayout } from '@idealyst/navigation';
4030
4196
 
4031
- export function AppLayout({ options, routes, currentPath, children }: StackLayoutProps) {
4197
+ export function AppLayout({ options, routes, currentPath }: StackLayoutProps) {
4198
+ const { navigate } = useNavigator();
4032
4199
  return (
4033
- <GeneralLayout
4034
- header={{
4035
- enabled: true,
4036
- height: 56,
4037
- content: (
4038
- <View style={{ flexDirection: 'row', alignItems: 'center', flex: 1 }}>
4039
- <Text typography="h6" weight="bold">{options?.headerTitle || 'App'}</Text>
4040
- <View style={{ marginLeft: 'auto' }}>{options?.headerRight}</View>
4041
- </View>
4042
- ),
4043
- }}
4044
- sidebar={{
4045
- enabled: true,
4046
- collapsible: true,
4047
- expandedWidth: 240,
4048
- collapsedWidth: 64,
4049
- content: <SidebarMenu routes={routes} currentPath={currentPath} />,
4050
- }}
4051
- >
4052
- {children}
4053
- </GeneralLayout>
4200
+ <View style={{ flex: 1 }}>
4201
+ {/* Header */}
4202
+ <View style={{ height: 56, flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, borderBottomWidth: 1, borderBottomColor: '#e0e0e0' }}>
4203
+ <Text typography="h6" weight="bold">{options?.headerTitle || 'App'}</Text>
4204
+ <View style={{ marginLeft: 'auto' }}>{options?.headerRight}</View>
4205
+ </View>
4206
+ <View style={{ flex: 1, flexDirection: 'row' }}>
4207
+ {/* Sidebar */}
4208
+ <View style={{ width: 240 }}>
4209
+ <SidebarMenu routes={routes} currentPath={currentPath} />
4210
+ </View>
4211
+ {/* Content via Outlet */}
4212
+ <View style={{ flex: 1 }}>
4213
+ <Outlet />
4214
+ </View>
4215
+ </View>
4216
+ </View>
4054
4217
  );
4055
4218
  }
4056
4219
  \`\`\`
@@ -4086,7 +4249,7 @@ const appRouter: NavigatorParam = {
4086
4249
  component: HomeScreen,
4087
4250
  options: {
4088
4251
  tabBarLabel: "Home",
4089
- tabBarIcon: ({ color }) => <Icon name="home" color={color} />,
4252
+ tabBarIcon: ({ focused }) => <Icon name={focused ? 'home' : 'home-outline'} size="sm" />,
4090
4253
  },
4091
4254
  },
4092
4255
  {
@@ -4095,7 +4258,7 @@ const appRouter: NavigatorParam = {
4095
4258
  component: SearchScreen,
4096
4259
  options: {
4097
4260
  tabBarLabel: "Search",
4098
- tabBarIcon: ({ color }) => <Icon name="magnify" color={color} />,
4261
+ tabBarIcon: () => <Icon name="magnify" size="sm" />,
4099
4262
  },
4100
4263
  },
4101
4264
  ],
@@ -4116,7 +4279,7 @@ const appRouter: NavigatorParam = {
4116
4279
  3. **Options are your data source** - headerTitle, tabBarIcon, etc. drive your layout
4117
4280
  4. **routes array is navigation menu** - Use it to build sidebars, tab bars, menus
4118
4281
  5. **currentPath enables active states** - Compare to highlight current item
4119
- 6. **Outlet renders children** - From react-router-dom, this is where screen content goes
4282
+ 6. **Outlet renders content** - Import from @idealyst/navigation, this is where screen content goes
4120
4283
 
4121
4284
  ## Common Patterns
4122
4285