# GridFolders

**Category:** Base Components/Collections/GridFolders/GridFolders

## Design

### Description

The `GridFolders` component presents folders and their respective content in a visually organized grid view, where each part is neatly divided into its own dedicated section. The [`useGridFolders()`](./?path=/story/base-components-collections-gridfolders-usegridfolders--usegridfolders) hook manages the state and behavior of the grid component based on the provided collections.


```tsx
import { GridFolders, useGridFolders } from '@wix/patterns';
```

### Demo

```tsx
import React from 'react';
import { queryContacts } from '@wix/ambassador-contacts-v4-contact/http';
import { Contact } from '@wix/ambassador-contacts-v4-contact/types';
import {
  OffsetQuery,
  useCollection,
  GridFolders,
  PageWrapper,
  useGridFolders,
} from '@wix/patterns';
import { useHttpClient } from '@wix/yoshi-flow-bm';
import { Page } from '@wix/design-system';

function Basic() {
  const httpClient = useHttpClient();

  const collection = useCollection<Contact>({
    queryName: 'griditems',
    itemKey: (item) => item.id as string,
    itemName: (item) => item.name as string,
    fetchData: (query: OffsetQuery) => {
      const { limit, offset, search, filters } = query;
      return httpClient
        .request(
          queryContacts({
            query: { paging: { limit, offset }, filter: filters },
            search,
          }),
        )
        .then((res) => {
          const {
            data: { contacts = [], pagingMetadata },
          } = res;
          return {
            items: contacts,
            total: pagingMetadata?.total,
          };
        });
    },
    fetchErrorMessage: ({ err }) => String(err),
  });

  const foldersCollection = useCollection<Contact>({
    queryName: 'gridfolders',
    paginationMode: 'offset',
    itemName: (item) => item.name as string,
    fetchData: (query: OffsetQuery) => {
      const { limit, offset, search, filters } = query;
      return httpClient
        .request(
          queryContacts({
            query: { paging: { limit: 20, offset }, filter: filters },
            search,
          }),
        )
        .then((res) => {
          const {
            data: { contacts = [], pagingMetadata },
          } = res;
          return {
            items: contacts,
            total: 20,
          };
        });
    },
    fetchErrorMessage: ({ err }) => String(err),
  });

  const componentState = useGridFolders({
    items: collection,
    folders: foldersCollection,
  });

  return (
    <PageWrapper>
      <Page height="400px">
        <Page.Header title="Folders and items" />

        <Page.Content>
          <GridFolders
            state={componentState}
            preset="title"
            folderPreset="title"
          />
        </Page.Content>
      </Page>
    </PageWrapper>
  );
}
```

---

### Variations

### Grid Folders

Displaying folders and their contents in a grid view.

```tsx
import React from 'react';
import { queryContacts } from '@wix/ambassador-contacts-v4-contact/http';
import { Contact } from '@wix/ambassador-contacts-v4-contact/types';
import {
  OffsetQuery,
  useCollection,
  GridFolders,
  PageWrapper,
  useGridFolders,
} from '@wix/patterns';
import { useHttpClient } from '@wix/yoshi-flow-bm';
import { Page } from '@wix/design-system';

function Basic() {
  const httpClient = useHttpClient();

  const collection = useCollection<Contact>({
    queryName: 'griditems_example',
    itemKey: (item) => item.id as string,
    itemName: (item) => item.name as string,
    fetchData: (query: OffsetQuery) => {
      const { limit, offset, search, filters } = query;
      return httpClient
        .request(
          queryContacts({
            query: { paging: { limit, offset }, filter: filters },
            search,
          }),
        )
        .then((res) => {
          const {
            data: { contacts = [], pagingMetadata },
          } = res;
          return {
            items: contacts,
            total: pagingMetadata?.total,
          };
        });
    },
    fetchErrorMessage: ({ err }) => String(err),
  });

  const foldersCollection = useCollection<Contact>({
    queryName: 'gridfolders_example',
    paginationMode: 'offset',
    itemName: (item) => item.name as string,
    fetchData: (query: OffsetQuery) => {
      const { limit, offset, search, filters } = query;
      return httpClient
        .request(
          queryContacts({
            query: { paging: { limit, offset }, filter: filters },
            search,
          }),
        )
        .then((res) => {
          const {
            data: { contacts = [], pagingMetadata },
          } = res;
          return {
            items: contacts,
            total: pagingMetadata?.total,
          };
        });
    },
    fetchErrorMessage: ({ err }) => String(err),
  });

  const componentState = useGridFolders({
    items: collection,
    folders: foldersCollection,
  });

  return (
    <PageWrapper>
      <Page height="400px">
        <Page.Header title="Folders and items" />

        <Page.Content>
          <GridFolders
            state={componentState}
            preset="title"
            folderPreset="title"
          />
        </Page.Content>
      </Page>
    </PageWrapper>
  );
}
```

