RuntimeErrorFooter.js 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. const theme = require('../theme');
  2. const Spacer = require('./Spacer');
  3. /**
  4. * @typedef {Object} RuntimeErrorFooterProps
  5. * @property {string} [initialFocus]
  6. * @property {boolean} multiple
  7. * @property {function(MouseEvent): void} onClickCloseButton
  8. * @property {function(MouseEvent): void} onClickNextButton
  9. * @property {function(MouseEvent): void} onClickPrevButton
  10. */
  11. /**
  12. * A fixed footer that handles pagination of runtime errors.
  13. * @param {Document} document
  14. * @param {HTMLElement} root
  15. * @param {RuntimeErrorFooterProps} props
  16. * @returns {void}
  17. */
  18. function RuntimeErrorFooter(document, root, props) {
  19. const footer = document.createElement('div');
  20. footer.style.backgroundColor = '#' + theme.dimgrey;
  21. footer.style.bottom = '0';
  22. footer.style.boxShadow = '0 -1px 4px rgba(0, 0, 0, 0.3)';
  23. footer.style.height = '2.5rem';
  24. footer.style.left = '0';
  25. footer.style.lineHeight = '2.5rem';
  26. footer.style.position = 'fixed';
  27. footer.style.textAlign = 'center';
  28. footer.style.width = '100vw';
  29. footer.style.zIndex = '2';
  30. const BUTTON_CONFIGS = {
  31. prev: {
  32. id: 'prev',
  33. label: '◀ Prev',
  34. onClick: props.onClickPrevButton,
  35. },
  36. close: {
  37. id: 'close',
  38. label: '× Close',
  39. onClick: props.onClickCloseButton,
  40. },
  41. next: {
  42. id: 'next',
  43. label: 'Next ▶',
  44. onClick: props.onClickNextButton,
  45. },
  46. };
  47. let buttons = [BUTTON_CONFIGS.close];
  48. if (props.multiple) {
  49. buttons = [BUTTON_CONFIGS.prev, BUTTON_CONFIGS.close, BUTTON_CONFIGS.next];
  50. }
  51. /** @type {HTMLButtonElement | undefined} */
  52. let initialFocusButton;
  53. for (let i = 0; i < buttons.length; i += 1) {
  54. const buttonConfig = buttons[i];
  55. const button = document.createElement('button');
  56. button.id = buttonConfig.id;
  57. button.innerHTML = buttonConfig.label;
  58. button.tabIndex = 1;
  59. button.style.backgroundColor = '#' + theme.dimgrey;
  60. button.style.border = 'none';
  61. button.style.color = '#' + theme.white;
  62. button.style.cursor = 'pointer';
  63. button.style.fontSize = 'inherit';
  64. button.style.height = '100%';
  65. button.style.padding = '0.5rem 0.75rem';
  66. button.style.width = (100 / buttons.length).toString(10) + '%';
  67. button.addEventListener('click', buttonConfig.onClick);
  68. if (buttonConfig.id === props.initialFocus) {
  69. initialFocusButton = button;
  70. }
  71. footer.appendChild(button);
  72. }
  73. root.appendChild(footer);
  74. Spacer(document, root, { space: '2.5rem' });
  75. if (initialFocusButton) {
  76. initialFocusButton.focus();
  77. }
  78. }
  79. module.exports = RuntimeErrorFooter;