Chapter 2: Navigation

The top navigation bar. Displays the title and actions.

Basic Syntax

import { Navbar, UpperNavbarItem } from '@cap-rel/smartcommon';
import { FiMenu, FiUser } from 'react-icons/fi';

function MyPage() {
    return (
        <>
            <Navbar title="My Application">
                <UpperNavbarItem icon={FiMenu} onClick={openMenu} />
                <UpperNavbarItem icon={FiUser} onClick={goToProfile} />
            </Navbar>
            {/* Content */}
        </>
    );
}
Prop Type Description
title string Main title
subtitle string Optional subtitle
showBack boolean Show back button
onBack function Back button callback

UpperNavbarItem Props

Prop Type Description
icon Component react-icons icon
onClick function Click action
badge number Notification counter

Side menu with navigation.

Syntax

import { useState } from 'react';
import { Sidebar, Button } from '@cap-rel/smartcommon';
import { useNavigation, useGlobalStates, useApi } from '@cap-rel/smartcommon';
import { FiHome, FiList, FiSettings, FiLogOut } from 'react-icons/fi';

function MainLayout({ children }) {
    const [isSidebarOpen, setIsSidebarOpen] = useState(false);
    const nav = useNavigation();
    const api = useApi();
    const gst = useGlobalStates();

    const menuItems = [
        { icon: FiHome, label: 'Home', path: '/' },
        { icon: FiList, label: 'Products', path: '/products' },
        { icon: FiSettings, label: 'Settings', path: '/settings' }
    ];

    const handleLogout = async () => {
        await api.logout();
        nav.navigate('/login');
    };

    return (
        <>
            <Sidebar
                isOpen={isSidebarOpen}
                onClose={() => setIsSidebarOpen(false)}
            >
                {/* User header */}
                <div className="p-4 border-b">
                    <p className="font-bold">{gst.get('session')?.user?.name}</p>
                    <p className="text-sm text-gray-500">{gst.get('session')?.user?.email}</p>
                </div>

                {/* Menu */}
                <nav className="p-2">
                    {menuItems.map(item => (
                        <button
                            key={item.path}
                            onClick={() => {
                                nav.navigate(item.path);
                                setIsSidebarOpen(false);
                            }}
                            className="flex items-center gap-3 w-full p-3 rounded hover:bg-gray-100"
                        >
                            <item.icon />
                            {item.label}
                        </button>
                    ))}
                </nav>

                {/* Logout */}
                <div className="p-4 border-t mt-auto">
                    <Button onClick={handleLogout} variant="outline" className="w-full">
                        <FiLogOut className="mr-2" />
                        Logout
                    </Button>
                </div>
            </Sidebar>

            {children}
        </>
    );
}

Props

Prop Type Description
isOpen boolean Controls display
onClose function Close callback
position string 'left' or 'right'

Tabbar

Bottom tab bar (mobile navigation).

Syntax

import { Tabbar, TabbarItem } from '@cap-rel/smartcommon';
import { useNavigation } from '@cap-rel/smartcommon';
import { useLocation } from 'react-router-dom';
import { FiHome, FiSearch, FiShoppingCart, FiUser } from 'react-icons/fi';

function AppTabbar() {
    const nav = useNavigation();
    const location = useLocation();

    const tabs = [
        { icon: FiHome, label: 'Home', path: '/' },
        { icon: FiSearch, label: 'Search', path: '/search' },
        { icon: FiShoppingCart, label: 'Cart', path: '/cart', badge: 3 },
        { icon: FiUser, label: 'Profile', path: '/profile' }
    ];

    return (
        <Tabbar>
            {tabs.map(tab => (
                <TabbarItem
                    key={tab.path}
                    icon={tab.icon}
                    label={tab.label}
                    active={location.pathname === tab.path}
                    badge={tab.badge}
                    onClick={() => nav.navigate(tab.path)}
                />
            ))}
        </Tabbar>
    );
}

TabbarItem Props

Prop Type Description
icon Component react-icons icon
label string Text below icon
active boolean Selected state
badge number Notification counter
onClick function Click action

useNavigation

Hook for programmatic navigation.

Syntax

import { useNavigation } from '@cap-rel/smartcommon';

function MyComponent() {
    const nav = useNavigation();

    return (
        <div>
            {/* Navigate to route */}
            <button onClick={() => nav.navigate('/products')}>
                View products
            </button>

            {/* Navigate with parameter */}
            <button onClick={() => nav.navigate(`/products/${productId}`)}>
                Details
            </button>

            {/* Go back */}
            <button onClick={() => nav.navigate(-1)}>
                Back
            </button>

            {/* Replace (no history) */}
            <button onClick={() => nav.replace('/login')}>
                Login
            </button>
        </div>
    );
}

