Skip to content

Commit 7dbfb5c

Browse files
authored
feat(pds-table): add head border, background, and row divider props (#629)
* feat(pds-table): add border, background, and rowDividers props * test(pds-table): add tests for border, background, and rowDividers * docs(pds-table): add stories and docs for new props * docs(pds-table): update readme files * style(pds-table): adjust padding and add letter-spacing to table head cell * docs(pds-table): enhance documentation for head background and row dividers * refactor(pds-table-head-cell): use @State for reactive class management * refactor(pds-table-row): use @State for reactive class management * docs(pds-table): add rowDividers to React example * docs(pds-table): clarify component names in documentation * test(pds-table-head-cell): add tests for sorting, border, and background attributes * chore(pds-table): remove unused story exports for table head configurations * refactor(pds-table): update rowDividers prop to reflect changes and clean up unused code * refactor(pds-table): change lifecycle method to componentWillLoad and streamline rowDividers logic * fix(pds-table): set default value for rowDividers prop to false and update documentation * refactor(pds-table-row): enhance observer management for row sorting * fix(pds-table): update border property description to reflect top and bottom borders * test(pds-table-row): add verification for is-last-row class in row rendering * test(pds-table-row): update checkbox type assertion and enhance row existence checks
1 parent cc3c994 commit 7dbfb5c

File tree

16 files changed

+782
-25
lines changed

16 files changed

+782
-25
lines changed

libs/core/src/components.d.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1713,6 +1713,11 @@ export namespace Components {
17131713
* Enables the table to be responsive by horizontally scrolling on smaller screens.
17141714
*/
17151715
"responsive": boolean;
1716+
/**
1717+
* Adds divider borders between table rows. The last row will not have a bottom border.
1718+
* @defaultValue false
1719+
*/
1720+
"rowDividers": boolean;
17161721
/**
17171722
* Determines if the table displays checkboxes for selectable rows.
17181723
*/
@@ -1731,6 +1736,16 @@ export namespace Components {
17311736
"truncate": boolean;
17321737
}
17331738
interface PdsTableHead {
1739+
/**
1740+
* Adds a subtle background color to the table head.
1741+
* @defaultValue false
1742+
*/
1743+
"background": boolean;
1744+
/**
1745+
* Adds top and bottom borders to the table head.
1746+
* @defaultValue false
1747+
*/
1748+
"border": boolean;
17341749
/**
17351750
* Determines if the select all checkbox is in an indeterminate state.
17361751
*/
@@ -4479,6 +4494,11 @@ declare namespace LocalJSX {
44794494
* Enables the table to be responsive by horizontally scrolling on smaller screens.
44804495
*/
44814496
"responsive"?: boolean;
4497+
/**
4498+
* Adds divider borders between table rows. The last row will not have a bottom border.
4499+
* @defaultValue false
4500+
*/
4501+
"rowDividers"?: boolean;
44824502
/**
44834503
* Determines if the table displays checkboxes for selectable rows.
44844504
*/
@@ -4497,6 +4517,16 @@ declare namespace LocalJSX {
44974517
"truncate"?: boolean;
44984518
}
44994519
interface PdsTableHead {
4520+
/**
4521+
* Adds a subtle background color to the table head.
4522+
* @defaultValue false
4523+
*/
4524+
"background"?: boolean;
4525+
/**
4526+
* Adds top and bottom borders to the table head.
4527+
* @defaultValue false
4528+
*/
4529+
"border"?: boolean;
45004530
/**
45014531
* Determines if the select all checkbox is in an indeterminate state.
45024532
*/

libs/core/src/components/pds-table/docs/pds-table.mdx

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { components } from '../../../../dist/docs.json';
88

99
# Table
1010

11-
The table, consisting of rows and columns, is used to display and organize tabular data.
11+
The table (`pds-table`), consisting of rows and columns, is used to display and organize tabular data.
1212

1313
## Guidelines
1414

@@ -29,21 +29,27 @@ Be sure to make proper use of the subcomponents to ensure that the table is acce
2929

3030
<DocArgsTable componentName="pds-table" docSource={components} />
3131

32+
### Head
33+
34+
The table header (`pds-table-head`). Equivalent to the `<thead>` element.
35+
36+
<DocArgsTable componentName="pds-table-head" docSource={components} />
37+
3238
### Head Cell
3339

34-
The table header cell. Equivalent to the `<th>` element.
40+
The table header cell (`pds-table-head-cell`). Equivalent to the `<th>` element.
3541

3642
<DocArgsTable componentName="pds-table-head-cell" docSource={components} />
3743

3844
### Row
3945

40-
The table row. Equivalent to the `<tr>` element.
46+
The table row (`pds-table-row`). Equivalent to the `<tr>` element.
4147

4248
<DocArgsTable componentName="pds-table-row" docSource={components} />
4349

4450
### Cell
4551

46-
The table body cell. Equivalent to the `<td>` element.
52+
The table body cell (`pds-table-cell`). Equivalent to the `<td>` element.
4753

4854
<DocArgsTable componentName="pds-table-cell" docSource={components} />
4955

@@ -211,6 +217,87 @@ A compact table is a table with a reduced row spacing. This is useful for tables
211217
</pds-table>
212218
</DocCanvas>
213219

220+
### Head Background and Row Dividers
221+
222+
When the `border` and `background` props are set to `true` on `pds-table-head`, the header will display top and bottom borders and a subtle background color to visually distinguish it from the table body. When the `row-dividers` prop is set to `true` on `pds-table`, divider borders will be added between rows for clear separation. The last row will not have a bottom border.
223+
224+
<DocCanvas mdxSource={{
225+
react: `<PdsTable componentId="head-background-dividers" rowDividers={true}>
226+
<PdsTableHead background={true} border={true}>
227+
<PdsTableHeadCell>Column Title</PdsTableHeadCell>
228+
<PdsTableHeadCell>Column Title</PdsTableHeadCell>
229+
<PdsTableHeadCell>Column Title</PdsTableHeadCell>
230+
</PdsTableHead>
231+
<PdsTableBody>
232+
<PdsTableRow>
233+
<PdsTableCell>Row Item Alpha</PdsTableCell>
234+
<PdsTableCell>Row Item Beta</PdsTableCell>
235+
<PdsTableCell>Row Item Charlie</PdsTableCell>
236+
</PdsTableRow>
237+
<PdsTableRow>
238+
<PdsTableCell>Row Item Alpha</PdsTableCell>
239+
<PdsTableCell>Row Item Beta</PdsTableCell>
240+
<PdsTableCell>Row Item Charlie</PdsTableCell>
241+
</PdsTableRow>
242+
<PdsTableRow>
243+
<PdsTableCell>Row Item Alpha</PdsTableCell>
244+
<PdsTableCell>Row Item Beta</PdsTableCell>
245+
<PdsTableCell>Row Item Charlie</PdsTableCell>
246+
</PdsTableRow>
247+
</PdsTableBody>
248+
</PdsTable>`,
249+
webComponent: `
250+
<pds-table component-id="head-background-dividers" row-dividers>
251+
<pds-table-head background border>
252+
<pds-table-head-cell>Column Title</pds-table-head-cell>
253+
<pds-table-head-cell>Column Title</pds-table-head-cell>
254+
<pds-table-head-cell>Column Title</pds-table-head-cell>
255+
</pds-table-head>
256+
<pds-table-body>
257+
<pds-table-row>
258+
<pds-table-cell>Row Item Alpha</pds-table-cell>
259+
<pds-table-cell>Row Item Beta</pds-table-cell>
260+
<pds-table-cell>Row Item Charlie</pds-table-cell>
261+
</pds-table-row>
262+
<pds-table-row>
263+
<pds-table-cell>Row Item Alpha</pds-table-cell>
264+
<pds-table-cell>Row Item Beta</pds-table-cell>
265+
<pds-table-cell>Row Item Charlie</pds-table-cell>
266+
</pds-table-row>
267+
<pds-table-row>
268+
<pds-table-cell>Row Item Alpha</pds-table-cell>
269+
<pds-table-cell>Row Item Beta</pds-table-cell>
270+
<pds-table-cell>Row Item Charlie</pds-table-cell>
271+
</pds-table-row>
272+
</pds-table-body>
273+
</pds-table>
274+
`}}>
275+
<pds-table component-id="head-background-dividers" row-dividers>
276+
<pds-table-head background border>
277+
<pds-table-head-cell>Column Title</pds-table-head-cell>
278+
<pds-table-head-cell>Column Title</pds-table-head-cell>
279+
<pds-table-head-cell>Column Title</pds-table-head-cell>
280+
</pds-table-head>
281+
<pds-table-body>
282+
<pds-table-row>
283+
<pds-table-cell>Row Item Alpha</pds-table-cell>
284+
<pds-table-cell>Row Item Beta</pds-table-cell>
285+
<pds-table-cell>Row Item Charlie</pds-table-cell>
286+
</pds-table-row>
287+
<pds-table-row>
288+
<pds-table-cell>Row Item Alpha</pds-table-cell>
289+
<pds-table-cell>Row Item Beta</pds-table-cell>
290+
<pds-table-cell>Row Item Charlie</pds-table-cell>
291+
</pds-table-row>
292+
<pds-table-row>
293+
<pds-table-cell>Row Item Alpha</pds-table-cell>
294+
<pds-table-cell>Row Item Beta</pds-table-cell>
295+
<pds-table-cell>Row Item Charlie</pds-table-cell>
296+
</pds-table-row>
297+
</pds-table-body>
298+
</pds-table>
299+
</DocCanvas>
300+
214301

215302
### Selectable
216303

libs/core/src/components/pds-table/pds-table-head-cell/pds-table-head-cell.scss

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
:host {
2-
--border-head-cell-default: var(--pine-border-width-thin) solid var(--pine-color-background-subtle);
2+
--border-head-cell-default: var(--pine-border-width-thin) solid var(--pine-color-border-subtle);
33

44
--box-shadow-default: 3px 3px 6px -2px rgba(0, 0, 0, 0.1);
55

@@ -9,8 +9,9 @@
99
font-family: var(--pine-font-family-body);
1010
font-size: var(--pine-font-size);
1111
font-weight: var(--pine-font-weight-regular);
12+
letter-spacing: var(--pine-letter-spacing);
1213
line-height: var(--pine-line-height-body);
13-
padding: var(--pine-dimension-150);
14+
padding: var(--pine-dimension-sm);
1415
position: relative;
1516
text-align: start;
1617
vertical-align: inherit;
@@ -27,6 +28,16 @@
2728
z-index: var(--pine-z-index-raised);
2829
}
2930

31+
// When parent table-head has background, fixed cells should inherit it
32+
:host(.is-fixed.has-head-background) {
33+
background-color: var(--pine-color-background-subtle);
34+
}
35+
36+
// When parent table-head has border prop, add top border (bottom already set in :host)
37+
:host(.has-head-border) {
38+
border-block-start: var(--border-head-cell-default);
39+
}
40+
3041
// box shadow when table has scrolled and cell is fixed
3142
:host(.has-scrolled.is-fixed) {
3243
box-shadow: var(--box-shadow-default);

libs/core/src/components/pds-table/pds-table-head-cell/pds-table-head-cell.tsx

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export class PdsTableHeadCell {
1313
private scrollContainer: HTMLElement | null = null;
1414
private setupTimer: number | undefined;
1515
private setupRetries: number = 0;
16+
private headObserver?: MutationObserver;
1617

1718
/**
1819
* Sets the text alignment within the head cell.
@@ -46,8 +47,27 @@ export class PdsTableHeadCell {
4647
*/
4748
@State() isSelected: boolean = false;
4849

49-
componentWillRender() {
50+
/**
51+
* Determines if the parent table-head has the border attribute.
52+
* @defaultValue false
53+
*/
54+
@State() private hasHeadBorder: boolean = false;
55+
56+
/**
57+
* Determines if the parent table-head has the background attribute.
58+
* @defaultValue false
59+
*/
60+
@State() private hasHeadBackground: boolean = false;
61+
62+
componentWillLoad() {
63+
// Set initial references and state before first render
5064
this.tableRef = this.hostElement.closest('pds-table') as HTMLPdsTableElement;
65+
66+
const tableHead = this.hostElement.closest('pds-table-head') as HTMLElement;
67+
if (tableHead) {
68+
this.hasHeadBorder = tableHead.hasAttribute('border');
69+
this.hasHeadBackground = tableHead.hasAttribute('background');
70+
}
5171
}
5272

5373
componentDidLoad() {
@@ -56,12 +76,37 @@ export class PdsTableHeadCell {
5676
// This enables the first column header to show a shadow when the table is scrolled horizontally
5777
this.setupScrollListener();
5878
}
79+
80+
// Watch for changes to the parent table-head's border and background attributes
81+
const tableHead = this.hostElement.closest('pds-table-head') as HTMLElement;
82+
if (tableHead && typeof MutationObserver !== 'undefined') {
83+
// Defensive guard: disconnect existing observer before creating a new one
84+
if (this.headObserver) {
85+
this.headObserver.disconnect();
86+
}
87+
88+
this.headObserver = new MutationObserver(() => {
89+
// Update state when border or background attributes change
90+
this.hasHeadBorder = tableHead.hasAttribute('border');
91+
this.hasHeadBackground = tableHead.hasAttribute('background');
92+
});
93+
94+
this.headObserver.observe(tableHead, {
95+
attributes: true,
96+
attributeFilter: ['border', 'background']
97+
});
98+
}
5999
}
60100

61101
disconnectedCallback() {
62102
this.cleanupScrollListener();
103+
104+
if (this.headObserver) {
105+
this.headObserver.disconnect();
106+
}
63107
}
64108

109+
65110
private setupScrollListener() {
66111
if (!this.tableRef) return;
67112

@@ -156,6 +201,14 @@ export class PdsTableHeadCell {
156201
classNames.push('has-scrolled');
157202
}
158203

204+
if (this.hasHeadBackground) {
205+
classNames.push('has-head-background');
206+
}
207+
208+
if (this.hasHeadBorder) {
209+
classNames.push('has-head-border');
210+
}
211+
159212
return classNames.join(' ');
160213
}
161214

0 commit comments

Comments
 (0)