-
Notifications
You must be signed in to change notification settings - Fork 829
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
[EuiDataGrid] Implement draggable column headers #8015
base: main
Are you sure you want to change the base?
[EuiDataGrid] Implement draggable column headers #8015
Conversation
@@ -110,6 +115,8 @@ export const EuiDraggable: FunctionComponent<EuiDraggableProps> = ({ | |||
role={ | |||
hasInteractiveChildren | |||
? 'group' | |||
: customDragHandle === 'custom' |
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.
The idea here is to provide means to unset the role
for specific use cases. Using customDragHandle=true
for that would have impact on current usages, hence I'm suggesting to add a third custom option as this should not be a default.
The reasoning here is this:
EuiDraggable adds a drag wrapper around its content, which has role="button|group"
- this works for most cases where the drag element should be the interactive/focused element. The impact of this is, that the content of this element is not read as standalone semantic elements. E.g. role="button"
removes additional semantic content and just reads visible text content.
For datagrid column headers we rather want the columnheader
to still be the element to be read via screen readers as it holds all semantic information. Instead we want the draggable accessible information added to the column header instead of the wrapper being read only.
To ensure the columnheader
role element is read, the draggable wrapper needs to have no role that removes the content semantics. Hence the decision to provide means to unset it for this case.
9e23fdd
to
2ccfb4d
Compare
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 VRT images updates are related to this change which means the "Account" title now sits flush within the header cell padding instead of 2px offset due to the gap (which applied because the action elements are only visually hidden but available in the DOM)
packages/eui/src-docs/src/views/datagrid/schema_columns/column_dragging.js
Outdated
Show resolved
Hide resolved
packages/eui/src/components/datagrid/body/header/data_grid_header_cell.styles.ts
Outdated
Show resolved
Hide resolved
packages/eui/src/components/datagrid/body/header/data_grid_header_cell.styles.ts
Outdated
Show resolved
Hide resolved
packages/eui/src/components/datagrid/body/header/data_grid_header_row.styles.ts
Show resolved
Hide resolved
packages/eui/src/components/datagrid/body/header/data_grid_header_row.tsx
Outdated
Show resolved
Hide resolved
packages/eui/src/components/datagrid/body/header/data_grid_header_cell.tsx
Outdated
Show resolved
Hide resolved
// Draggable prevents FocusTrap onOutsideClick to be called. | ||
// We manually close the popover for draggable cells and | ||
// update the focus index onBlur to ensure execution order | ||
// as closePopover() focuses its own cells first on close. |
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 need to run for today but I'm planning on coming back to this file and doing a closer review tomorrow (also delaying because I'm guessing this might change significantly if we need to support #8015 (comment)).
Just curious, do we know exactly why the draggable library interferes with our existing click events?
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.
Interactive children work as expected with the draggable header columns (example story).
The general problem is that clicking the draggable column will click the draggable wrapper (and does not receive focus), not the column header. And somewhere the focus is caught, because the focus
listener on the header cell that handles the focus context does not trigger.
This starts happening as soon as the provided.draggableProps
are added. I did not find the root cause in code so far. 🤔
141c294
to
deceb15
Compare
- draggable cells prevent onOutsideClick to be triggered, we need to manually update focus to ensure expected behavior - moves columnResizer element to ensure drag and resize actions stay separate
- add columnDragDrop control to custom ehader story for testing with interactive headers
- ensures the columnheader element is read instead of the wrapping draggable container; this requires the draggable wrapper to not have a role as the default roles button/group remove any semantics from their content when focused which results in the content not fully being read
- this reparenting approach is required due to transform context of datagrid which interfers with the positioning of dragged items
- use unique ids - remove position style override as it's not needed for the reparented/portalled approach
- the changes are only related to the conditionally added gap on header cells
- prevents error about not finishing drop animation as there were duplicate elements being dragged
- prevents duplicate SR output in entering the cell
…e elements - ensure we use the rowing tabindex and don't add additional unwanted tab stops
- includes column header with interactive cell content
- moving dragged item into the body scope to prevent issues due to stacked context. this requires applying styles to the dragged item manually as it's not part of the datagrid style scope - added some smaller cleanups to ensure correct styles
b428995
to
45ec4e5
Compare
💚 Build Succeeded
History
|
Summary
closes #7136
This PR implements reordering
EuiDataGrid
columns via draggable column headers.This implementation is opt-in keeping parity with current usages.
Todo
EuiDataGrid
Emotion conversionadd docs update to EUI+ docs (DataGrid content is not yet available, EUI+ is still in need to be fully migrated/released)Changes
canDragAndDropColumns
oncolumnVisibility
prop ofEuiDataGrid
to toggle draggable column headers - default value isfalse
EuiDragDropContext
andEuiDroppable
inEuiGridHeaderRow
to enable a drop zone for all non-control columnsEuiDraggable
inEuiDataGridHeaderCell
to enable draggable column headersposition: fixed
element inside a transform contextcustomDragHandle
prop value onEuiDraggable
to beboolean | 'custom'
Accessibility
The
Draggable
implementation comes with great accessibility out of the box (adding hints and announcements where needed) BUT for the use case of datagrid headers it was not completely fitting and needed a small adjustment.The expected behavior is, that focussing a column header, we want the
columnheader
role to be read with all its expected labels and attached descriptions.EuiDraggable
currently always added a role on the drag container (button
orgroup
) which will be read instead of the content (effectively losing us semantic information). To solve this we optionally remove the added role on the drag container, which results in the content being read on focus as wanted.This was tested and optimized on Win11 for JAWS and NVDA.
Screen reader output
Screenshots
mouse usage
Screen.Recording.2024-09-10.at.18.01.57.mov
keyboard usage
Screen.Recording.2024-09-10.at.18.05.00.mov
resizing
Screen.Recording.2024-09-10.at.18.06.38.mov
QA
Storybook: https://eui.elastic.co/pr_8015/storybook/?path=/story/tabular-content-euidatagrid--playground&args=columnDragDrop:!true
EUI docs: https://eui.elastic.co/pr_8015/index.html#/tabular-content/data-grid-schema-columns#draggable-columns
columnDragDrop
prop works to en/disable draggable columnsGeneral checklist
Checked in both light and dark modes@default
if default values are missing) and playground togglesChecked Code Sandbox works for any docs examplesIf applicable, added the breaking change issue label (and filled out the breaking change checklist)If applicable, file an issue to update EUI's Figma library with any corresponding UI changes. (This is an internal repo, if you are external to Elastic, ask a maintainer to submit this request)