## API

### Props

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `state` | `GridFoldersState<T1, F1, T2, F2>` | Yes | - | A GridFoldersState instance created using [useGridFolders](./?path=/story/base-components-collections-gridfolders-usegridfolders--usegridfolders). |
| `itemsSectionTitle` | `string` | No | - | Optional custom title for the items section |
| `renderFolderItem` | `((item: T2, index: number) => Partial<SupportedCardGalleryItemProps>)` | No | - | Same as `renderItem`, but for a folder item. |
| `folderPreset` | `"title" \| "full"` | No | - | Same as `preset` but for a folder item |
| `folderActionCell` | `ActionCell<T2, F2>` | No | - | Same as `actionCell`, but for a folder item. |
| `renderFolderAddItem` | `(() => ReactElement<AddItemProps, string \| JSXElementConstructor<any>>)` | No | - | Same as `renderAddItem`, but for a folder item. |
| `search` | `boolean \| FilterElement<any> \| CollectionSearchElement` | No | `true` | Displays a search input on the right side of the table toolbar.<br> <br> Accepts a boolean or a custom React element as a parameter. When passing `false`, no search input is displayed. |
| `title` | `ToolbarTitleElement` | No | - | Displays a title at the left of a toolbar. Accepts a [ToolbarTitle](./?path=/story/features-display-toolbar--toolbartitle) component. |
| `tags` | `TagsElement<T1, Partial<F1 & F2>>` | No | - | Enables tags feature. In this element you can pass the configuration |
| `errorState` | `((err: unknown, params: { isOnline: boolean; retry: () => void; }) => ReactElement<any, string \| JSXElementConstructor<any>>)` | No | - | A render function to be rendered when there's an error fetching data from the server.<br> The function accepts the following parameters <br> * `err`: The error thrown by the [fetchData](./?path=/story/common-hooks--usecollection) function <br> * `isOnline`: Indicates whether internet connection is available <br> * `retry`: Retry collection fetch on failed response, similar to `collection.retryFetch` <br> Returns [`EmptyState`](https://www.docs.wixdesignsystem.com/?path=/story/components-layout--emptystate) component. |
| `maxSelection` | `number` | No | - | Limits the amount of rows a visitor can select. |
| `views` | `CollectionViewsDropdownElement<Partial<F1 & F2>>` | No | - | Adds view options to the table headers. Accepts a [Views](./?path=/story/features-display-views--views) component. |
| `filters` | `CollectionToolbarFiltersElement` | No | - | Adds filters to the toolbar and/or a sliding panel. Accepts a `ToolbarFilters` component, which must have the `panelTitle` prop defined. |
| `tabs` | `TabsFilterElement<TabsFilterProps<T1>>` | No | - | Displays tabs at the left of a toolbar. Accepts a [TabsFilter](./?path=/story/features-filter-components--tabsfilter) component. |
| `minCardHeight` | `MinHeight<string \| number>` | No | `300px` | Minimum height for a card's container when showing:<br> - A loader<br> - Empty state<br> - Error state <br><br> If no unit is specified, `px` is used. |
| `renderError` | `((params: { err: unknown; isOnline: boolean; retry: () => void; }) => ReactElement<any, string \| JSXElementConstructor<any>>)` | No | - | A render function to be rendered when there's an error fetching data from the server.<br> The function accepts the following parameters <br> * `err`: The error thrown by the [fetchData](./?path=/story/common-hooks--usecollection) function <br> * `isOnline`: Indicates whether internet connection is available <br> * `retry`: Retry collection fetch on failed response, similar to `collection.retryFetch` <br> Returns [`EmptyState`](https://www.docs.wixdesignsystem.com/?path=/story/components-layout--emptystate) component. @deprecated Use `errorState` instead. |
| `emptyState` | `ReactNode` | No | - | Renders when there are no items to display. Accepts a [`CollectionEmptyState`](./?path=/story/features-display-empty-states--collectionemptystate) component. |
| `noResultsState` | `ReactNode \| ((params: { hasAvailableItems: boolean; query: ComputedQuery<Partial<F1 & F2>>; }) => ReactNode)` | No | - | Shown when a search or filter has no results. Accepts a [`CollectionNoResultsState`](./?path=/story/features-display-empty-states--collectionnoresultsstate) component, or a function that accepts the following parameters: - `hasAvailableItems`: Indicates whether other items may be shown using other filter or search parameters. - `query`: An instance of [`ComputedQuery`](./?path=/story/common-models--computedquery) representing the query that resulted in the empty state. The function should return [`CollectionNoResultsState`](./?path=/story/features-display-empty-states--collectionnoresultsstate). |
| `summaryBar` | `ReactNode` | No | - | Display a summary bar below the toolbar. Accepts a [`SummaryBar`](./?path=/story/features-display-toolbar--summarybar) component. |
| `dragAndDropSubmit` | `DragAndDropSubmit<T1, Partial<F1 & F2>>` | No | - | Function that submits a drop event to the server. <br> <br> The parameter is an event object containing the following details: <br> -`from: {item: T; index: number}`: The dragged item. <br> -`after: null \| [item: T; iindex: number}`: The previous dropped item. If this is the first item to be dropped, this argument is `null`. <br> -`filters`: Applied [Drag and Drop](./?path=/story/features-sort-drag-and-drop--overview) filters. @returns Promise |
| `dragAndDropBulkSubmit` | `DragAndDropBulkSubmit<T1, Partial<F1 & F2>>` | No | - | Function that submits an array of drop events to the server. <br> <br> The parameter is an array of event objects containing the following details: <br> -`from: {item: T; index: number}`: The dragged item. <br> -`after: null \| [item: T; index: number}`: The previous dropped item. If this is the first item to be dropped, this argument is `null`. <br> -`filters`: Applied [Drag and Drop](./?path=/story/features-sort-drag-and-drop--overview) filters. <br> @returns Promise |
| `dragAndDropCancel` | `DragAndDropCancel<T1, Partial<F1 & F2>>` | No | - | A function that cancels a drop event. <br> Supported arguments: <br> - `from: {item: T; index: number}`: The dragged item. - `after: null \| {item: T; index: number}`: The item that the dragged item was dropped after. If dropped at the head of the collection, this argument will be `null`. - `filters`: Currently applied filters. Used in cases where your server holds a unique ordering per filtering. See the `dragAndDropCategories` prop. If the move is cancelled, the function returns a toast config object with a message. Otherwise, the function will return a null value. |
| `extensionMenuItems` | `ExtensionMenuItemsType` | No | - | @deprecated It doesn't need to be passed implicitly anymore. |
| `dragAndDropReorderModeToolbar` | `ReorderModeToolbarElement \| null` | No | - | Drag and drop reorder mode toolbar. This prop accepts a `ReorderModeToolbar` component.<br> The `ReorderModeToolbar` component accepts the following props:<br> + `learnMoreUrl`: [string] A URL in the toolbar.<br> + `reorderModeTitle`: [string] A title in the toolbar. |
| `customColumns` | `CustomColumnsElement \| null` | No | - | Adds functionality to allow visitors to create choose which columns to display and in what order. Accepts a [CustomColumns](./?path=/story/features-display--customcolumns) component. |
| `multiLevelSorting` | `MultiLevelSortingElement` | No | - | Adds functionality to allow visitors to sort multiple columns simultaneously. Accepts a [MultiLevelSorting](./?path=/story/features-sort-sortable-columns-multilevelsorting--multilevelsorting) component. |
| `primaryActionButton` | `PrimaryActionButtonElement` | No | - | Adds functionality for a primary action button in the toolbar. Accepts a [PrimaryActionButton](./?path=/story/features-actions-primary-actions--primary-action-button) component. |
| `secondaryActions` | `ToolbarSecondaryActionsElement` | No | - | Secondary buttons w/o PopoverMenu component to be rendered on the toolbar. |
| `moreActions` | `MoreActionsElement` | No | - | A [`MoreActions`](./?path=/story/features-actions-more-actions--more-actions) component to be rendered on the header. |
| `AddApplyFiltersButton` | `AddApplyFiltersButtonType` | No | - | Apply filter button implementation: `import { AddApplyFiltersButton } from '@wix/patterns';` <br> Add `Apply` button to the filters panel footer. Panel filters will be applied only after the button is clicked. |
| `internalScroll` | `boolean` | No | - | Indicates whether the table should have an [internal scroll](./?path=/story/features-display-internal-scroll--internal-scroll) instead of the default page scroll. |
| `showFieldTypeIcons` | `boolean` | No | `false` | When true, renders prefix icons for field types in column headers, filters, and the customize-columns panel. Each column and filter should have a `fieldType` property set so Cairo can render the matching icon. |
| `showTitleBar` | `boolean` | No | `true` | Indicates whether to show Table Title Bar or not. Note: if you pass `showTitleBar = false` title bar is not removed from the DOM. For better accessibility column titles should be defined as well. |
| `exportButton` | `ReactElement<any, string \| JSXElementConstructor<any>>` | No | - | A [`<ExportButton />`](./?path=/story/features-export--exportto) react element to be added to the toolbar |
| `importButton` | `ReactElement<any, string \| JSXElementConstructor<any>>` | No | - | A [`<ImportButton />`] react element to be added to the toolbar. |
| `exportModal` | `ReactElement<any, string \| JSXElementConstructor<any>>` | No | - | A [`<ExportModal />`](./?path=/story/features-export--exportto#CTA_is_out_of_the_table) react element to be rendered in table's context. |
| `importModal` | `ReactElement<any, string \| JSXElementConstructor<any>>` | No | - | A [`<ImportModal />`] react element to be rendered in table's context. |
| `dragAndDropCategories` | `(keyof F1 \| keyof F2)[][] \| null` | No | - | By default, drag and drop works only without filters. To enable drag and drop with filters, pass an array of filters to this prop. The functionality will then work only for the specified filters, and to enable without filters, you must pass an empty array. For more information, see the [Drag and Drop Overview](//?path=/story/features-sort-drag-and-drop--overview). |
| `preset` | `"title" \| "full" \| "footer" \| "empty"` | No | `title` | A `CardGalleryItem` preset to preserve the same card size regardless of the provided data. Subtitle will be shown only in 'full' or 'footer' presets. @example full — renders title + subtitle title — renders only title empty — renders a card without a footer |
| `renderItem` | `((item: T1, index: number) => Partial<SupportedCardGalleryItemProps>)` | No | - | A function that renders a custom item of the grid. Returns a WSR [`CardGalleryItemProps`](https://www.docs.wixdesignsystem.com/?path=/story/components-lists--cardgalleryitem) object. |
| `actionCell` | `ActionCell<T1, F1>` | No | - | Adds an action on the grid item. For example, a delete button to delete an item. Accepts an [`ActionCellProps`](https://www.docs.wixdesignsystem.com/?path=/story/components-lists-table--tableactioncell) object, or a function that returns an `ActionCellProps` object. |
| `renderAddItem` | `(() => ReactElement<AddItemProps, string \| JSXElementConstructor<any>>)` | No | - | A function that renders [`<AddItem>`](https://www.docs.wixdesignsystem.com/?path=/story/components-actions--additem&activeTab=Description&globals=backgrounds.value:!hex(F8F8F8);backgrounds.grid:false) after all cards in a gallery. <br><br> The `<AddItem>` card will not show when filters are applied unless the filter is defined with the persistent option. |
| `imagePlacement` | `"top" \| "side"` | No | - | Sets placement of a background image. |

