Columns
Column Grouping
Column Grouping allows you to specify hierarchical relationships among columns.
The groupId
property specifies the column group a particular column belongs
to.
When specifying column groups, a tree structure is defined for the grouping, and
the groupId
specifies the path of the column within that tree. Graphite Grid
maintains a flat representation of columns, with each individual column
declaratively describing which column group it is a part of.
Individual columns are part of the same group when they have the same value for
the groupId
property, even if the columns are not contiguous in the
definitions. This means they will share the same collapse state across the grid.
In the example below, notice that collapsing any of the "Greeks"
grouping
collapses both groups.
export function ColumnGroups() {
const grid = useGraphiteGrid({
initial: {
columnDefinitions: [
{ id: "Alpha", groupId: ["Greeks"], field: 0 },
{ id: "Beta", groupId: ["Greeks"], field: 1 },
{ id: "Stock Price", field: 2 },
{ id: "Gamma", groupId: ["Greeks"], field: 3 },
{ id: "Nested", groupId: ["Nested", "Level 2"], field: 3 },
],
// other grid properties
},
});
return (
<div style={{ height: 400 }}>
<GraphiteGridDom state={grid} />
</div>
);
}
Column Group Visibility
Graphite Grid determines if a column group can be expanded or collapsed
depending on the value of the groupVisibility
property of all the columns in
the column group. The groupVisibility
property is defined on individual
columns and may take one of the following values:
"always-visible"
"visible-when-closed"
"visible-when-open"
A column group may not be collapsed when all the columns in that group have a
groupVisibility
value of "always-visible"
. The default value for columns is
"visible-when-open"
.
export function ColumnGroupsAlwaysVisible() {
const grid = useGraphiteGrid({
initial: {
columnDefinitions: [
{ id: "Alpha", groupId: ["Greeks"], field: 0 },
{ id: "Beta", groupId: ["Greeks"], field: 1 },
{ id: "Stock Price", field: 2 },
{
id: "Gamma",
groupId: ["Greeks"],
field: 3,
groupVisibility: "always-visible",
},
{
id: "Epsilon",
groupId: ["Greeks"],
field: 3,
groupVisibility: "always-visible",
},
],
// other grid properties
},
});
return (
<div style={{ height: 400 }}>
<GraphiteGridDom state={grid} />
</div>
);
}
In the above example, notice that the first column group is collapsible,
but the second group cannot be collapsed because all the members
have a groupVisibility
value of "always-visible"
.
Collapsed Column Group Visibility
Two outcomes may occur when a column group is collapsed depending
on the value of the groupVisibility
for the individual columns that make up that group:
- If one or more columns have
"always-visible"
or"visible-when-closed"
set, collapsing a group will result in hiding columns not visible when the group is closed. - If all the columns have
visible-when-open
(which is the default), then collapsing the group replaces the column with an empty collapsed state column, which may be expanded to open the group.
export function CollapsedVisibility() {
const grid = useGraphiteGrid({
initial: {
columnDefinitions: [
{ id: "Alpha", groupId: ["Greeks"], field: 0 },
{
id: "Beta",
groupId: ["Greeks"],
field: 1,
groupVisibility: "visible-when-closed",
},
{ id: "Stock Price", field: 2 },
{ id: "Gamma", groupId: ["Hidden On Collapse"], field: 3 },
{ id: "Epsilon", groupId: ["Hidden On Collapse"], field: 3 },
],
// other grid properties
},
});
return (
<div style={{ height: 400 }}>
<GraphiteGridDom state={grid} />
</div>
);
}
In the above example, the Beta
column is only visible when the group
it is a part of is collapsed. However, the Gamma
and Epsilon
columns are hidden when the group is collapsed, resulting in the
collapsed column being rendered.
Column ID Path Delimiter
Column groups are specified as an array of strings
on the column definition.
This array of strings is subsequently joined using a delimiter to create a group
ID for the column group. Graphite Grid uses a default delimiter to join the
group IDs. This default can be changed by specifying a value for the
columnIdPathDelimiter
in the initial state. This value cannot be changed
once set.
const grid = useGraphiteGrid({
initial: {
columnIdPathDelimiter: "--",
// other grid properties
},
});
Given the above settings, a group such as ["A", "B", "C"]
has an ID of
"A--B--C"
.
Column Group Header Renderer
To override what is displayed in a column group cell,
use the columnHeaderGroupRenderer
property on the grid.
In the example below, a custom renderer styles the cell
with Tailwind.
export function ColumnGroupRenderer() {
const grid = useGraphiteGrid({
initial: {
columnHeaderGroupRenderer: ({ columnGroup }) => {
return (
<div className="flex items-center justify-center bg-red-200 dark:bg-red-400 h-full">
{columnGroup.occurrenceKey}
</div>
);
},
// other grid properties
},
});
return (
<div style={{ height: 400 }}>
<GraphiteGridDom state={grid} />
</div>
);
}
Notice that the expansion indicator does not match the new renderer's style. The
expansion renderer is a separate component from the column group renderer, which
can be changed using the columnHeaderGroupExpansionRenderer
property.
Info
The code example uses the columnGroup.occurrenceKey
value for the group's
contents. The occurrenceKey
is the column group's ID plus a position count.
Since the same column group may be split across the Grid, each occurrence is
given an incremented count.
export function ColumnGroupRendererExpansion() {
const grid = useGraphiteGrid({
initial: {
columnHeaderGroupExpansionRenderer: ({ api, groupId }) => {
const isExpanded = api.useApiSlice((s) => s.isColumnGroupExpanded(groupId));
return (
<button
className="flex items-center justify-center bg-red-200 dark:bg-red-400 h-full w-8"
onClick={() => api.toggleColumnGroup(groupId)}
>
{isExpanded ? "-" : "+"}
</button>
);
},
// other grid properties
},
});
// ...
}
The expansion renderer is styled in the code above to match the group renderer.
The api.useApiSlice
method lets a component reactively listen to grid changes,
and the isColumnGroupExpanded(groupId)
call returns true
if the column group
is expanded.
Resizing Column Groups
A column group can be used to simultaneously resize
the individual columns within the group. A column group
will only be resizable if all the columns in the group are resizable.
In this case the change in size is distributed among the
columns in the group. The resizable
property on the definition must be true
for a column to be resizable.
export function ColumnGroupResizing() {
const grid = useGraphiteGrid({
initial: {
columnDefinitions: [
{
id: "Alpha",
groupId: ["Parent", "Resizable"],
resizable: true,
field: 0,
},
{
id: "Beta",
groupId: ["Parent", "Resizable"],
resizable: true,
field: 1,
},
{ id: "Gamma", groupId: ["Parent", "Not Resizable"], field: 2 },
{ id: "Epsilon", groupId: ["Parent", "Not Resizable"], field: 3 },
],
// other grid properties
},
});
return (
<div style={{ height: 400 }}>
<GraphiteGridDom state={grid} />
</div>
);
}
The Resizable
column group can be used to resize the Alpha
and Beta
columns because both columns are resizable. The Parent
and Not Resizable
column groups cannot be resized as the Gamma
and Epsilon
columns are not
resizable.
Tip
A column can be resized by hovering over the column with your pointer and dragging the resize handle (Note: The resize handle is a colored bar on the edge of the column).
Moving Column Groups
A column group can be used to move columns in bulk. A column group will only be moveable if all the columns in the group are moveable.
export function ColumnGroupMoveable() {
const grid = useGraphiteGrid({
initial: {
columnDefinitions: [
{
id: "Alpha",
groupId: ["Parent", "Moveable"],
moveable: true,
field: 0,
},
{
id: "Beta",
groupId: ["Parent", "Moveable"],
moveable: true,
field: 1,
},
{ id: "Gamma", groupId: ["Parent", "Not Moveable"], field: 2 },
{ id: "Epsilon", groupId: ["Parent", "Not Moveable"], field: 3 },
],
// other grid properties
},
});
return (
<div style={{ height: 400 }}>
<GraphiteGridDom state={grid} />
</div>
);
}
The Moveable
group can be moved to a new position as the Alpha
and Beta
columns are moveable. The Parent
and Not Moveable
groups are not moveable, as the Gamma
and Epsilon
columns
are not moveable. Moving a column group within itself has no effect.
Tip
Column groups can be moved by clicking and dragging the header cell. If the resize handle is clicked, it takes precedence over the move.
Sticky Label
Column groups span many columns. The grid may be scrolled horizontally
when columns take more horizontal space than the viewport. The
label of the column group may be hidden as the user scrolls. To
avoid this, set the stickyHeaderLabel
value to true
(this
value applies to both columns and column groups).
export function ColumnGroupStickyLabel() {
const grid = useGraphiteGrid({
initial: {
stickyHeaderLabel: true,
// other grid properties
},
});
// ...
}
Column Group Header Height
The height of the column group header may be controlled using the
columnHeaderGroupHeight
property on the grid. This value can be "auto"
or a
number representing height in px
. Using a fixed height is generally
recommended as the "auto"
can cause layout shifts if the content of column
group headers changes.
export function ColumnGroupHeight() {
const grid = useGraphiteGrid({
initial: {
columnHeaderGroupHeight: 80,
// other grid properties
},
});
// ...
}