Theming
Follow the host app's theme (automatic)
Every color the grid draws falls back to Theme.of(context).colorScheme
when you leave the style config field null. So a grid inside another app's
MaterialApp follows that app's ThemeData — including dark mode — with
zero configuration.
MaterialApp(
theme: myAppTheme, // <-- the grid follows THIS
darkTheme: ThemeData.dark(),
home: BCellGrid(columns: cols, rows: rows),
)
Theme fallbacks:
| Grid part | ColorScheme role |
|---|---|
| header background | surfaceContainerHighest |
| row background | surface |
| selection | primaryContainer |
| grid border | outline |
| cell border | outlineVariant |
| header text | textTheme.titleSmall |
| cell text | textTheme.bodyMedium |
| sort icon | ambient IconTheme |
| fill handle (drag square) | activatedColor |
| fill handle outline | surface |
Override specific colors
Pass a BCellGridStyleConfig only for the parts you want to pin; the rest
still follow the theme.
BCellGrid(
columns: cols,
rows: rows,
configuration: BCellGridConfiguration(
style: BCellGridStyleConfig(
rowHeight: 44,
columnHeight: 48,
activatedColor: Colors.teal.shade100, // selection
oddRowColor: Theme.of(context).colorScheme // zebra striping (null = off)
.primary.withValues(alpha: 0.06),
// columnTextStyle / cellTextStyle: copyWith the theme style so text
// color + family keep following the theme.
columnTextStyle: Theme.of(context).textTheme.titleSmall
?.copyWith(fontWeight: FontWeight.bold),
// Metrics & small parts (defaults shown):
defaultColumnTitlePadding: EdgeInsets.symmetric(horizontal: 8),
defaultCellPadding: EdgeInsets.symmetric(horizontal: 8),
iconSize: 14, // header sort icon
iconColor: null, // null = inherit IconTheme
fillHandleSize: 8, // drag-fill square on the focused cell
fillHandleColor: null, // null = activatedColor
fillHandleBorderColor: null, // null = colorScheme.surface
),
),
)
Rows are fixed-extent: vertical defaultCellPadding must fit within
rowHeight, or it squeezes the cell content instead of growing the row.
Per-column / per-cell color
Color one column's cells by value with cellStyle (lighter than a full
renderer — use it when you only need color):
BCellColumn(
title: 'Amount', field: 'amount', type: BCellColumnType.number(),
cellStyle: (ctx) {
final v = ctx.cell.value as num? ?? 0;
if (v < 0) return const BCellStyle(textStyle: TextStyle(color: Colors.red));
return const BCellStyle(backgroundColor: Color(0xFFE8F5E9));
},
)
BCellStyle carries backgroundColor and/or textStyle. Return null for
the default look. To use theme colors here, read
Theme.of(context).colorScheme.* and pass them in.
For a full custom cell widget (icons, links, rich text), use renderer
instead — see Cell renderers.
Data-driven color (conditional formatting)
Color-scale / data-bar / icon-set over a numeric column:
BCellColumn(
title: 'Score', field: 'score', type: BCellColumnType.number(),
renderer: BCellConditionalFormat.colorScale(stateManager, useMid: true).toRenderer(),
// also: .dataBar(stateManager).toRenderer(), .iconSet(stateManager).toRenderer()
)
Broadcast a font to many grids
BCellFontScope pushes one font to every BCell widget below it (grid +
pager + tab bar) through a single controller:
final font = BCellFontController();
BCellFontScope(
controller: font,
child: Column(children: [
Expanded(child: BCellGrid(columns: cols, rows: rows)),
BCellPagination(stateManager),
]),
);
font.setFont(const TextStyle(fontFamily: 'serif')); // null = theme default