Styling
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 should also obey customization of Bootstrap via variable overrides. For example, setting a new
primarytheme color with an SCSS variable will cause buttons of theprimaryvariant in React Bootstrap Data Grid to be the new color as well. Additionally, setting the$table-cell-vertical-alignvariable can be used to adjust the vertical alignment of table cells from the default oftop. - 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. Currently, the only properties of this type are the
pageSelectorJustifyContentandcomponentSizeproperties of theGridPaginationStateinterface. These properties set the component size and flexbox justify content settings of the Bootstrap pagination component, respectively. - Injection of Custom Classes via the StyleModel Prop
- The
StyleModelprop 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 |
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:
origIndexandorigRowIndex- Refers to the index of a row as it is passed into the
rowsprop of theGridcomponent. displayIndex- Refers to the index of the row as it is displayed in the table, after sorting, pagination, and filtering are applied.
colIndex- Refers 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 table element. This element always has the table class to apply Bootstrap styles. In addition, when row selection mode is enabled, the table will have the table-hover class to indicate that the rows are selectable by clicking on them. |
| 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 th elements inside the thead element of the main table. For columns are currently being used for sorting, the Grid will automatically apply the table-active class. In addition, if a column is available as an option for sorting, the Grid will use a CSS class (specific to this project) to set the cursor to be a pointer. |
| caption | string[] | Optional | Specifies additional CSS classes for the caption element of the main table. |
| tbodyTr | (origIndex: number, 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 | (origIndex: number, 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 | (origIndex: number, displayIndex: number) => string[] | Optional | Specifies additional CSS classes for the td elements of the selection controls column. |
| selectInput | (origIndex: number, displayIndex: number) => string[] | Optional | Specifies additional CSS classes for the input elements inside the td elements of the selection controls column. |
| editStartButton | (origIndex: number, 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 a array of non-zero length is supplied, the btn-primary class will not be applied, allowing for customization of the button variant. |
| editDeleteButton | (origIndex: number, 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 a array of non-zero length is supplied, the btn-secondary class will not be applied, allowing for customization of the button variant. |
| editSaveButton | (origIndex: number, 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 a array of non-zero length is supplied, the btn-primary class will not be applied, allowing for customization of the button variant. |
| editCancelButton | (origIndex: number, 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 a 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 th element that contains the control for selecting and deselecting all rows. The cell only appears if selection for the By default, the CSS classes There is also a class |
| rowSelectColTd | (origIndex: number, displayIndex: number) => string[] | Optional | Specifies additional classes of the td elements in the selection controls column |
| rowSelectInput | (origIndex: number, 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.
index- Zero-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. colIndex- Zero-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 caption element of the filter options table. |
| 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 property. |
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 |
Examples
Colors and Alignment Example
Code
"use client";
import Grid, { ColDef, RowDef, StyleModel, TableStyleModel } from "@/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;
};
const getRows: (partialRows: PartialRow[], colors: string[]) => RowDef[] = (
partialRows,
colors,
) =>
partialRows.map((_, index) => ({
variant: partialRows[index].variant,
color: colors[index],
alignment: partialRows[index].alignment,
placeholderText: placeholderText,
}));
const tableStyleModel: TableStyleModel = {
caption: ["caption-top"],
table: ["table-bordered", "border-primary"],
tbodyTr: (origIndex) => [`table-${partialRows[origIndex].variant}`],
tbodyTd: (origRowIndex, _, colIndex) =>
colIndex === 2 ? [`align-${partialRows[origRowIndex].alignment}`] : [],
};
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
import Grid, {
ColDef,
EditableTableFilterState,
EditModel,
FilterModel,
RowDef,
StyleModel,
UpdateCallbackGenerator,
} from "@/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",
},
];
const initRows: RowDef[] = [
{
name: "Commander Shepard",
timesAttended: 100,
recruitmentDate: new Date("2183-01-01"),
},
{
name: "Kaidan Alenko",
timesAttended: 25,
recruitmentDate: new Date("2183-01-02"),
},
{
name: "Ashley Williams",
timesAttended: 20,
recruitmentDate: new Date("2183-01-10"),
},
{
name: "Garrus Vakarian",
timesAttended: 15,
recruitmentDate: new Date("2183-02-01"),
},
{
name: "Tali'Zorah nar Rayya",
timesAttended: 12,
recruitmentDate: new Date("2183-03-15"),
},
{
name: "Urdnot Wrex",
timesAttended: 10,
recruitmentDate: new Date("2183-03-20"),
},
{
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"],
},
};
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(
(origIndex) => (rowDef) => {
setRows((rows) => {
const newRows = rows.slice();
newRows[origIndex] = rowDef;
return newRows;
});
},
[],
);
const getDeleteCallback: (origIndex: number) => () => void = useCallback(
(origIndex) => () => {
setRows((rows) => rows.toSpliced(origIndex, 1));
},
[],
);
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}
/>
<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 | Wed Jan 01 2183 | |
| Kaidan Alenko | 25 | Thu Jan 02 2183 | |
| Ashley Williams | 20 | Fri Jan 10 2183 | |
| Garrus Vakarian | 15 | Sat Feb 01 2183 | |
| Tali'Zorah nar Rayya | 12 | Sat Mar 15 2183 | |
| Urdnot Wrex | 10 | Thu Mar 20 2183 | |
| Liara T'soni | 8 | Sat Jun 21 2183 |