Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PBNTR-771] Multi Column Headers for Advanced Table-RAILS #4052

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -40,46 +40,59 @@ export const TableHeaderCell = ({

const toggleSortButton = (event: React.SyntheticEvent) => {
if (sortControl) {
const sortIsDesc = header.column.getIsSorted() === "desc"
const sortIsDesc = header?.column.getIsSorted() === "desc"
sortIsDesc
? sortControl.onChange({ desc: true })
: sortControl.onChange({ desc: false })
} else {
header.column.getToggleSortingHandler()(event)
header?.column.getToggleSortingHandler()(event)
}
}

const cellClassName = classnames("table-header-cells",
`${isChrome() ? "chrome-styles" : ""}`,
const isLeafColumn =
header?.column.getLeafColumns().length === 1 &&
header?.column.getLeafColumns()[0].id === header.column.id

const isLastHeaderCell =
header?.column.parent?.columns.at(-1) === header?.column ||
(header?.colSpan > 1 && header?.column.parent !== undefined);

const cellClassName = classnames(
"table-header-cells",
`${isChrome() ? "chrome-styles" : ""}`,
`${enableSorting ? "table-header-cells-active" : ""}`,
{ 'pinned-left': responsive === "scroll" && isPinnedLeft },
)
{ "pinned-left": responsive === "scroll" && isPinnedLeft },
isLastHeaderCell ? "last-header-cell" : ""
);

const cellId = `${loading ?
`loading-${header.id}`
: `${header.id}`
`loading-${header?.id}`
: `${header?.id}`
}`

const isToggleExpansionEnabledLoading =
header.index === 0 &&
header?.index === 0 &&
loading &&
(enableToggleExpansion === "all" || "header") &&
enableToggleExpansion !== "none"

const isToggleExpansionEnabled =
header.index === 0 &&
header?.index === 0 &&
!loading &&
(enableToggleExpansion === "all" || "header") &&
enableToggleExpansion !== "none"

const justifyHeader = isLeafColumn ? "end" : "center"

return (
<th
align="right"
className={cellClassName}
colSpan={header?.colSpan}
id={cellId}
key={`${header.id}-header`}
key={`${header?.id}-header`}
>
{header.isPlaceholder ? null : headerChildren && header.index === 0 ? (
{header?.isPlaceholder ? null : headerChildren && header?.index === 0 ? (
<Flex alignItems="center">
{headerChildren}
<div>
Expand All @@ -89,7 +102,7 @@ const isToggleExpansionEnabled =
) : (
<Flex
alignItems="center"
justify={header.index === 0 && enableSorting ? "between" : header.index === 0 && !enableSorting ? "start" : "end"}
justify={header?.index === 0 && enableSorting ? "between" : header?.index === 0 && !enableSorting ? "start" : justifyHeader}
>
{isToggleExpansionEnabled && (
<ToggleIconButton onClick={handleExpandOrCollapse} />
Expand All @@ -100,11 +113,11 @@ const isToggleExpansionEnabled =
)}

<Flex
className={`${header.index === 0 &&
className={`${header?.index === 0 &&
enableSorting &&
"header-sort-button pb_th_link"}`}
cursor={header.index === 0 && enableSorting ? "pointer" : "default"}
{...(header.index === 0 &&
cursor={header?.index === 0 && enableSorting ? "pointer" : "default"}
{...(header?.index === 0 &&
enableSorting && {
htmlOptions: {
onClick: (event: React.MouseEvent) => toggleSortButton(event),
Expand All @@ -116,14 +129,14 @@ const isToggleExpansionEnabled =
tabIndex: 0,
},
})}
justify={header.index === 0 && enableSorting ? "between" : "none"}
justify={header?.index === 0 && enableSorting ? "between" : "none"}
paddingLeft={enableSorting ? "xxs" : "xs"}
>
<div>
{flexRender(header.column.columnDef.header, header.getContext())}
{flexRender(header?.column.columnDef.header, header?.getContext())}
</div>

{header.index === 0 &&
{header?.index === 0 &&
header.column.getCanSort() &&
enableSorting &&
(loading ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,16 @@ export const TableBody = ({
>
{row.getVisibleCells().map((cell, i) => {
const isPinnedLeft = columnPinning.left.includes(cell.column.id)
const isLastCell = cell.column.parent?.columns.at(-1)?.id === cell.column.id

return (
<td
align="right"
className={classnames(
`${cell.id}-cell position_relative`,
isChrome() ? "chrome-styles" : "",
isPinnedLeft && 'pinned-left'
isPinnedLeft && 'pinned-left',
isLastCell && 'last-cell',
)}
key={`${cell.id}-data`}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,43 @@
min-width: 180px;
}

.pb_advanced_table_header {
> tr:not(:first-child) {
.last-header-cell {
border-right: 1px solid $border_light !important;
}

th {
border-radius: 0px !important;
border-width: 0 0 1px 0 !important;
}
th:first-child {
border-left-width: 1px !important;
@media only screen and (max-width: $screen-xl-min) {
border-left-width: 0 !important;
}
}
th:last-child {
border-right-width: 1px !important;
@media only screen and (max-width: $screen-xl-min) {
border-right-width: 0 !important;
}
}
}
th[colspan]:not([colspan="1"]) {
border-right: 1px solid $border_light;
}


}

.pb_advanced_table_body {
.last-cell {
border-right: 1px solid $border_light !important;
}
}


.table-header-cells-active:first-child {
color: $primary !important;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,27 +142,41 @@ const AdvancedTable = (props: AdvancedTableProps) => {
}
return columnCells
}
//Create column array in format needed by Tanstack
const columns =
columnDefinitions &&

const buildColumns = (columnDefinitions: GenericObject[]): any => {
return (
columnDefinitions &&
columnDefinitions.map((column, index) => {
// Define the base column structure
const columnStructure = {
...columnHelper.accessor(column.accessor, {
header: column.label,
}),
}
//Checking to see if grouped column or not
if (column.columns && column.columns.length > 0) {
return {
header: column.label || "",
columns: buildColumns(column.columns),
};
} else {
// Define the base column structure
const columnStructure = {
...columnHelper.accessor(column.accessor, {
header: column.label || "",
}),
};

if (column.cellAccessors || column.customRenderer) {
columnStructure.cell = createCellFunction(
column.cellAccessors,
column.customRenderer,
index
)
}
if (column.cellAccessors || column.customRenderer) {
columnStructure.cell = createCellFunction(
column.cellAccessors,
column.customRenderer,
index
);
}

return columnStructure;
}
})
);
};

return columnStructure
})
//Create column array in format needed by Tanstack
const columns = buildColumns(columnDefinitions);

//Syntax for sorting Array if we want to manage state ourselves
const sorting = [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<% column_definitions = [
{
accessor: "year",
label: "Year",
cellAccessors: ["quarter", "month", "day"],
},
{
label: "Enrollment Data",
columns: [
{
accessor: "newEnrollments",
label: "New Enrollments",
},
{
accessor: "scheduledMeetings",
label: "Scheduled Meetings",
},
],
},
{
label: "Performance Data",
columns: [
{
accessor: "attendanceRate",
label: "Attendance Rate",
},
{
accessor: "completedClasses",
label: "Completed Classes",
},
{
accessor: "classCompletionRate",
label: "Class Completion Rate",
},
{
accessor: "graduatedStudents",
label: "Graduated Students",
},
],
},
] %>

<%= pb_rails("advanced_table", props: { id: "beta_table_with_headers", table_data: @table_data, column_definitions: column_definitions }) %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from "react"
import { AdvancedTable } from "playbook-ui"
import MOCK_DATA from "./advanced_table_mock_data.json"

const AdvancedTableColumnHeaders = (props) => {
const columnDefinitions = [
{
accessor: "year",
label: "Year",
cellAccessors: ["quarter", "month", "day"],
},
{
label: "Enrollment Data",
columns: [
{
accessor: "newEnrollments",
label: "New Enrollments",
},
{
accessor: "scheduledMeetings",
label: "Scheduled Meetings",
},
],
},
{
label: "Performance Data",
columns: [
{
accessor: "attendanceRate",
label: "Attendance Rate",
},
{
accessor: "completedClasses",
label: "Completed Classes",
},
{
accessor: "classCompletionRate",
label: "Class Completion Rate",
},
{
accessor: "graduatedStudents",
label: "Graduated Students",
},
],
},
];


return (
<>
<AdvancedTable
columnDefinitions={columnDefinitions}
tableData={MOCK_DATA}
{...props}
/>
</>
)
}

export default AdvancedTableColumnHeaders
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Use a nested `columns` array in your columnDefinitions to create multiple header rows. Any column with `columns` is treated as a grouped header, and its child columns are displayed beneath it.
Loading
Loading