Conway's Game of Life as a React web app
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Controls.tsx 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import React, { useEffect } from 'react';
  2. interface Props {
  3. running: boolean;
  4. speed: number;
  5. width: number;
  6. height: number;
  7. reset: () => void;
  8. toggle: () => void;
  9. download: () => void;
  10. updateCellSize: (f: (size: number) => number) => void;
  11. updateDimensions: (dimensions: { width?: number; height?: number }) => void;
  12. updateSpeed: (speed: number) => void;
  13. upload: () => void;
  14. }
  15. const Controls = (props: Props) => {
  16. const {
  17. running,
  18. speed,
  19. toggle,
  20. updateSpeed,
  21. width,
  22. height,
  23. reset,
  24. updateCellSize,
  25. updateDimensions,
  26. download,
  27. upload,
  28. } = props;
  29. const goSlower = () => {
  30. updateSpeed(speed + 100);
  31. };
  32. const goFaster = () => {
  33. if (speed > 100) {
  34. updateSpeed(speed - 100);
  35. }
  36. };
  37. const getSmaller = () => {
  38. updateCellSize((size) => size - 1);
  39. };
  40. const getBigger = () => {
  41. updateCellSize((size) => size + 1);
  42. };
  43. useEffect(() => {
  44. document.addEventListener('keyup', (e) => {
  45. if (e.key === ' ') {
  46. toggle();
  47. }
  48. });
  49. }, [toggle]);
  50. return (
  51. <div className="controls">
  52. <div className="controls__section dimensions">
  53. <label>
  54. Width{' '}
  55. <input
  56. className="number-field"
  57. type="number"
  58. value={width}
  59. onChange={(e) =>
  60. updateDimensions({ width: parseInt(e.currentTarget.value, 10) })
  61. }
  62. />
  63. </label>
  64. <label>
  65. Height{' '}
  66. <input
  67. className="number-field"
  68. type="number"
  69. value={height}
  70. onChange={(e) =>
  71. updateDimensions({ height: parseInt(e.currentTarget.value, 10) })
  72. }
  73. />
  74. </label>
  75. </div>
  76. <div className="controls__section speed">
  77. <button className="button" onClick={goSlower}>
  78. Slower
  79. </button>
  80. <button className="button" disabled={speed <= 100} onClick={goFaster}>
  81. Faster
  82. </button>
  83. </div>
  84. <div className="controls__section size">
  85. <button className="button" onClick={getSmaller}>
  86. Smaller
  87. </button>
  88. <button className="button" onClick={getBigger}>
  89. Bigger
  90. </button>
  91. </div>
  92. <div className="controls__section import-export">
  93. <div className="upload">
  94. <button className="button" onClick={upload}>
  95. Import
  96. </button>
  97. </div>
  98. <div className="download">
  99. <button className="button" onClick={download}>
  100. Export
  101. </button>
  102. </div>
  103. </div>
  104. <div className="controls__section play-reset">
  105. <div className="reset">
  106. <button className="button" onClick={reset}>
  107. Reset
  108. </button>
  109. </div>
  110. <div className="play">
  111. <button className="button" onClick={toggle}>
  112. {running ? 'Pause' : 'Play'}
  113. </button>
  114. </div>
  115. </div>
  116. </div>
  117. );
  118. };
  119. export default Controls;