
# Boards, Calendars & Timelines

Four components take the same records a table would show and arrange them by something other than row order — by card, by column, by date, by span. All four bind through the shared [`dataSource`](/en/docs/pages-data-binding) module.

## `gallery`

A responsive card grid.

| Property       | Description                                                              |
| -------------- | ------------------------------------------------------------------------ |
| `dataSource`   | Table binding.                                                           |
| `gridColumns`  | Column count per breakpoint — `{ mobile, sm, md, lg, xl }`, each 1 to 6. |
| `galleryCard`  | Card configuration (see below).                                          |
| `layout`       | `grid` (uniform rows) or `masonry` (variable heights).                   |
| `emptyMessage` | Shown when nothing matches.                                              |

| `galleryCard` property | Description                                       |
| ---------------------- | ------------------------------------------------- |
| `coverImage`           | Cover image URL, usually a `$record.*` reference. |
| `aspectRatio`          | Cover ratio, e.g. `4:3`, `16:9`, `1:1`.           |
| `children`             | Components rendered in the card body.             |
| `hoverOverlay`         | `{ children }` rendered over the card on hover.   |
| `onClick`              | Action invoked when the card is clicked.          |

```yaml
- type: gallery
  dataSource: { table: products }
  gridColumns: { mobile: 1, md: 2, lg: 3 }
  layout: masonry
  galleryCard:
    coverImage: '$record.photo'
    aspectRatio: '4:3'
    children:
      - { type: text, tag: h3, content: '$record.name' }
```

## `kanban`

A board grouping records into columns by a field value, with drag-and-drop between them.

| Property             | Description                                                                 |
| -------------------- | --------------------------------------------------------------------------- |
| `dataSource`         | Table binding.                                                              |
| `kanbanGroupBy`      | `{ field }` — the field whose values become the columns.                    |
| `card`               | Card configuration (see below).                                             |
| `drag`               | `{ enabled, persistAction }` — whether cards move, and what saves the move. |
| `colorField`         | Field driving column accent color.                                          |
| `emptyColumnMessage` | Shown in a column with no cards.                                            |

| `card` property | Description                                                                                                              |
| --------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `children`      | Components rendered in the card body.                                                                                    |
| `coverImage`    | Card cover image URL.                                                                                                    |
| `colorField`    | Field whose value sets the card's color.                                                                                 |
| `footer`        | `{ field, format }` entries in the card footer. `format` is `relative-date`, `short-date`, `avatar`, `badge`, or `text`. |
| `onClick`       | Action invoked when the card is clicked.                                                                                 |

```yaml
- type: kanban
  dataSource: { table: tasks }
  kanbanGroupBy: { field: status }
  drag: { enabled: true }
  card:
    children: [{ type: text, content: '$record.title' }]
    footer: [{ field: assignee, format: avatar }, { field: due_date, format: short-date }]
```

## `calendar`

A month, week or day calendar of date-bearing records. The field mappings sit at the top level — only click handling lives under `calendarEvent` and `calendarInteraction`.

| Property                                       | Description                                                  |
| ---------------------------------------------- | ------------------------------------------------------------ |
| `dataSource`                                   | Table binding.                                               |
| `dateField`                                    | Field supplying each event's start.                          |
| `endDateField`                                 | Field supplying its end, for events that span time.          |
| `labelField`                                   | Field rendered as the event's label.                         |
| `colorField`                                   | Field whose value sets the event color.                      |
| `defaultView`                                  | `month`, `week`, or `day`.                                   |
| `maxEventsPerDay`                              | Cap before a day cell collapses into a "+N more" affordance. |
| `calendarEvent.onEventClick`                   | Action invoked when an event is clicked.                     |
| `calendarInteraction.onDateClick`              | Action invoked when an empty date or slot is clicked.        |
| `calendarInteraction.timeSlotInterval`         | Slot length in minutes for week and day views.               |
| `calendarInteraction.showCurrentTimeIndicator` | Draw a line at the current time.                             |

```yaml
- type: calendar
  dataSource: { table: bookings }
  dateField: starts_at
  endDateField: ends_at
  labelField: customer_name
  defaultView: week
  calendarInteraction: { timeSlotInterval: 30, showCurrentTimeIndicator: true }
```

## `data-timeline`

A Gantt-style view of records that occupy a span rather than an instant. Its schema is deliberately minimal — `dataSource` plus `props` — and the field mappings are read from `props`:

| `props` key   | Description                                                    |
| ------------- | -------------------------------------------------------------- |
| `startField`  | **Required at render time.** Field supplying each bar's start. |
| `endField`    | Field supplying its end.                                       |
| `labelField`  | Field rendered as the bar's label.                             |
| `groupBy`     | Field whose values become the timeline's rows.                 |
| `colorField`  | Field whose value sets the bar color.                          |
| `defaultZoom` | `day`, `week`, `month`, `quarter`, or `year`.                  |

```yaml
- type: data-timeline
  dataSource: { table: phases }
  props:
    startField: starts_on
    endField: ends_on
    labelField: name
    groupBy: workstream
    defaultZoom: month
```

:::callout
**These `props` keys are not schema-validated.** A misspelled `startFeild` passes validation and the component renders its error state instead of a timeline. Check the spelling here more carefully than elsewhere.
:::

Note that `data-timeline` is the data-bound Gantt island; the plain `timeline` in [Display Components](/en/docs/display-components) is a static structural list with a rail, and takes no data source.

## Related Pages

- [Tables & Lists](/en/docs/data-components) — `data-table`, `list`, `data-form`.
- [Charts & KPIs](/en/docs/data-components-charts) — aggregated visualizations.
- [Data Binding](/en/docs/pages-data-binding) — `dataSource`, filters, pagination.
- [Interactions & Auto-Save](/en/docs/interactions) — the actions these components invoke.
- [Display Components](/en/docs/display-components) — the non-data `timeline`.
