-
-
Notifications
You must be signed in to change notification settings - Fork 72
Issue 649 - Fix mismatched row height for fixed columns #722
Conversation
'console.log("logging things")', | ||
'console.warn("this is a markdown cell")' | ||
] | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changing the mock to have variable height Markdown rows
@@ -48,6 +48,9 @@ const INNER_STYLE = { | |||
minWidth: '100%' | |||
}; | |||
|
|||
const WIDTH_EPSILON = 0.5; | |||
const MAX_WIDTH_ITERATIONS = 30; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
30 is a very high number but most of the time it takes 2-6 iterations for the table's column width to settle.
@@ -146,7 +149,7 @@ export default class ControlledTable extends PureComponent<ControlledTableProps> | |||
|
|||
componentDidUpdate() { | |||
this.updateStylesheet(); | |||
this.applyStyle(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
applyStyle
is removed / replaced by new code to handle the fixed rows
r0c1.style.marginLeft = `-${width2}`; | ||
r0c1.style.marginRight = `${width2}`; | ||
r1c1.style.marginLeft = `-${width2}`; | ||
r1c1.style.marginRight = `${width2}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there are fixed columns, align the cell's table in such a way as to make the first visible column left-aligned with the cell.
@@ -718,7 +700,10 @@ export default class ControlledTable extends PureComponent<ControlledTableProps> | |||
const { r0c1 } = this.refs as { [key: string]: HTMLElement }; | |||
|
|||
Logger.trace(`ControlledTable fragment scrolled to (left,top)=(${ev.target.scrollLeft},${ev.target.scrollTop})`); | |||
r0c1.style.marginLeft = `${-ev.target.scrollLeft}px`; | |||
|
|||
const margin = parseFloat(ev.target.scrollLeft) + parseFloat(getComputedStyle(r0c1).marginRight); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
margin-left
and margin-right
match in dimension, if not sign. Scroll adds to the initial offset.
columnId, | ||
isValid, | ||
style, | ||
value | ||
} = this.props; | ||
|
||
return (<th | ||
className={classes + (isValid ? '' : ' invalid')} | ||
className={className + (isValid ? '' : ' invalid')} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Standardizing prop name across all components simplifies manipulation elsewhere.
color: graytext | ||
} | ||
} | ||
display: inline-block; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation here was all weirded out - fixed. Lots of noise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like some got fixed and some other parts got mucked up. Mostly lines 507+ but there are a few before that that look weird as well. Is there an auto-formatter for .less
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OIC you have some hard tabs mixed in with spaces here - this file looks funny in #728 as well as a result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll double check to make sure this file has been cleaned up.. but yes, at some point it became a mix of tabs/spaces
const getFirstPhantom = (cell: JSX.Element) => React.cloneElement(cell, { | ||
...cell.props, | ||
style: { ...cell.props.style, borderLeft: 'transparent' } | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Various component cloning / manipulations.
getHiddenCell
makes a phantom version of a cell - will be invisible
getFirstPhantom
solves a doubled border issue
@@ -25,27 +25,35 @@ export class DashTableHelper { | |||
} | |||
|
|||
public getCell(row: number, column: number, editable: State = State.Ready) { | |||
return cy.get(`#${this.id} ${getSelector(editable)} tbody tr td.column-${column}`).eq(row); | |||
return cy.get(`#${this.id} ${getSelector(editable)} tbody tr td.column-${column}:not(.phantom-cell)`).eq(row); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update test helper to ignore phantom cells
]} | ||
columns={columnFormats} | ||
/>)) | ||
const variants: ITest[] = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Markdown visual tests with both fixed an no fixed columns
style_data_conditional={[{ | ||
if: { column_id: 'Region' }, | ||
whiteSpace: 'normal' | ||
}]} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the standard prop to do this
|
||
Array.from<HTMLElement>( | ||
r0c1.querySelectorAll('table.cell-table > tbody > tr:last-of-type > *') | ||
).forEach((c, i) => this.setCellWidth(c, r1c1CellWidths[i])); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All this replaces and adds to the previous applyStyle
method
) { | ||
break; | ||
} | ||
} while (true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a big deal, but given that ultimately there's a known limit (MAX_WIDTH_ITERATIONS
) I'd have probably written this as a for
loop, with only the width test down here breaking the loop early.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Want to keep both exit conditions together, that's why I opted for a while
instead of a for
loop. Did some clean up so the exit condition is now in the while
condition instead of the body. 207c90a
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also removed the it % 2 == 0
check which is no longer necessary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, makes sense. Glad the it % 2 === 0
can be avoided!
@@ -1,6 +1,7 @@ | |||
import * as R from 'ramda'; | |||
import React from 'react'; | |||
import { memoizeOneFactory } from 'core/memoizer'; | |||
import isNil from 'ramda/es/isNil'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just the one in import * as R from 'ramda';
above? In fact you use both copies...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Weird.. fixed with 33db6f3
}, | ||
{ cells: 0, count: 0 }, | ||
row as any | ||
).cells; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🌴const pivot = ...
looks identical to above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🌴 3d0b8c8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Just a few small comments, then this is ready to go! 💃
…able into 649-mismatched-row-heights
Closes #649
This PR proposes to fix the misaligned rows issue by adding invisible cells in both the fixed columns and unfixed columns sections of the table. With some tweaks, this allows both fixed and unfixed cells to calculate their size based on the entire table's content, making sure that both size have the same size/height.
Afterwards the fixed rows can be coerced into having the correct width. With some extra tweaks for Firefox.
Percy browser versions have been updated for both
dash-table
anddash-table-python-v0
in order for the snapshots to match local behavior.A lot of the changes in the PR is fixing the test logic to handle the added
phantom-cell
.Current implementation slows down rendering for fixed table significantly (about 2.5x slower) but is significantly better than previous attempts (about 10-20x slower). Still investigating what can be done to reduce the overhead.
Possible secondary strategies:
page_size
from 250 to 100 would provide significant performance mitigation for default usage while not impacting usability significantly.