# Pinning Rows

The Grid provides built-in row pinning that lets you lock rows at the top or bottom of the scrollable area. Pinned rows stay visible while the user scrolls through the body data and are immune to filtering and pagination.

<CtaPanelOverview></CtaPanelOverview>

## Getting Started

To enable row pinning, set the [`pinnable`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#pinnable) prop to `true`. The Grid will manage the pinning state internally.

```jsx
<Grid pinnable={true}>
```

To allow users to pin rows, provide at least one of the following UI entry points:

* A Grid column with the **pin** [`columnType`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridcolumntype), which renders a built-in pin dropdown for every row.

  ```jsx
  <Column columnType="pin" />
  ```

* The built-in [`contextMenu`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#contextMenu), which exposes **Pin to Top**, **Pin to Bottom**, and **Unpin** actions when right-clicking a row.

  ```jsx
  <Grid pinnable={true} contextMenu={true}>
  ```

You can use either option or both together.

To pre-populate rows that are pinned on initial render, use [`defaultPinnedTopRows`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#defaultPinnedTopRows) and [`defaultPinnedBottomRows`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#defaultPinnedBottomRows).

```jsx
<Grid
    pinnable={true}
    defaultPinnedTopRows={[products[0], products[1]]}
    defaultPinnedBottomRows={[products[products.length - 1]]}
>
    <Column columnType="pin" />
    ...
</Grid>
```

The following example demonstrates row pinning in action. Click the pin icon in any row to open the dropdown and choose where to pin the row.

[Demo Source](https://demos.telerik.com/kendo-react-ui/grid/row-pinning/basic/func/source.txt)

## Controlled Mode

When you need full control over which rows are pinned, provide the [`pinnedTopRows`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#pinnedTopRows) and/or [`pinnedBottomRows`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#pinnedBottomRows) arrays and handle the [`onRowPinChange`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#onRowPinChange) event to update them. The [`GridRowPinChangeEvent`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridrowpinchangeevent) provides the updated arrays and the affected data item.

The following example demonstrates controlled row pinning using the context menu to pin rows to the top or bottom, with `pinnedTopRows` and `pinnedBottomRows` managed externally via state.

[Demo Source](https://demos.telerik.com/kendo-react-ui/grid/row-pinning/controlled/func/source.txt)

## Custom Pinned Row Rendering

You can customize how pinned rows are rendered using the [`rows.pinnedData`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#rows) setting or the [`cells.pin`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#cells) setting for the pin column cells.

```jsx
<Grid
    pinnable={true}
    rows={{ pinnedData: CustomPinnedRow }}
    cells={{ pin: { data: CustomPinCell } }}
>
```

## Suggested Links

* [Locking Rows (CSS-based)](https://www.telerik.com/kendo-react-ui-develop/components/grid/rows/row-pin)
* [API Reference of the Grid](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops)
* [API Index of the Grid](https://www.telerik.com/kendo-react-ui-develop/components/grid/api)
