[kbn-grid-layout][dashboard] Basic keyboard interaction (#208286)

## Summary
Adds keyboard navigation for drag-and-drop interactions
Fixes https://github.com/elastic/kibana/issues/211925
Fixes https://github.com/elastic/kibana/issues/190448

### Supported features 
1. Resize panels


https://github.com/user-attachments/assets/ba7add16-a0c6-4f15-9f3b-0f8ef7caf8ac

2. Drag panels within the same section (dragging between sections is
pending)


https://github.com/user-attachments/assets/a1fd80af-63ca-4fa2-bded-3db9968a8366

3. Move rows up/down


https://github.com/user-attachments/assets/8d7e8d7d-b1bf-4abe-9cc2-28eeea9b43f8

### Interaction Flow

1. Start interaction with `Space` or `Enter`
2. Move using arrow keys
3. Finish by confirming (`Enter`/`Space`) or canceling (`Escape`)
(blurring also confirms the changes)

### Scrolling Behavior:
* Default browser scrolling is disabled in interaction mode to avoid
unexpected behavior and edge cases that would overcomplicate this simple
implementation.
* Scrolling occurs when the user reaches the edge of the screen while
resizing or dragging, allowing them to continue the interaction
smoothly.
* When the operation is confirmed, we also scroll to the element to make
sure it's in view.

### Missing (planned for another PR):
* A11y announcements 
* Dragging between sections
* This feature is not well unit-tested, but it's very difficult to do it
without mocking the crucial pieces of functionality. I'd vote to leave
it for now and add a few functional tests once we decide a strategy for
it, since drag and drop interactions are anyway quite difficult to
unit-test reliably anyway.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Marta Bondyra 2025-04-01 11:29:02 +02:00 committed by GitHub
parent 8767adc622
commit f5b185a28f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 835 additions and 241 deletions

View file

@ -50,6 +50,7 @@ import { dashboardInputToGridLayout, gridLayoutToDashboardPanelMap } from './uti
const DASHBOARD_MARGIN_SIZE = 8;
const DASHBOARD_GRID_HEIGHT = 20;
const DASHBOARD_GRID_COLUMN_COUNT = 48;
const DASHBOARD_DRAG_TOP_OFFSET = 150;
export const GridExample = ({
coreStart,
@ -67,6 +68,7 @@ export const GridExample = ({
gutterSize: DASHBOARD_MARGIN_SIZE,
rowHeight: DASHBOARD_GRID_HEIGHT,
columnCount: DASHBOARD_GRID_COLUMN_COUNT,
keyboardDragTopLimit: DASHBOARD_DRAG_TOP_OFFSET,
});
const mockDashboardApi = useMockDashboardApi({ savedState: savedState.current });