---
source_hash: "62d87e8e"
title: "Chapter 1: Layout"
weight: 530
---

# Chapter 1: Layout

## Page

The `Page` component is the main container for each screen. It manages:

- Page title
- Transition animations
- Scroll

### Basic Syntax

```javascript
import { Page } from '@cap-rel/smartcommon';

function HomePage() {
    return (
        <Page title="Home">
            <p>Page content</p>
        </Page>
    );
}
```

### Main Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| title | string | - | Title displayed in the navbar |
| subtitle | string | - | Optional subtitle |
| className | string | - | Additional CSS classes |
| onRefresh | function | - | Pull-to-refresh callback |

### Page with Refresh

```javascript
function ItemsPage() {
    const [items, setItems] = useState([]);

    const handleRefresh = async () => {
        const data = await api.private.get('items').json();
        setItems(data);
    };

    return (
        <Page title="My Items" onRefresh={handleRefresh}>
            {items.map(item => (
                <div key={item.id}>{item.label}</div>
            ))}
        </Page>
    );
}
```

## Block

The `Block` component structures content into distinct visual sections.

### Basic Syntax

```javascript
import { Page, Block } from '@cap-rel/smartcommon';

function ProfilePage() {
    return (
        <Page title="Profile">
            <Block>
                <h2>Personal Information</h2>
                <p>Name: John Doe</p>
            </Block>

            <Block>
                <h2>Preferences</h2>
                <p>Language: French</p>
            </Block>
        </Page>
    );
}
```

### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| title | string | - | Block title |
| className | string | - | Additional CSS classes |
| padding | boolean | true | Add internal padding |

### Block with Title

```javascript
<Block title="Information">
    <p>Block content</p>
</Block>
```

## Panel

The `Panel` component displays a sliding panel from the side of the screen.

### Syntax

```javascript
import { useState } from 'react';
import { Page, Block, Button, Panel } from '@cap-rel/smartcommon';

function MyPage() {
    const [isPanelOpen, setIsPanelOpen] = useState(false);

    return (
        <Page title="My Page">
            <Block>
                <Button onClick={() => setIsPanelOpen(true)}>
                    Open Panel
                </Button>
            </Block>

            <Panel
                isOpen={isPanelOpen}
                onClose={() => setIsPanelOpen(false)}
                position="right"
            >
                <h2>Panel Content</h2>
                <p>Additional information</p>
            </Panel>
        </Page>
    );
}
```

### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| isOpen | boolean | false | Controls display |
| onClose | function | - | Close callback |
| position | string | 'right' | 'left', 'right', 'top', 'bottom' |
| title | string | - | Panel title |

## Popup

The `Popup` component displays a centered modal window.

### Syntax

```javascript
import { useState } from 'react';
import { Page, Block, Button, Popup } from '@cap-rel/smartcommon';

function MyPage() {
    const [isPopupOpen, setIsPopupOpen] = useState(false);

    return (
        <Page title="My Page">
            <Block>
                <Button onClick={() => setIsPopupOpen(true)}>
                    Delete
                </Button>
            </Block>

            <Popup
                isOpen={isPopupOpen}
                onClose={() => setIsPopupOpen(false)}
                title="Confirmation"
            >
                <p>Are you sure you want to delete this item?</p>
                <div className="flex gap-2 mt-4">
                    <Button onClick={() => setIsPopupOpen(false)}>
                        Cancel
                    </Button>
                    <Button variant="danger" onClick={handleDelete}>
                        Delete
                    </Button>
                </div>
            </Popup>
        </Page>
    );
}
```

### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| isOpen | boolean | false | Controls display |
| onClose | function | - | Close callback |
| title | string | - | Popup title |
| closeOnOverlay | boolean | true | Close on overlay click |

## Complete Example

```javascript
import { useState } from 'react';
import {
    Page,
    Block,
    Panel,
    Popup,
    Button,
    List,
    ListItem
} from '@cap-rel/smartcommon';

export const ProductsPage = () => {
    const [selectedProduct, setSelectedProduct] = useState(null);
    const [showDeletePopup, setShowDeletePopup] = useState(false);
    const [showFilters, setShowFilters] = useState(false);

    const products = [
        { id: 1, label: 'Product A', price: 29.99 },
        { id: 2, label: 'Product B', price: 49.99 },
        { id: 3, label: 'Product C', price: 19.99 }
    ];

    const handleDelete = async () => {
        // Delete product
        console.log('Deleting', selectedProduct);
        setShowDeletePopup(false);
        setSelectedProduct(null);
    };

    return (
        <Page title="Products">
            {/* Actions */}
            <Block>
                <Button onClick={() => setShowFilters(true)}>
                    Filters
                </Button>
            </Block>

            {/* List */}
            <Block title="Catalog">
                <List>
                    {products.map(product => (
                        <ListItem
                            key={product.id}
                            title={product.label}
                            subtitle={`${product.price} €`}
                            onClick={() => setSelectedProduct(product)}
                            actions={
                                <Button
                                    size="sm"
                                    variant="danger"
                                    onClick={(e) => {
                                        e.stopPropagation();
                                        setSelectedProduct(product);
                                        setShowDeletePopup(true);
                                    }}
                                >
                                    Delete
                                </Button>
                            }
                        />
                    ))}
                </List>
            </Block>

            {/* Filter Panel */}
            <Panel
                isOpen={showFilters}
                onClose={() => setShowFilters(false)}
                title="Filters"
                position="right"
            >
                <p>Filter options here</p>
            </Panel>

            {/* Confirmation Popup */}
            <Popup
                isOpen={showDeletePopup}
                onClose={() => setShowDeletePopup(false)}
                title="Confirm Deletion"
            >
                <p>
                    Delete "{selectedProduct?.label}"?
                </p>
                <div className="flex gap-2 mt-4">
                    <Button onClick={() => setShowDeletePopup(false)}>
                        Cancel
                    </Button>
                    <Button variant="danger" onClick={handleDelete}>
                        Delete
                    </Button>
                </div>
            </Popup>
        </Page>
    );
};
```

## Best Practices

1. **One Page per route component**
2. **Use Block to group** content logically
3. **Panel for secondary actions** (filters, details)
4. **Popup for confirmations** and critical actions

## Key Points to Remember

1. **Page** = main container with title and animations
2. **Block** = content section with styling
3. **Panel** = sliding side panel
4. **Popup** = centered modal for confirmations

[Back to Module](/training/module6-smartcommon-composants) | [Next Chapter: Navigation ->](/training/module6-smartcommon-composants/navigation)
