> For the complete documentation index, see [llms.txt](https://docs.rowsncolumns.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rowsncolumns.app/configuration/components/grid-footer.md).

# Grid Footer

The `GridFooter` component provides a customizable footer area at the bottom of the spreadsheet grid, allowing users to add additional rows dynamically.

## Overview

GridFooter displays at the bottom of the spreadsheet canvas and typically includes controls for adding new rows to the end of the sheet. It's useful for applications where users frequently add data at the bottom of their spreadsheet.

## Basic Usage

```tsx
import { SpreadsheetProvider, CanvasGrid, GridFooter } from "@rowsncolumns/spreadsheet";
import { useSpreadsheetState } from "@rowsncolumns/spreadsheet-state";

function MySpreadsheet() {
  const {
    activeSheetId,
    onRequestAddRows,
    // ... other hook values
  } = useSpreadsheetState({
    // ... configuration
  });

  return (
    <SpreadsheetProvider>
      <CanvasGrid
        sheetId={activeSheetId}
        footerHeight={80}
        footerComponent={
          <GridFooter
            sheetId={activeSheetId}
            onRequestAddRows={onRequestAddRows}
          />
        }
        // ... other props
      />
    </SpreadsheetProvider>
  );
}
```

## Props

### GridFooter Props

| Prop               | Type                                                | Description                             |
| ------------------ | --------------------------------------------------- | --------------------------------------- |
| `sheetId`          | `number`                                            | The ID of the active sheet              |
| `onRequestAddRows` | `(sheetId: number, additionalRows: number) => void` | Callback when user requests to add rows |

### CanvasGrid Props (for footer)

| Prop              | Type              | Description                         |
| ----------------- | ----------------- | ----------------------------------- |
| `footerHeight`    | `number`          | Height of the footer area in pixels |
| `footerComponent` | `React.ReactNode` | The footer component to render      |

## Features

### Add Rows Functionality

The GridFooter includes:

* An input field for specifying the number of rows to add
* An "Add" button to execute the action
* Automatic scrolling to the bottom after adding rows

```tsx
const { onRequestAddRows } = useSpreadsheetState({
  sheets,
  sheetData,
  onChangeSheets: setSheets,
  onChangeSheetData: setSheetData,
});

// GridFooter will call this when user clicks "Add"
// It automatically scrolls to the bottom after adding rows
<GridFooter
  sheetId={activeSheetId}
  onRequestAddRows={(sheetId, numRows) => {
    console.log(`Adding ${numRows} rows to sheet ${sheetId}`);
    onRequestAddRows?.(sheetId, numRows);
  }}
/>
```

### Implementing onRequestAddRows

The `onRequestAddRows` callback is typically provided by `useSpreadsheetState`, but you can also implement custom logic:

```tsx
import { useState } from "react";
import type { Sheet } from "@rowsncolumns/spreadsheet";

const [sheets, setSheets] = useState<Sheet[]>([
  { sheetId: 1, rowCount: 100, columnCount: 26, title: "Sheet 1" }
]);

const handleAddRows = (sheetId: number, additionalRows: number) => {
  setSheets(prev => prev.map(sheet => {
    if (sheet.sheetId === sheetId) {
      return {
        ...sheet,
        rowCount: sheet.rowCount + additionalRows,
      };
    }
    return sheet;
  }));
};

<GridFooter
  sheetId={activeSheetId}
  onRequestAddRows={handleAddRows}
/>
```

## Custom Footer Component

You can create your own custom footer component instead of using the default GridFooter:

```tsx
const CustomFooter = ({ sheetId }: { sheetId: number }) => {
  return (
    <div className="flex items-center justify-between p-4 bg-gray-100">
      <span>Sheet {sheetId}</span>
      <button onClick={() => console.log("Custom action")}>
        Custom Action
      </button>
    </div>
  );
};

<CanvasGrid
  footerHeight={60}
  footerComponent={<CustomFooter sheetId={activeSheetId} />}
/>
```

## Styling

The GridFooter component uses Tailwind CSS classes and can be customized through className props:

```tsx
// The default GridFooter styling includes:
// - Responsive padding
// - Border styling
// - Background color from theme
// - Proper alignment with row headers
```

## Layout Considerations

### Footer Height

The `footerHeight` prop determines the height of the footer area:

```tsx
<CanvasGrid
  footerHeight={80}  // 80 pixels for footer
  footerComponent={<GridFooter {...props} />}
/>
```

### Row Header Alignment

GridFooter automatically aligns with the row header column, ensuring consistent layout:

```tsx
// Internal padding matches ROW_HEADER_WIDTH constant
// Scrollbar space is automatically accounted for
```

## Complete Example

```tsx
import React, { useState } from "react";
import {
  SpreadsheetProvider,
  CanvasGrid,
  GridFooter,
  type Sheet,
} from "@rowsncolumns/spreadsheet";
import {
  useSpreadsheetState,
  type SheetData,
} from "@rowsncolumns/spreadsheet-state";

function SpreadsheetWithFooter() {
  const [sheets, setSheets] = useState<Sheet[]>([
    { sheetId: 1, rowCount: 100, columnCount: 26, title: "Sheet 1" }
  ]);
  const [sheetData, setSheetData] = useState<SheetData>({});

  const {
    activeCell,
    activeSheetId,
    selections,
    getCellData,
    onChangeActiveCell,
    onChangeSelections,
    onRequestAddRows,
    // ... other state values
  } = useSpreadsheetState({
    sheets,
    sheetData,
    onChangeSheets: setSheets,
    onChangeSheetData: setSheetData,
  });

  return (
    <SpreadsheetProvider>
      <CanvasGrid
        sheetId={activeSheetId}
        activeCell={activeCell}
        selections={selections}
        getCellData={getCellData}
        onChangeActiveCell={onChangeActiveCell}
        onChangeSelections={onChangeSelections}
        footerHeight={80}
        footerComponent={
          <GridFooter
            sheetId={activeSheetId}
            onRequestAddRows={onRequestAddRows}
          />
        }
      />
    </SpreadsheetProvider>
  );
}
```

## Best Practices

1. **Set appropriate footer height**: The default 80px works well for most cases, but adjust based on your content
2. **Validate row additions**: Consider limits on total row count to prevent performance issues
3. **Provide feedback**: Show loading states or success messages when adding rows
4. **Handle errors gracefully**: Validate the number input and handle edge cases

## Use Cases

* **Data entry applications**: Allow users to easily add more rows as they input data
* **Dynamic spreadsheets**: Support growing datasets without manual sheet configuration
* **Form-like interfaces**: Provide a way to add new records at the bottom of a list
* **Log viewers**: Allow users to append new log entries

## Performance

GridFooter is lightweight and doesn't impact spreadsheet performance. The component only re-renders when its props change, and adding rows is handled efficiently by the spreadsheet state management.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.rowsncolumns.app/configuration/components/grid-footer.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
