Skip to content

createAdaptiveTable ​

ts
function createAdaptiveTable<T extends Record<string, unknown>> (
  table: DataTableContext<T>,
  options: AdaptiveTableOptions<T>,
): AdaptiveTableContext<T>

The composable behind <AdaptiveTable>. Takes an existing DataTableContext — created by the consumer with createDataTable, same as any other v0 usage — and a field list. It doesn't create the table itself, so nothing from createDataTable's options or adapters is hidden or duplicated: sort, pagination, selection and grouping stay exactly as the consumer configured them.

On setup, it registers columns into table.columns derived from fields.

Options ​

ts
interface AdaptiveTableOptions<T> {
  fields: AdaptiveField<T>[]
  breakpoints?: BreakpointsContext
  mobileBreakpoint?: BreakpointName | number
  mobileMode?: 'card' | 'list'
  itemKey?: keyof T & string
}
OptionTypeDefaultDescription
fieldsAdaptiveField<T>[]—Drives both the desktop columns and the mobile layout. Required.
breakpointsBreakpointsContextcreateBreakpoints()Pass an existing context (e.g. from a v0 plugin install) instead of creating a new one per table.
mobileBreakpointBreakpointName | number'sm'Breakpoint below which the mobile layout replaces the table. Reactive — see Mobile layout.
mobileMode'card' | 'list''card'Which mobile layout to render. See Mobile layout.
itemKeykeyof T & stringarray indexProperty used as the row/card/list-item key, and to track selection and expanded state per item.

Return value ​

ts
interface AdaptiveTableContext<T> {
  table: DataTableContext<T>
  fields: Readonly<Ref<readonly AdaptiveField<T>[]>>
  desktopFields: Readonly<Ref<readonly AdaptiveField<T>[]>>
  isMobile: Readonly<Ref<boolean>>
  mobileMode: Readonly<Ref<'card' | 'list'>>
  columns: Readonly<Ref<readonly DataTableColumnTicketInput<T>[]>>
  cardSections: ComputedRef<readonly AdaptiveCardSection<T>[]>
  resolveValue: (item: T, field: AdaptiveField<T>) => unknown
  formatValue: (item: T, field: AdaptiveField<T>) => string
  itemKey: (item: T, index: number) => string | number
  ariaSort: (field: AdaptiveField<T>) => 'ascending' | 'descending' | 'none'
  isSelected: (item: T, index: number) => boolean
  isSelectable: (item: T, index: number) => boolean
  toggleSelection: (item: T, index: number, event?: { shiftKey?: boolean }) => void
  isExpanded: (item: T, index: number) => boolean
  toggleExpanded: (item: T, index: number) => void
}

cardSections groups the resolved fields by role (title, subtitle, body), already ordered — this is what both mobile renderers iterate over, the same field list that produced the desktop columns.

isExpanded/toggleExpanded back the list mobile mode's per-row expand state; they're inert (but harmless to call) when mobileMode is 'card'.

Reaching for this composable directly — instead of <AdaptiveTable> — makes sense when you need a fully custom render (a different element structure, a third layout of your own) but still want the column/mobile-role derivation and the desktop/mobile switch for free.