Styling
Methods
There are three primary ways of applying custom styles to the components of react-bootstrap-data-grid:
Bootstrap Variable Overrides
Because react-bootstrap-data-grid makes heavy use of Bootstrap CSS classes and variables, it will also obey
customization of Bootstrap via variable overrides. For example, setting a new primary theme color with an SCSS
variable will cause buttons of the primary variant in react-bootstrap-data-grid to be the new color as well.
Additionally, setting the $table-cell-vertical-align variable can be used to adjust the vertical alignment of table
cells from the default of top.
Specific Members of Props in react-bootstrap-data-grid
A small number of options that are set via properties of component props are implemented via CSS classes or HTML style attributes.
Pagination Component
When pagination is enabled for the grid, the pageSelectorJustifyContent and componentSize
properties of the GridPaginationState interface set the component size and flexbox
justify-content settings of
the Bootstrap pagination component, respectively.
Column Widths
Column widths specified in the ColDef interface are implemented via HTML style attributes.
Table Display Mode
The displayMode property of GridProps sets the CSS
display property on the main table
element via Boostrap utility classes.
Injection of Custom Classes via the StyleModel Prop
The StyleModel prop contains a fairly extensive of list of properties that correspond to HTML elements in various
parts of react-bootstrap-data-grid. These properties either contain arrays of strings that are CSS classes or functions
that return an array of such strings.
Type Definitions
StyleModel
A prop of this type is optionally passed to the Grid component to enable injection of custom CSS classes.
| Property name | Type definition | Required/Optional | Description |
|---|---|---|---|
| mainTableStyleModel | TableStyleModel | Optional | Properties to apply custom CSS classes to elements of the main table of the Grid component |
| filterInputTableStyleModel | FilterInputTableStyleModel | Optional | Properties to apply custom CSS classes to elements of the filter inputs table |
| additionalComponentsStyleModel | AdditionalComponentsStyleModel | Optional | Properties to apply custom CSS classes for any elements not covered by the other properties in StyleModel |
| toolbarStyleModel | ToolbarStyleModel | Optional | Properties to apply CSS classes to various elements of the toolbar that allows the user to access separate interfaces like filtering options or the export feature. |
| exportFormStyleModel | ExportFormStyleModel | Optional | Properties to apply CSS classes various elements of the export form. |
TableStyleModel
Properties of this type are used to inject custom CSS classes into the main table of the Grid component.
When more than one of a certain kind of element exists, a function is used to specify different classes based on the index of the element. Certain parameters are common to many different properties:
origIndexandorigRowIndexRefers to the index of a row as it is passed into the
rowsprop of theGridcomponent.displayIndexRefers to the index of the row as it is displayed in the table, after sorting, pagination, and filtering are applied.
colIndexRefers to the index of a column as it corresponds to the
colsprop passed into theGridcomponent.
| Property name | Type definition | Required/Optional | Description |
|---|---|---|---|
| table | string[] | Optional | Specifies additional CSS classes for the main When row selection mode is enabled, the table will have the |
| tbody | string[] | Optional | Specifies additional CSS classes for the tbody element of the main table. |
| thead | string[] | Optional | Specifies additional CSS classes for the thead element of the main table. |
| theadTr | string[] | Optional | Specifies additional CSS classes for the sole tr element of the thead element of the main table. |
| theadTh | (colIndex: number) => string[] | Optional | Specifies additional CSS classes for For columns that are currently being used for sorting, the |
| caption | string[] | Optional | Specifies additional CSS classes for the |
| tbodyTr | (id: number | string, displayIndex: number) => string[] | Optional | Specifies additional CSS classes for tr elements inside the tbody element of the main table. The Grid component will automatically apply the table-active class to selected rows. |
| tbodyTd | (origRowIndex: number, displayRowIndex: number, colIndex: number) => string[] | Optional | Specifies additional CSS classes for td elements in side the tbody element of the main table. |
| editColTh | string[] | Optional | Specifies additional CSS classes for the th element of the editing controls column. |
| editColTd | (id: number | string, displayIndex: number) => string[] | Optional | Specifies additional CSS classes for the td elements of the editing controls column. |
| selectColTh | string[] | Optional | Specifies additional CSS classes for the th element of the selection controls column. |
| selectColTd | (id: number | string, displayIndex: number) => string[] | Optional | Specifies additional CSS classes for the td elements of the selection controls column. |
| selectInput | (id: number | string, displayIndex: number) => string[] | Optional | Specifies additional CSS classes for the input elements inside the td elements of the selection controls column. |
| editStartButton | (id: number | string, displayIndex: number) => string[] | Optional | Specifies the styles for all Edit buttons of the editing controls column. The Grid automatically applies the btn-primary class to these buttons, but if an array of non-zero length is supplied, the btn-primary class will not be applied, allowing for customization of the button variant. |
| editDeleteButton | (id: number | string, displayIndex: number) => string[] | Optional | Specifies the styles for all Delete buttons of the editing controls column. The Grid automatically applies the btn-secondary class to these buttons, but if an array of non-zero length is supplied, the btn-secondary class will not be applied, allowing for customization of the button variant. |
| editSaveButton | (id: number | string, displayIndex: number) => string[] | Optional | Specifies the styles for all Save buttons of the editing controls column. The Grid automatically applies the btn-primary class to these buttons, but if an array of non-zero length is supplied, the btn-primary class will not be applied, allowing for customization of the button variant. |
| editCancelButton | (id: number | string, displayIndex: number) => string[] | Optional | Specifies the styles for all Cancel buttons of the editing controls column. The Grid automatically applies the btn-secondary class to these buttons, but if an array of non-zero length is supplied, the btn-secondary class will not be applied, allowing for customization of the button variant. |
| rowSelectColTh | string[] | Optional | Specifies additional classes of the By default, the CSS classes There is also a class |
| rowSelectColTd | (id: number | string, displayIndex: number) => string[] | Optional | Specifies additional classes of the td elements in the selection controls column |
| rowSelectInput | (id: number | string, displayIndex: number) => string[] | Optional | Specifies additional classes of the input elements in the selection controls column |
FilterInputTableStyleModel
Properties of this type are used to inject custom CSS classes into the filter options table of the Grid component.
Like the TableStyleModel type, for certain kinds of elements there are more than one of that kind and function
parameters are used to specify classes differently for different elements.
indexZero-based index that refers to the row of filter options as it appears in the UI. The order in which the rows appear is the same as the order corresponding columns in the
colsprop to theGridcomponent, except that only filterable rows are included.colIndexZero-based index that refers to the columns of the filter options table. The columns are fixed regardless of the contents of options passed to the
Gridand are as follows:- Enabled - contains checkbox controls to enable or disable filtering on a column
- Column - contains the name of the column
- Type - contains a string indicating the type of the column (e.g. String or Date)
- Operator - contains a selection input to choose operator used to apply filtering
- Value - contains inputs to adjust the values to filter on
| Property name | Type definition | Required/Optional | Description |
|---|---|---|---|
| table | string[] | Optional | Specifies additional CSS classes for the table element of filter options interface. This element always has the table class to apply Bootstrap styles. |
| tbody | string[] | Optional | Specifies additional CSS classes for the tbody element of the filter options table. |
| thead | string[] | Optional | Specifies additional CSS classes for the thead element of the filter options table. |
| theadTr | string[] | Optional | Specifies additional CSS classes for the sole tr element of the thead element of the filter options table. |
| theadTh | (colIndex: number) => string[] | Optional | Specifies additional CSS classes for th elements inside the thead element of the filter options table. |
| caption | string[] | Optional | Specifies additional CSS classes for the |
| tbodyTr | (index: number) => string[] | Optional | Specifies additional CSS classes for tr elements inside the tbody element of the filter options table. |
| tbodyTd | (index: number, colIndex: number) => string[] | Optional | Specifies additional CSS classes for td elements in side the tbody element of the filter options table. |
| enablementInput | (rowIndex: number) => string[] | Optional | Specifies additional CSS classes for input checkbox elements that enable and disable filtering based on certain fields. |
| schemeSelectionInput | (rowIndex: number) => string[] | Optional | Specifies additional CSS classes for the select elements that are used to adjust the operators used for filtering for a field. |
| searchStringInput | (rowIndex: number) => string[] | Optional | Specifies additional CSS classes for the input elements used to specify string values on which to filter. This property only applies if the row is associated with a column of type string. It is up to the developer to confirm that fact. |
| numberInput | (rowIndex: number) => string[] | Optional | Specifies additional CSS classes for the input elements used to specify the number values on which to filter. This property only applies if the row is associated with a column of type number. It is up to the developer to confirm that fact. |
| startDateInput | (rowIndex: number) => string[] | Optional | Specifies additional CSS classes for the input elements used to specify the starting dates or datetimes on which to filter. This property only applies if the row is associated with a column of type date or datetime. It is up to the developer to confirm that fact. |
| endDateInput | (rowIndex: number) => string[] | Optional | Specifies additional CSS classes for the input elements used to specify the ending dates or datetimes on which to filter. This property only applies if the row is associated with a column of type date or datetime. It is up to the developer to confirm that fact. |
| submitButton | string[] | Optional | Specifies additional CSS classes for the submit button used to save changes to the filter criteria. The btn-secondary class is applied automatically, but will not be applied if an array of length at least 1 is passed for this property. |
| form | string[] | Optional | Specifies CSS classes for the Supplying the table-responsive Bootstrap utility class may be used to make the table responsive. Note that this responsive behavior only works if the |
AdditionalComponentsStyleModel
| Property name | Type definition | Required/Optional | Description |
|---|---|---|---|
| topLevelDiv | string[] | Optional | CSS classes for the top level div element that contains other divs, the following order:
|
| filterInputsDiv | string[] | Optional | CSS classes for the div that contains toggle button for the filter options table followed by the filter options table itself |
| tableAndPaginationDiv | string[] | Optional | CSS classes for the div that contains main table followed by the pagination component if pagination is enabled |
| filterUiToggleButton | string[] | Optional | CSS classes for the button that toggles the visibility of the filter options table. Only appears if filtering is enabled (by supplying the The variant of this button is set to primary by default via the |
| paginationUiDiv | string[] | Optional | CSS classes for the |
ToolbarStyleModel
| Property name | Type definition | Required/Optional | Description |
|---|---|---|---|
| activeButton | string[] | Optional | CSS classes for the button on the toolbar that is currently selected. By default contains |
| inactiveButton | string[] | Optional | CSS classes for buttons on the toolbar that are not selected. By default contains |
| toolbar | string[] | Optional | CSS classes for the |
| interfaceContainer | string[] | Optional | CSS classes for the By default, the |
ExportFormStyleModel
| Property name | Type definition | Required/Optional | Description |
|---|---|---|---|
| legend | string[] | Optional | CSS classes for the |
| radioContainer | string[] | Optional | CSS classes for the |
| radioInput | string[] | Optional | CSS classes for the |
| radioLabel | string[] | Optional | CSS classes for the |
| submitButton | string[] | Optional | CSS classes for the submit button of the export form. Contains the classes |
Examples
Colors and Alignment Example
Code
"use client";
import Grid, {
ColDef,
RowDef,
StyleModel,
TableStyleModel,
} from "@absreim/react-bootstrap-data-grid";
import { FC, useMemo } from "react";
const cols: ColDef[] = [
{
type: "string",
name: "variant",
label: "Variant",
},
{
type: "string",
name: "color",
label: "Color",
},
{
type: "string",
name: "alignment",
label: "Alignment",
},
{
type: "string",
name: "placeholderText",
label: "Placeholder Text",
},
];
type PartialRow = Record<"variant" | "alignment", string>;
const partialRows: PartialRow[] = [
{
variant: "primary",
alignment: "baseline",
},
{
variant: "secondary",
alignment: "top",
},
{
variant: "success",
alignment: "middle",
},
{
variant: "danger",
alignment: "bottom",
},
{
variant: "warning",
alignment: "text-top",
},
{
variant: "info",
alignment: "text-bottom",
},
{
variant: "light",
alignment: "baseline",
},
{
variant: "dark",
alignment: "top",
},
];
const placeholderText =
"This is placeholder text intended to take up space in order to demonstrate " +
"the effects of vertical alignment. If cell being vertically aligned is the " +
"tallest column for a row, then vertical alignment will have no effect. " +
"There should be enough text here to demonstrate the effect even at the " +
"largest breakpoint.";
const getComputedTableColors: (variants: string[]) => string[] = (variants) => {
const table: HTMLTableElement = document.createElement("table");
table.className = "table";
table.style.position = "absolute";
table.style.visibility = "hidden";
const tbody = table.createTBody();
variants.forEach((variant) => {
const tr: HTMLTableRowElement = document.createElement("tr");
tr.className = `table-${variant}`;
const td: HTMLTableCellElement = document.createElement("td");
tr.appendChild(td);
tbody.appendChild(tr);
});
document.body.appendChild(table);
const colors = Array.from(tbody.children).map((tr) => {
const td = tr.firstElementChild!;
return getComputedStyle(td).backgroundColor;
});
table.remove();
return colors;
};
interface Data {
variant: string;
color: string;
alignment: string;
placeholderText: string;
}
const getRows: (
partialRows: PartialRow[],
colors: string[],
) => RowDef<Data>[] = (partialRows, colors) =>
partialRows.map((_, index) => ({
id: partialRows[index].variant,
data: {
variant: partialRows[index].variant,
color: colors[index],
alignment: partialRows[index].alignment,
placeholderText: placeholderText,
},
}));
const variantToAlignment = new Map(
partialRows.map(({ variant, alignment }) => [variant, alignment]),
);
const tableStyleModel: TableStyleModel = {
caption: ["caption-top"],
table: ["table-bordered", "border-primary"],
tbodyTr: (id) => [`table-${id}`],
tbodyTd: (id, _, colIndex) =>
colIndex === 2 ? [`align-${variantToAlignment.get(id as string)}}`] : [],
};
const styleModel: StyleModel = {
mainTableStyleModel: tableStyleModel,
};
const caption: string =
"Table demonstrating various ways of customizing " +
"styling with classes built into Bootstrap";
const SampleStyledGrid: FC = () => {
const rows = useMemo(() => {
const variants = partialRows.map(({ variant }) => variant);
const colors = getComputedTableColors(variants);
return getRows(partialRows, colors);
}, []);
return (
<Grid rows={rows} cols={cols} styleModel={styleModel} caption={caption} />
);
};
export default SampleStyledGrid;Live Demo
Inputs and Display Order Example
Code
"use client";
import Grid, {
ColDef,
EditableTableFilterState,
EditModel,
FilterModel,
RowDef,
RowId,
StyleModel,
UpdateCallbackGenerator,
} from "@absreim/react-bootstrap-data-grid";
import { FC, MouseEventHandler, useCallback, useMemo, useState } from "react";
const cols: ColDef[] = [
{
type: "string",
name: "name",
label: "Name",
},
{
type: "number",
name: "timesAttended",
label: "Times Attended",
},
{
type: "date",
name: "recruitmentDate",
label: "Recruitment Date",
},
];
interface Data {
name: string;
timesAttended: number;
recruitmentDate: Date;
}
const initRows: RowDef<Data>[] = [
{
id: 0,
data: {
name: "Commander Shepard",
timesAttended: 100,
recruitmentDate: new Date("2183-01-01"),
},
},
{
id: 1,
data: {
name: "Kaidan Alenko",
timesAttended: 25,
recruitmentDate: new Date("2183-01-02"),
},
},
{
id: 2,
data: {
name: "Ashley Williams",
timesAttended: 20,
recruitmentDate: new Date("2183-01-10"),
},
},
{
id: 3,
data: {
name: "Garrus Vakarian",
timesAttended: 15,
recruitmentDate: new Date("2183-02-01"),
},
},
{
id: 4,
data: {
name: "Tali'Zorah nar Rayya",
timesAttended: 12,
recruitmentDate: new Date("2183-03-15"),
},
},
{
id: 5,
data: {
name: "Urdnot Wrex",
timesAttended: 10,
recruitmentDate: new Date("2183-03-20"),
},
},
{
id: 6,
data: {
name: "Liara T'soni",
timesAttended: 8,
recruitmentDate: new Date("2183-06-21"),
},
},
];
const caption = "Normandy SR-1 Insiders";
const styleModel: StyleModel = {
mainTableStyleModel: {
table: ["table-striped"],
tbodyTdInput: () => ["form-control-sm"],
editDeleteButton: () => ["btn-danger"],
editSaveButton: () => ["btn-success"],
editCancelButton: () => ["btn-warning"],
},
additionalComponentsStyleModel: {
topLevelDiv: ["vstack flex-column-reverse border"],
filterInputsDiv: [
"vstack flex-column-reverse align-items-start border m-2 p-2 gap-2",
],
tableAndPaginationDiv: ["vstack flex-column-reverse border m-2 p-2"],
filterUiToggleButton: ["btn-info"],
},
filterInputTableStyleModel: {
table: ["table-striped-columns"],
startDateInput: () => ["form-control-sm"],
endDateInput: () => ["form-control-sm"],
submitButton: ["btn-success"],
form: ["table-responsive", "w-100"]
},
};
const SampleStyledInputsGrid: FC = () => {
const [rows, setRows] = useState<RowDef[]>(initRows);
const [tableFilterState, setTableFilterState] =
useState<EditableTableFilterState>({
name: {
type: "string",
scheme: "contains",
searchString: "",
enabled: false,
},
timesAttended: {
type: "number",
scheme: "greaterOrEqual",
numValue: null,
enabled: false,
},
recruitmentDate: {
type: "date",
scheme: "between",
startDate: null,
endDate: null,
enabled: false,
},
});
const filterModel: FilterModel = useMemo(
() => ({
tableFilterState,
setTableFilterState,
}),
[tableFilterState],
);
const getUpdateCallback: UpdateCallbackGenerator = useCallback(
(id) => (rowData) => {
const newRows = rows.slice();
const index = rows.findIndex((row) => row.id === id);
if (index === undefined) {
return;
}
newRows[index] = {
id,
data: rowData,
};
setRows(newRows);
},
[rows],
);
const getDeleteCallback: (id: RowId) => () => void = useCallback(
(id) => () => {
const index = rows.findIndex((row) => row.id === id);
if (index === undefined) {
return;
}
setRows(rows.toSpliced(index, 1));
},
[rows],
);
const editModel: EditModel = { getUpdateCallback, getDeleteCallback };
const handleReset: MouseEventHandler<HTMLButtonElement> = () => {
setRows(initRows);
};
return (
<div className="vstack gap-2 align-items-start border p-2">
<Grid
rows={rows}
cols={cols}
caption={caption}
filterModel={filterModel}
editModel={editModel}
styleModel={styleModel}
responsive={true}
/>
<button className="btn btn-secondary btn-sm" onClick={handleReset}>
Reset Rows
</button>
</div>
);
};
export default SampleStyledInputsGrid;Live Demo
| Name | Times Attended | Recruitment Date | Edit Controls |
|---|---|---|---|
| Commander Shepard | 100 | 2183-01-01 | |
| Kaidan Alenko | 25 | 2183-01-02 | |
| Ashley Williams | 20 | 2183-01-10 | |
| Garrus Vakarian | 15 | 2183-02-01 | |
| Tali'Zorah nar Rayya | 12 | 2183-03-15 | |
| Urdnot Wrex | 10 | 2183-03-20 | |
| Liara T'soni | 8 | 2183-06-21 |