Complete Example: Layout with Navigation

// components/layouts/MainLayout/index.jsx
import { useState } from 'react';
import { useLocation } from 'react-router-dom';
import {
    Navbar,
    Sidebar,
    Tabbar,
    TabbarItem,
    UpperNavbarItem
} from '@cap-rel/smartcommon';
import { useNavigation, useGlobalStates, useApi } from '@cap-rel/smartcommon';
import {
    FiMenu,
    FiHome,
    FiList,
    FiPlus,
    FiSettings,
    FiLogOut
} from 'react-icons/fi';

export const MainLayout = ({ children, title }) => {
    const [sidebarOpen, setSidebarOpen] = useState(false);
    const nav = useNavigation();
    const location = useLocation();
    const api = useApi();
    const gst = useGlobalStates();

    const handleLogout = async () => {
        await api.logout();
        nav.navigate('/login');
    };

    return (
        <div className="min-h-screen flex flex-col">
            {/* Navbar */}
            <Navbar title={title}>
                <UpperNavbarItem
                    icon={FiMenu}
                    onClick={() => setSidebarOpen(true)}
                />
            </Navbar>

            {/* Sidebar */}
            <Sidebar
                isOpen={sidebarOpen}
                onClose={() => setSidebarOpen(false)}
            >
                <div className="p-4 border-b">
                    <p className="font-bold">{gst.get('session')?.user?.name}</p>
                </div>

                <nav className="flex-1 p-2">
                    <SidebarLink
                        icon={FiHome}
                        label="Home"
                        onClick={() => {
                            nav.navigate('/');
                            setSidebarOpen(false);
                        }}
                    />
                    <SidebarLink
                        icon={FiList}
                        label="Products"
                        onClick={() => {
                            nav.navigate('/products');
                            setSidebarOpen(false);
                        }}
                    />
                    <SidebarLink
                        icon={FiSettings}
                        label="Settings"
                        onClick={() => {
                            nav.navigate('/settings');
                            setSidebarOpen(false);
                        }}
                    />
                </nav>

                <div className="p-4 border-t">
                    <button
                        onClick={handleLogout}
                        className="flex items-center gap-2 text-red-500"
                    >
                        <FiLogOut /> Logout
                    </button>
                </div>
            </Sidebar>

            {/* Main content */}
            <main className="flex-1 pb-16">
                {children}
            </main>

            {/* Tabbar */}
            <Tabbar>
                <TabbarItem
                    icon={FiHome}
                    label="Home"
                    active={location.pathname === '/'}
                    onClick={() => nav.navigate('/')}
                />
                <TabbarItem
                    icon={FiList}
                    label="Products"
                    active={location.pathname.startsWith('/products')}
                    onClick={() => nav.navigate('/products')}
                />
                <TabbarItem
                    icon={FiPlus}
                    label="New"
                    onClick={() => nav.navigate('/products/new')}
                />
                <TabbarItem
                    icon={FiSettings}
                    label="Settings"
                    active={location.pathname === '/settings'}
                    onClick={() => nav.navigate('/settings')}
                />
            </Tabbar>
        </div>
    );
};

// Helper component
const SidebarLink = ({ icon: Icon, label, onClick }) => (
    <button
        onClick={onClick}
        className="flex items-center gap-3 w-full p-3 rounded hover:bg-gray-100"
    >
        <Icon />
        {label}
    </button>
);

Using the Layout

// components/pages/private/ProductsPage/index.jsx
import { MainLayout } from '../../../layouts/MainLayout';
import { Block, List, ListItem } from '@cap-rel/smartcommon';

export const ProductsPage = () => {
    const products = [...];

    return (
        <MainLayout title="Products">
            <Block>
                <List>
                    {products.map(p => (
                        <ListItem
                            key={p.id}
                            title={p.label}
                            subtitle={`${p.price} €`}
                        />
                    ))}
                </List>
            </Block>
        </MainLayout>
    );
};

Key Points to Remember

  1. Navbar = top bar with title and actions
  2. Sidebar = sliding side menu
  3. Tabbar = bottom tab navigation
  4. useNavigation = programmatic navigation
  5. Combine these components into a Reusable Layout

Previous Chapter | Back to Module | Next Chapter: Forms ->