traceRovingTabIndex.tsx 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import {traceReducerExhaustiveActionCheck} from 'sentry/views/performance/newTraceDetails/traceState';
  2. import type {TraceTree, TraceTreeNode} from '../traceModels/traceTree';
  3. export interface TraceRovingTabIndexState {
  4. index: number | null;
  5. items: number | null;
  6. node: TraceTreeNode<TraceTree.NodeValue> | null;
  7. }
  8. export type TraceRovingTabIndexAction =
  9. | {
  10. index: number | null;
  11. items: number;
  12. node: TraceTreeNode<TraceTree.NodeValue> | null;
  13. type: 'initialize roving reducer';
  14. }
  15. | {
  16. action_source: 'click' | 'keyboard' | 'load';
  17. index: number;
  18. node: TraceTreeNode<TraceTree.NodeValue>;
  19. type: 'set roving index';
  20. }
  21. | {type: 'clear'}
  22. | {type: 'clear roving index'}
  23. | {items: number; type: 'set roving count'};
  24. export type RovingTabIndexUserActions = 'next' | 'previous' | 'last' | 'first';
  25. export function traceRovingTabIndexReducer(
  26. state: TraceRovingTabIndexState,
  27. action: TraceRovingTabIndexAction
  28. ): TraceRovingTabIndexState {
  29. switch (action.type) {
  30. case 'initialize roving reducer': {
  31. return {index: action.index, items: action.items, node: action.node};
  32. }
  33. case 'set roving count': {
  34. return {...state, items: action.items};
  35. }
  36. case 'set roving index':
  37. return {...state, node: action.node, index: action.index};
  38. case 'clear roving index':
  39. case 'clear':
  40. return {...state, index: null, node: null};
  41. default:
  42. traceReducerExhaustiveActionCheck(action);
  43. return state;
  44. }
  45. }
  46. export function getRovingIndexActionFromDOMEvent(
  47. event: React.KeyboardEvent
  48. ): RovingTabIndexUserActions | null {
  49. // @TODO it would be trivial to extend this and support
  50. // things like j/k vim-like navigation or add modifiers
  51. // so that users could jump to parent or sibling nodes.
  52. // I would need to put some thought into this, but shift+cmd+up
  53. // seems like a good candidate for jumping to parent node and
  54. // shift+cmd+down for jumping to the next sibling node.
  55. switch (event.key) {
  56. case 'ArrowDown':
  57. if (event.shiftKey) {
  58. return 'last';
  59. }
  60. return 'next';
  61. case 'ArrowUp':
  62. if (event.shiftKey) {
  63. return 'first';
  64. }
  65. return 'previous';
  66. case 'Home':
  67. return 'first';
  68. case 'End':
  69. return 'last';
  70. case 'Tab':
  71. if (event.shiftKey) {
  72. return 'previous';
  73. }
  74. return 'next';
  75. default:
  76. return null;
  77. }
  78. }