Grid Footer

Footer component for adding rows dynamically at the bottom of the spreadsheet

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

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

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

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:

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}
/>

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

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:

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

Layout Considerations

The footerHeight prop determines the height of the footer area:

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

Row Header Alignment

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

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

Complete Example

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.

Last updated

Was this helpful?