Skip to content

Commit

Permalink
Added stickyRightcolumn prop and example doc. Adjusted styling to acc…
Browse files Browse the repository at this point in the history
…omodate prop
  • Loading branch information
skduncan committed Dec 23, 2024
1 parent 12f1d15 commit 9002861
Show file tree
Hide file tree
Showing 8 changed files with 206 additions and 34 deletions.
79 changes: 67 additions & 12 deletions playbook/app/pb_kits/playbook/pb_table/_table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type TableProps = {
size?: "sm" | "md" | "lg",
sticky?: boolean,
stickyLeftcolumn?: string[],
stickyRightcolumn?: string[],
striped?: boolean,
tag?: "table" | "div",
verticalBorder?: boolean,
Expand All @@ -53,6 +54,7 @@ const Table = (props: TableProps): React.ReactElement => {
size = 'sm',
sticky = false,
stickyLeftcolumn = [],
stickyRightcolumn= [],
striped = false,
tag = 'table',
verticalBorder = false,
Expand Down Expand Up @@ -80,6 +82,7 @@ const Table = (props: TableProps): React.ReactElement => {
'no-hover': disableHover,
'sticky-header': sticky,
'sticky-left-column': stickyLeftcolumn,
'sticky-right-column': stickyRightcolumn,
'striped': striped,
[outerPaddingCss]: outerPadding !== '',
},
Expand All @@ -90,7 +93,8 @@ const Table = (props: TableProps): React.ReactElement => {
)

useEffect(() => {
const handleStickyColumns = () => {
const handleStickyLeftColumns = () => {
if (!stickyLeftcolumn.length) return;
let accumulatedWidth = 0;

stickyLeftcolumn.forEach((colId, index) => {
Expand All @@ -103,11 +107,11 @@ const Table = (props: TableProps): React.ReactElement => {
(header as HTMLElement).style.left = `${accumulatedWidth}px`;

if (!isLastColumn) {
header.classList.add('with-border');
header.classList.remove('sticky-shadow');
header.classList.add('with-border-right');
header.classList.remove('sticky-left-shadow');
} else {
header.classList.remove('with-border');
header.classList.add('sticky-shadow');
header.classList.remove('with-border-right');
header.classList.add('sticky-left-shadow');
}

accumulatedWidth += (header as HTMLElement).offsetWidth;
Expand All @@ -118,27 +122,78 @@ const Table = (props: TableProps): React.ReactElement => {
(cell as HTMLElement).style.left = `${accumulatedWidth - (header as HTMLElement).offsetWidth}px`;

if (!isLastColumn) {
cell.classList.add('with-border');
cell.classList.remove('sticky-shadow');
cell.classList.add('with-border-right');
cell.classList.remove('sticky-left-shadow');
} else {
cell.classList.remove('with-border');
cell.classList.add('sticky-shadow');
cell.classList.remove('with-border-right');
cell.classList.add('sticky-left-shadow');
}
});
});
};

setTimeout(() => {
handleStickyColumns();
handleStickyLeftColumns();
}, 10);

window.addEventListener('resize', handleStickyColumns);
window.addEventListener('resize', handleStickyLeftColumns);

return () => {
window.removeEventListener('resize', handleStickyColumns);
window.removeEventListener('resize', handleStickyLeftColumns);
};
}, [stickyLeftcolumn]);

useEffect(() => {
const handleStickyRightColumns = () => {
if (!stickyRightcolumn.length) return;
let accumulatedWidth = 0;

stickyRightcolumn.reverse().forEach((colId, index) => {
const isLastColumn = index === stickyRightcolumn.length - 1;
const header = document.querySelector(`th[id="${colId}"]`);
const cells = document.querySelectorAll(`td[id="${colId}"]`);

if (header) {
header.classList.add('sticky');
(header as HTMLElement).style.right = `${accumulatedWidth}px`;

if (!isLastColumn) {
header.classList.add('with-border-left');
header.classList.remove('sticky-right-shadow');
} else {
header.classList.remove('with-border-left');
header.classList.add('sticky-right-shadow');
}

accumulatedWidth += (header as HTMLElement).offsetWidth;
}

cells.forEach((cell) => {
cell.classList.add('sticky');
(cell as HTMLElement).style.right = `${accumulatedWidth - (header as HTMLElement).offsetWidth}px`;

if (!isLastColumn) {
cell.classList.add('with-border-left');
cell.classList.remove('sticky-right-shadow');
} else {
cell.classList.remove('with-border-left');
cell.classList.add('sticky-right-shadow');
}
});
});
};

setTimeout(() => {
handleStickyRightColumns();
}, 10);

window.addEventListener('resize', handleStickyRightColumns);

return () => {
window.removeEventListener('resize', handleStickyRightColumns);
};
}, [stickyRightcolumn]);

useEffect(() => {
const instance = new PbTable()
instance.connect()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import React from 'react'
import Table from '../_table'

const TableStickyLeftColumns = () => {
return (
<Table
responsive="scroll"
size="md"
stickyRightcolumn={["13", "14", "15"]}
>
<thead>
<tr>
<th>{'Column 1'}</th>
<th>{'Column 2'}</th>
<th>{'Column 3'}</th>
<th>{'Column 4'}</th>
<th>{'Column 5'}</th>
<th>{'Column 6'}</th>
<th>{'Column 7'}</th>
<th>{'Column 8'}</th>
<th>{'Column 9'}</th>
<th>{'Column 10'}</th>
<th>{'Column 11'}</th>
<th>{'Column 12'}</th>
<th id="13">{'Column 13'}</th>
<th id="14">{'Column 14'}</th>
<th id="15">{'Column 15'}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{'Value 1'}</td>
<td>{'Value 2'}</td>
<td>{'Value 3'}</td>
<td>{'Value 4'}</td>
<td>{'Value 5'}</td>
<td>{'Value 6'}</td>
<td>{'Value 7'}</td>
<td>{'Value 8'}</td>
<td>{'Value 9'}</td>
<td>{'Value 10'}</td>
<td>{'Value 11'}</td>
<td>{'Value 12'}</td>
<td id="13">{'Value 13'}</td>
<td id="14">{'Value 14'}</td>
<td id="15">{'Value 15'}</td>
</tr>
<tr>
<td>{'Value 1'}</td>
<td>{'Value 2'}</td>
<td>{'Value 3'}</td>
<td>{'Value 4'}</td>
<td>{'Value 5'}</td>
<td>{'Value 6'}</td>
<td>{'Value 7'}</td>
<td>{'Value 8'}</td>
<td>{'Value 9'}</td>
<td>{'Value 10'}</td>
<td>{'Value 11'}</td>
<td>{'Value 12'}</td>
<td id="13">{'Value 13'}</td>
<td id="14">{'Value 14'}</td>
<td id="15">{'Value 15'}</td>
</tr>
<tr>
<td>{'Value 1'}</td>
<td>{'Value 2'}</td>
<td>{'Value 3'}</td>
<td>{'Value 4'}</td>
<td>{'Value 5'}</td>
<td>{'Value 6'}</td>
<td>{'Value 7'}</td>
<td>{'Value 8'}</td>
<td>{'Value 9'}</td>
<td>{'Value 10'}</td>
<td>{'Value 11'}</td>
<td>{'Value 12'}</td>
<td id="13">{'Value 13'}</td>
<td id="14">{'Value 14'}</td>
<td id="15">{'Value 15'}</td>
</tr>
</tbody>
</Table>
)
}

export default TableStickyLeftColumns
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The `stickyRightColumn` prop works in the same way as the above `stickyLeftColumn` prop. It expects an array of the column ids you want to be sticky. Make sure to add the corresponding id to the `<th>` and `<td>`.
If you are using the sub-component variant, then you will pass the id to `<Table.Header>` and `<Table.Cell>`
1 change: 1 addition & 0 deletions playbook/app/pb_kits/playbook/pb_table/docs/example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ examples:
- table_lg: Large
- table_sticky: Sticky Header
- table_sticky_left_columns: Sticky Left Column
- table_sticky_right_columns: Sticky Right Column
- table_alignment_row: Row Alignment
- table_alignment_column: Cell Alignment
- table_alignment_shift_row: Row Shift
Expand Down
1 change: 1 addition & 0 deletions playbook/app/pb_kits/playbook/pb_table/docs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export { default as TableWithSubcomponents } from './_table_with_subcomponents.j
export { default as TableWithSubcomponentsAsDivs } from './_table_with_subcomponents_as_divs.jsx'
export { default as TableOuterPadding } from './_table_outer_padding.jsx'
export { default as TableStickyLeftColumns } from './_table_sticky_left_columns.jsx'
export { default as TableStickyRightColumns } from './_table_sticky_right_columns.jsx'
export { default as TableWithCollapsible } from './_table_with_collapsible.jsx'
export { default as TableWithCollapsibleWithCustomContent } from './_table_with_collapsible_with_custom_content.jsx'
export { default as TableWithCollapsibleWithNestedTable } from './_table_with_collapsible_with_nested_table.jsx'
Expand Down
34 changes: 17 additions & 17 deletions playbook/app/pb_kits/playbook/pb_table/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import PbEnhancedElement from '../pb_enhanced_element'

export default class PbTable extends PbEnhancedElement {
private stickyLeftColumns: string[] = [];
private handleStickyColumnsRef: () => void;
private handleStickyLeftColumnsRef: () => void;

static get selector(): string {
return '.table-responsive-collapse'
Expand Down Expand Up @@ -31,10 +31,10 @@ export default class PbTable extends PbEnhancedElement {
});

// New sticky columns logic
this.initStickyColumns();
this.initStickyLeftColumns();
}

private initStickyColumns(): void {
private initStickyLeftColumns(): void {
// Find tables with sticky-left-column class
const tables = document.querySelectorAll('.sticky-left-column');

Expand All @@ -52,16 +52,16 @@ export default class PbTable extends PbEnhancedElement {

if (this.stickyLeftColumns.length > 0) {
setTimeout(() => {
this.handleStickyColumnsRef = this.handleStickyColumns.bind(this);
this.handleStickyColumns();
window.addEventListener('resize', this.handleStickyColumnsRef);
this.handleStickyLeftColumnsRef = this.handleStickyLeftColumns.bind(this);
this.handleStickyLeftColumns();
window.addEventListener('resize', this.handleStickyLeftColumnsRef);
}, 10);
}
}
});
}

private handleStickyColumns(): void {
private handleStickyLeftColumns(): void {
let accumulatedWidth = 0;

this.stickyLeftColumns.forEach((colId, index) => {
Expand All @@ -74,11 +74,11 @@ export default class PbTable extends PbEnhancedElement {
(header as HTMLElement).style.left = `${accumulatedWidth}px`;

if (!isLastColumn) {
header.classList.add('with-border');
header.classList.remove('sticky-shadow');
header.classList.add('with-border-right');
header.classList.remove('sticky-left-shadow');
} else {
header.classList.remove('with-border');
header.classList.add('sticky-shadow');
header.classList.remove('with-border-right');
header.classList.add('sticky-left-shadow');
}

accumulatedWidth += (header as HTMLElement).offsetWidth;
Expand All @@ -89,20 +89,20 @@ export default class PbTable extends PbEnhancedElement {
(cell as HTMLElement).style.left = `${accumulatedWidth - (header as HTMLElement).offsetWidth}px`;

if (!isLastColumn) {
cell.classList.add('with-border');
cell.classList.remove('sticky-shadow');
cell.classList.add('with-border-right');
cell.classList.remove('sticky-left-shadow');
} else {
cell.classList.remove('with-border');
cell.classList.add('sticky-shadow');
cell.classList.remove('with-border-right');
cell.classList.add('sticky-left-shadow');
}
});
});
}

// Cleanup method to remove event listener
disconnect(): void {
if (this.handleStickyColumnsRef) {
window.removeEventListener('resize', this.handleStickyColumnsRef);
if (this.handleStickyLeftColumnsRef) {
window.removeEventListener('resize', this.handleStickyLeftColumnsRef);
}
}
}
20 changes: 18 additions & 2 deletions playbook/app/pb_kits/playbook/pb_table/styles/_scroll.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,24 @@
@media (max-width: 1600px) {
&[class*="table-responsive-scroll"] {
border-radius: 4px;
box-shadow: 1px 0 0 0px $border_light
}
box-shadow: 1px 0 0 0px $border_light,
-1px 0 0 0px $border_light
}

&[class^=pb_table].table-sm.table-card thead tr th:first-child,
&[class^=pb_table].table-sm:not(.no-hover).table-card tbody tr td:first-child {
border-left-width: 0px;
}

&[class^=pb_table].table-md.table-card thead tr th:first-child,
&[class^=pb_table].table-md:not(.no-hover).table-card tbody tr td:first-child {
border-left-width: 0px;
}

&[class^=pb_table].table-lg.table-card thead tr th:first-child,
&[class^=pb_table].table-lg:not(.no-hover).table-card tbody tr td:first-child {
border-left-width: 0px;
}

&[class^=pb_table].table-sm.table-card thead tr th:last-child,
&[class^=pb_table].table-sm:not(.no-hover).table-card tbody tr td:last-child {
Expand Down
16 changes: 13 additions & 3 deletions playbook/app/pb_kits/playbook/pb_table/styles/_sticky_columns.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,21 @@
background-color: white;
}

.with-border {
// For use with sticky left columns
.sticky-left-shadow {
box-shadow: 4px 0 10px rgba(60, 106, 172, 0.16) !important;
}

.with-border-right {
border-right: 1px solid $border_light !important;
}

.sticky-shadow {
box-shadow: 4px 0 10px rgba(60, 106, 172, 0.16) !important;
// For use with sticky right columns
.sticky-right-shadow {
box-shadow: -4px 0 10px rgba(60, 106, 172, 0.16) !important;
}

.with-border-left {
border-left: 1px solid $border_light !important;
}
}

0 comments on commit 9002861

Please sign in to comment.