Field configuration
Each entry in fields describes one column and, at the same time, where it lands on the mobile layout:
interface AdaptiveField<T> {
key: keyof T & string
label: string
type?: 'text' | 'number' | 'currency' | 'date' | 'datetime' | 'boolean' | 'chip' | 'avatar' | 'password'
format?: (value: unknown, item: T) => string
sortable?: boolean
filterable?: boolean
align?: 'start' | 'center' | 'end'
width?: string | number
hideOnDesktop?: boolean
mobile?: {
role: 'title' | 'subtitle' | 'body' | 'hidden'
order?: number
showLabel?: boolean
block?: boolean
}
}type picks a sensible default formatter. Pass format when you need something custom — it always wins over the default. A field with no mobile entry defaults to body. mobile: { role: 'hidden' } keeps a field on desktop only; hideOnDesktop: true does the reverse and keeps it mobile only.
width, align, sortable and filterable are all table concerns — they only affect the desktop <th>/sort/filter wiring and are ignored on mobile.
Toggle showLabel and block below to see what they change on the status field:
Body fields render bare (no label) on a shared wrapped line by default — showLabel prefixes the value with the field's label, and block gives it its own line instead of wrapping with the others. Both apply to card and list mobile modes identically; see Mobile layout for what differs between the two.
Anything past these toggles — a gauge, a chart, a custom layout — belongs in a card-{key} slot rather than more config; see Extension points.