Skip to main content
View as Markdown

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 module.

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.
- 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.
- 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.
- 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.
- type: data-timeline
  dataSource: { table: phases }
  props:
    startField: starts_on
    endField: ends_on
    labelField: name
    groupBy: workstream
    defaultZoom: month

Note that data-timeline is the data-bound Gantt island; the plain timeline in Display Components is a static structural list with a rail, and takes no data source.

Last updated July 27, 2026

This documentation was written with AI, so errors or outdated content are possible. Sovrium is in beta — contributions and corrections are welcome.

Built with Sovrium