NOTE: If using expandedControl the dev is expected to manage the row level expansion state themselves, the kit itself will NOT do it by default.
expandedControl is an optional prop that can be used to gain greater control over the expansion state of the Advanced Table. Tanstack handles expansion itself, however it does provide for a way to handle the state manually if needed. Usecases for this include needing to store the expansion state so it persists on page reload, set an initial expansion state, etc.
In this example we are showing that if initial expansion state is set, it will render the table expanded according to that state.
The expanded state must be an object with key/value pairs where the key is the row id and the value is a boolean, true or false. Tanstack by default assigns row ids based on index and depth of the row as can be seen in this example. For more information on row ids, see here.
By default, the click event on the row level toggleExpansion icon simply toggles the immediate sub rows open or closed. If you want to attach further logic to that button, the optional onRowToggleClick prop can be used. This click event provides one argument that can be hooked into: the current row object. Any additional functionality provided through this onClick will be applied in addition to the default.
Similar to the row level click event, the default of the click event on the toggleExpansion buttons that render in the first column header (and the subRow Header rows if prop enabled) toggles all top level rows open and closed. If you want to attach further logic to that button, the optional onToggleExpansionClick prop can be used. This click event provides one argument that can be hooked into: the current row object. Any additional functionality provided through this onClick will be applied in addition to the default.
ToggleExpansionIcon is another optional prop that can be used to customize the icon for the toggleExpansion button. This prop takes a string value with the default set to arrows-from-line. All strings must be valid FA icons.
import React, { useState } from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableExpandedControl = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] //State for manually effecting what is expanded const [expanded, setExpanded] = useState({'0': true, '0.0': true, '0.0.1': true}) //Passing expanded state to AdvancedTable as prop const expandedControl = { value: expanded, onChange: setExpanded, } const onRowToggleClick = (row) => { setExpanded({ ...expanded, [row.id]: !expanded[row.id] }) } return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} expandedControl={expandedControl} onRowToggleClick={onRowToggleClick} tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableExpandedControl
The expandByDepth prop enables users to expand or collapse table rows by specific levels of nesting. When provided, it renders a dropdown that appears when the toggle icon in the header is clicked.
expandByDepth accepts an array of objects, where each object defines the depth level to target and the label to display in the dropdown. When a user selects an option:
Expanding a depth: Expands all rows at the selected depth AND all parent levels above it (if parent levels were closed), ensuring nested content is visible.
Collapsing a depth: Only collapses rows at the selected depth, keeping parent rows expanded for context.
If you want to attach further logic to each option click, the optional onExpandByDepthClick prop can be used. This click event provides 2 arguments that can be hooked into: the depth level of the clicked item AND all flattened table rows. Any additional functionality provided through this onClick will be applied in addition to the default.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableExpandByDepth = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] const expandByDepth = [ { depth: 0, label: "Year", }, { depth: 1, label: "Quarter", }, { depth: 2, label: "Month", } ] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} expandByDepth={expandByDepth} onExpandByDepthClick={(depth, rows) => {console.log(depth, rows)}} tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableExpandByDepth
subRowHeaders is an optional prop that if present will add header rows at each level of the nested data. The prop takes an array of strings, each string being the text for each header row. The array of strings must be in the order in which they need to be rendered in the UI according to depth.
enableToggleExpansion is an additional optional prop that can be used in conjunction with the subRowHeaders prop. enableToggleExpansion is a string that can be "all", "header" or "none". If set to "all", the toggle exapansion button will appear in the table header as well as in the subRow headers. If set to "header" button will only appear in header and NOT in subRow headers. This is set to "header" by default.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableSubrowHeaders = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] //Render the subRow header rows const subRowHeaders = ["Quarter", "Month", "Day"] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} enableToggleExpansion="all" tableData={MOCK_DATA} > <AdvancedTable.Header /> <AdvancedTable.Body subRowHeaders={subRowHeaders}/> </AdvancedTable> </div> ) } export default AdvancedTableSubrowHeaders
cascadeCollapse is an optional prop that is set to 'false' by default. If set to 'true', collapsing any parent row itself or by using the toggle exapansion buttons in any header or subheader row also collapses all descendants and clears their expansion state. Re-expanding then shows only direct children until the user expands deeper levels again.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableCascadeCollapse = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] return ( <div> <AdvancedTable cascadeCollapse columnDefinitions={columnDefinitions} tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableCascadeCollapse
Use the pinnedRows prop to pin specific rows to the top of an Advanced Table. Pinned rows will remain at the top when scrolling through table data and will not change position if sorting is used.
NOTE:
sticky: true via tableProps (works with both responsive and non-responsive tables)tableData Array must contain a unique id in order to attach an id to all Rows for this to function. pinnedRows takes an array of row ids to the top property as shown in the code snippet below. pinnedRows, all its children will automatically be pinned with it. If id for a child is passed in without parent being pinned, nothing will be pinned. import React, { useState } from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data_with_id.json" const AdvancedTableRowPinning = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] const [pinnedRows, setPinnedRows] = useState({top: ["8"]}) return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} maxHeight="xs" pinnedRows={{value: pinnedRows, onChange: setPinnedRows}} tableData={MOCK_DATA} tableProps={{sticky: true}} > <AdvancedTable.Header enableSorting /> <AdvancedTable.Body /> </AdvancedTable> </div> ) } export default AdvancedTableRowPinning
selectableRows is a boolean prop that if present will add checkboxes to all rows that will allow for selecting rows.
When a parent row is clicked, it will check all nested children rows, Children rows can be manually checked or unchecked as well.
The onRowSelectionChange prop returns an array of ids of all Rows that have been selected. Open the console on this example and check and uncheck checkboxes to see this is action! NOTE: Each object within the tableDataArray must contain a unique id in order to attach an id to all Rows for this to function.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data_with_id.json" const AdvancedTableSelectableRows = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] //Render the subRow header rows const subRowHeaders = ["Quarter", "Month", "Day"] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} enableToggleExpansion="all" onRowSelectionChange={(selectedRows) => console.log(selectedRows)} selectableRows tableData={MOCK_DATA} > <AdvancedTable.Header /> <AdvancedTable.Body subRowHeaders={subRowHeaders}/> </AdvancedTable> </div> ) } export default AdvancedTableSelectableRows
selectableRows can also be used with tables without nested row data.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data_no_subrows.json" const AdvancedTableSelectableRowsNoSubrowsReact = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} onRowSelectionChange={(selectedRows) => console.log(selectedRows)} selectableRows tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableSelectableRowsNoSubrowsReact
Custom actions content can be rendered within the Actions Bar as shown in this doc example. The component passed to actions will be rendered on the right of the actionsBar. The onRowSelectionChange can then be used to attach the needed click events to those actions.
import React, {useState} from "react" import { AdvancedTable, CircleIconButton, Flex } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data_no_subrows.json" const AdvancedTableSelectableRowsActions = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] const [selectedRows, setSelectedRows] = useState() const CustomActions = () => { const rowIds = selectedRows ? Object.keys(selectedRows) : []; return ( <Flex> <CircleIconButton icon="file-csv" onClick={() => alert(rowIds.length === 0 ? "No Selection Made" : 'Row ids ' + rowIds.join(", ") + 'will be exported!') } variant="link" /> <CircleIconButton icon="trash-alt" onClick={() => alert(rowIds.length === 0 ? "No Selection Made" : 'Row ids ' + rowIds.join(", ") + 'will be deleted!') } variant="link" /> </Flex> ); }; return ( <div> <AdvancedTable actions={<CustomActions/>} columnDefinitions={columnDefinitions} onRowSelectionChange={(selected) => setSelectedRows(selected)} selectableRows tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableSelectableRowsActions
showActionsBar is an optional prop that renders the header at the top showing the row count. This is set to true by default but can be toggled off by setting it to false
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data_no_subrows.json" const AdvancedTableSelectableRowsHeader = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} onRowSelectionChange={(selectedRows) => console.log(selectedRows)} selectableRows showActionsBar={false} tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableSelectableRowsHeader