Skip to content

Commit 5febd6e

Browse files
committed
Fix bugs around sticky headers, pips
1 parent 6721f80 commit 5febd6e

File tree

6 files changed

+63
-117
lines changed

6 files changed

+63
-117
lines changed

polaris-react/src/components/DataTable/DataTable.stories.tsx

Lines changed: 12 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -13,45 +13,12 @@ export default {
1313
},
1414
} as ComponentMeta<typeof DataTable>;
1515

16-
function sortRows(rows, index, direction) {
16+
function sortCurrency(rows, index, direction) {
1717
return [...rows].sort((rowA, rowB) => {
18-
let type;
19-
if (rowA[index].length > 1) {
20-
if (!isNaN(parseFloat(rowA[index]))) {
21-
type = 'number';
22-
} else if (!isNaN(parseFloat(rowA[index].substring(1)))) {
23-
type = 'currency';
24-
} else type = 'string';
25-
} else {
26-
type = !isNaN(parseFloat(rowA[index])) ? 'number' : 'string';
27-
}
18+
const amountA = parseFloat(rowA[index].substring(1));
19+
const amountB = parseFloat(rowB[index].substring(1));
2820

29-
let itemA;
30-
let itemB;
31-
if (type === 'number') {
32-
itemA = parseInt(rowA[index], 10);
33-
} else if (type === 'currency') {
34-
itemA = parseFloat(rowA[index].substring(1));
35-
} else {
36-
itemA = rowA[index];
37-
}
38-
if (type === 'number') {
39-
itemB = parseInt(rowB[index], 10);
40-
} else if (type === 'currency') {
41-
itemB = parseFloat(rowA[index].substring(1));
42-
} else {
43-
itemB = rowA[index];
44-
}
45-
if (type === 'string') {
46-
let result;
47-
48-
if (itemA > itemB) result = 1;
49-
else if (itemB > itemA) result = -1;
50-
else result = 0;
51-
return direction === 'descending' ? result * -1 : result;
52-
}
53-
54-
return direction === 'descending' ? itemB - itemA : itemA - itemB;
21+
return direction === 'descending' ? amountB - amountA : amountA - amountB;
5522
});
5623
}
5724

@@ -111,7 +78,7 @@ export function Sortable() {
11178
const rows = sortedRows ? sortedRows : initiallySortedRows;
11279

11380
const handleSort = useCallback(
114-
(index, direction) => setSortedRows(sortRows(rows, index, direction)),
81+
(index, direction) => setSortedRows(sortCurrency(rows, index, direction)),
11582
[rows],
11683
);
11784

@@ -379,7 +346,7 @@ export function WithAllOfItsElements() {
379346

380347
const rows = sortedRows ? sortedRows : initiallySortedRows;
381348
const handleSort = useCallback(
382-
(index, direction) => setSortedRows(sortRows(rows, index, direction)),
349+
(index, direction) => setSortedRows(sortCurrency(rows, index, direction)),
383350
[rows],
384351
);
385352

@@ -477,9 +444,7 @@ export function WithColumnSpanning() {
477444
}
478445

479446
export function WithFixedColumns() {
480-
const [sortedRows, setSortedRows] = useState<any[]>();
481-
482-
const initiallySortedRows = [
447+
const rows = [
483448
[
484449
'Emerald Silk Gown',
485450
'Formalwear',
@@ -525,12 +490,6 @@ export function WithFixedColumns() {
525490
'$140.00',
526491
],
527492
];
528-
const rows = sortedRows ? sortedRows : initiallySortedRows;
529-
530-
const handleSort = useCallback(
531-
(index, direction) => setSortedRows(sortRows(rows, index, direction)),
532-
[rows],
533-
);
534493

535494
return (
536495
<Page title="Sales by product">
@@ -560,32 +519,20 @@ export function WithFixedColumns() {
560519
]}
561520
rows={rows}
562521
totals={['', '', '', '', '', '', 255, '$1399', '$155,830.00']}
563-
sortable={[
564-
false,
565-
false,
566-
false,
567-
false,
568-
true,
569-
false,
570-
false,
571-
false,
572-
true,
573-
]}
574-
defaultSortDirection="descending"
575522
initialSortColumnIndex={4}
576-
onSort={handleSort}
523+
stickyHeader
577524
fixedFirstColumns={3}
578525
truncate
526+
showTotalsInFooter
527+
footerContent={`Showing ${rows.length} of ${rows.length} results`}
579528
/>
580529
</Card>
581530
</Page>
582531
);
583532
}
584533

585534
export function WithIncreasedDensityAndZebraStriping() {
586-
const [sortedRows, setSortedRows] = useState<any[]>();
587-
588-
const initiallySortedRows = [
535+
const rows = [
589536
[
590537
<Link
591538
removeUnderline
@@ -627,12 +574,6 @@ export function WithIncreasedDensityAndZebraStriping() {
627574
],
628575
];
629576

630-
const rows = sortedRows ? sortedRows : initiallySortedRows;
631-
const handleSort = useCallback(
632-
(index, direction) => setSortedRows(sortRows(rows, index, direction)),
633-
[rows],
634-
);
635-
636577
return (
637578
<Page title="Sales by product">
638579
<Card>
@@ -653,10 +594,8 @@ export function WithIncreasedDensityAndZebraStriping() {
653594
]}
654595
rows={rows}
655596
totals={['', '', '', 255, '$155,830.00']}
656-
sortable={[false, true, false, false, true]}
657597
defaultSortDirection="descending"
658598
initialSortColumnIndex={4}
659-
onSort={handleSort}
660599
footerContent={`Showing ${rows.length} of ${rows.length} results`}
661600
hasZebraStripingOnData
662601
increasedTableDensity
@@ -667,9 +606,7 @@ export function WithIncreasedDensityAndZebraStriping() {
667606
}
668607

669608
export function WithStickyHeaderEnabled() {
670-
const [sortedRows, setSortedRows] = useState<any[]>();
671-
672-
const initiallySortedRows = [
609+
const rows = [
673610
[
674611
<Link
675612
removeUnderline
@@ -906,12 +843,6 @@ export function WithStickyHeaderEnabled() {
906843
],
907844
];
908845

909-
const rows = sortedRows ? sortedRows : initiallySortedRows;
910-
const handleSort = useCallback(
911-
(index, direction) => setSortedRows(sortRows(rows, index, direction)),
912-
[rows],
913-
);
914-
915846
return (
916847
<Page title="Sales by product">
917848
<Card>
@@ -932,10 +863,8 @@ export function WithStickyHeaderEnabled() {
932863
]}
933864
rows={rows}
934865
totals={['', '', '', 255, '$155,830.00']}
935-
sortable={[false, true, false, false, true]}
936866
defaultSortDirection="descending"
937867
initialSortColumnIndex={4}
938-
onSort={handleSort}
939868
footerContent={`Showing ${rows.length} of ${rows.length} results`}
940869
hasZebraStripingOnData
941870
increasedTableDensity

polaris-react/src/components/DataTable/DataTable.tsx

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ class DataTableInner extends PureComponent<CombinedProps, DataTableState> {
190190
if (fixedFirstColumn && process.env.NODE_ENV === 'development') {
191191
// eslint-disable-next-line no-console
192192
console.warn(
193-
'Deprecation: The `hasFixedFirstColumn` prop on the `DataTable` has been deprecated. See the v11 migration guide for replacing this prop with `fixedFirstColumns={n}`. https://github.com/Shopify/polaris/blob/main/documentation/guides/migrating-from-v10-to-v11.md',
193+
'Deprecation: The `hasFixedFirstColumn` prop on the `DataTable` has been deprecated. Use fixedFirstColumns={n} instead.',
194194
);
195195
}
196196

@@ -246,7 +246,9 @@ class DataTableInner extends PureComponent<CombinedProps, DataTableState> {
246246
!isScrolledFarthestLeft && styles.separate,
247247
)}
248248
style={{
249-
maxWidth: `${columnVisibilityData[fixedFirstColumns]?.rightEdge}px`,
249+
maxWidth: `${
250+
columnVisibilityData[fixedFirstColumns - 1]?.rightEdge
251+
}px`,
250252
}}
251253
>
252254
<thead>
@@ -311,7 +313,7 @@ class DataTableInner extends PureComponent<CombinedProps, DataTableState> {
311313
isScrolledFarthestRight={isScrolledFarthestRight}
312314
navigateTableLeft={this.navigateTable('left')}
313315
navigateTableRight={this.navigateTable('right')}
314-
fixedFirstColumn={Boolean(fixedFirstColumns)}
316+
fixedFirstColumns={fixedFirstColumns}
315317
setRef={(ref: any) => {
316318
if (location === 'header') {
317319
this.headerNav = ref;
@@ -504,10 +506,13 @@ class DataTableInner extends PureComponent<CombinedProps, DataTableState> {
504506
} = this;
505507

506508
if (condensed && table && scrollContainer && dataTable) {
507-
const headerCells = table.querySelectorAll(headerCell.selector);
509+
const headerCells = table.querySelectorAll<HTMLTableCellElement>(
510+
headerCell.selector,
511+
);
508512

513+
const rightMostHeader = headerCells[fixedFirstColumns - 1];
509514
const nthColumnWidth = fixedFirstColumns
510-
? headerCells[0].clientWidth + headerCells[1].clientWidth
515+
? rightMostHeader.offsetLeft + rightMostHeader.offsetWidth
511516
: 0;
512517

513518
if (headerCells.length > 0) {
@@ -738,18 +743,20 @@ class DataTableInner extends PureComponent<CombinedProps, DataTableState> {
738743
? this.tableHeadingWidths[headingIndex]
739744
: undefined;
740745

746+
const fixedCellVisible = !isScrolledFarthestLeft;
747+
741748
const cellProps = {
742749
header: true,
743750
stickyHeadingCell: inStickyHeader,
744751
content: heading,
745752
contentType: columnContentTypes[headingIndex],
746-
nthColumn: headingIndex <= fixedFirstColumns - 1,
753+
nthColumn: headingIndex < fixedFirstColumns,
747754
truncate,
748755
...sortableHeadingProps,
749756
verticalAlign,
750757
handleFocus: this.handleFocus,
751758
stickyCellWidth,
752-
fixedCellVisible: !isScrolledFarthestLeft,
759+
fixedCellVisible,
753760
firstColumnMinWidth,
754761
};
755762

@@ -782,6 +789,13 @@ class DataTableInner extends PureComponent<CombinedProps, DataTableState> {
782789
});
783790
}}
784791
inFixedNthColumn
792+
style={{
793+
left: this.state.columnVisibilityData[headingIndex]?.leftEdge,
794+
borderRight:
795+
headingIndex === fixedFirstColumns - 1 && fixedCellVisible
796+
? 'var(--p-border-divider)'
797+
: undefined,
798+
}}
785799
/>,
786800
];
787801
}

polaris-react/src/components/DataTable/components/Cell/Cell.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export interface CellProps {
3333
hasFixedNthColumn?: boolean;
3434
fixedCellVisible?: boolean;
3535
firstColumnMinWidth?: string;
36+
style?: React.CSSProperties;
3637
}
3738

3839
export function Cell({
@@ -59,6 +60,7 @@ export function Cell({
5960
hasFixedNthColumn = false,
6061
fixedCellVisible = false,
6162
firstColumnMinWidth,
63+
style,
6264
}: CellProps) {
6365
const i18n = useI18n();
6466
const numeric = contentType === 'numeric';
@@ -130,18 +132,22 @@ export function Cell({
130132

131133
const colSpanProp = colSpan && colSpan > 1 ? {colSpan} : {};
132134

135+
const minWidthStyles =
136+
nthColumn && firstColumnMinWidth
137+
? {minWidth: firstColumnMinWidth}
138+
: {minWidth: stickyCellWidth};
139+
133140
const stickyHeading = (
134141
<th
135142
ref={setRef}
136143
{...headerCell.props}
137144
{...colSpanProp}
138145
className={className}
139146
aria-sort={sortDirection}
140-
style={
141-
nthColumn && firstColumnMinWidth
142-
? {minWidth: firstColumnMinWidth}
143-
: {minWidth: stickyCellWidth}
144-
}
147+
style={{
148+
...style,
149+
...minWidthStyles,
150+
}}
145151
data-index-table-sticky-heading
146152
>
147153
{columnHeadingContent}

polaris-react/src/components/DataTable/components/Navigation/Navigation.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export interface NavigationProps {
1111
columnVisibilityData: ColumnVisibilityData[];
1212
isScrolledFarthestLeft?: boolean;
1313
isScrolledFarthestRight?: boolean;
14-
fixedFirstColumn?: boolean;
14+
fixedFirstColumns: number;
1515
navigateTableLeft?(): void;
1616
navigateTableRight?(): void;
1717
setRef?: (ref: HTMLDivElement | null) => void;
@@ -23,13 +23,13 @@ export function Navigation({
2323
isScrolledFarthestRight,
2424
navigateTableLeft,
2525
navigateTableRight,
26-
fixedFirstColumn,
26+
fixedFirstColumns,
2727
setRef = () => {},
2828
}: NavigationProps) {
2929
const i18n = useI18n();
3030

3131
const pipMarkup = columnVisibilityData.map((column, index) => {
32-
if (fixedFirstColumn && index === 0) return;
32+
if (index < fixedFirstColumns) return;
3333
const className = classNames(
3434
styles.Pip,
3535
column.isVisible && styles['Pip-visible'],

polaris-react/src/components/DataTable/components/Navigation/tests/Navigation.test.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ describe('<Navigation />', () => {
1414

1515
const navigation = mountWithApp(
1616
<Navigation
17+
fixedFirstColumns={0}
1718
columnVisibilityData={columnVisibilityData}
1819
isScrolledFarthestLeft
1920
isScrolledFarthestRight={false}
@@ -31,6 +32,7 @@ describe('<Navigation />', () => {
3132

3233
const navigation = mountWithApp(
3334
<Navigation
35+
fixedFirstColumns={0}
3436
columnVisibilityData={columnVisibilityData}
3537
isScrolledFarthestLeft
3638
isScrolledFarthestRight={false}
@@ -53,7 +55,7 @@ describe('<Navigation />', () => {
5355
columnVisibilityData={columnVisibilityData}
5456
isScrolledFarthestLeft
5557
isScrolledFarthestRight={false}
56-
fixedFirstColumn
58+
fixedFirstColumns={1}
5759
/>,
5860
);
5961

0 commit comments

Comments
 (0)