+
+
+
+ Click on cells to select them. Once all cells are selected, they will be unselected one by
+ one in the reverse order they were selected.
+
+
+
+ {Array.from({ length: gridSize }, (_, row) =>
+ Array.from({ length: gridSize }, (_, col) => {
+ const isSelected = selections.some((s) => s[0] === row && s[1] === col);
+ return (
+
+ );
+ })
+ )}
+
+
+ );
+}
+
+export default App;
diff --git a/apps/react/src/challenges/grid-lights/styles.module.scss b/apps/react/src/challenges/grid-lights/styles.module.scss
new file mode 100644
index 000000000..371bfbcae
--- /dev/null
+++ b/apps/react/src/challenges/grid-lights/styles.module.scss
@@ -0,0 +1,24 @@
+:root {
+ --size: min(90vw, 100vh - 10rem);
+ --grid-size: 3;
+}
+
+.wrapper {
+ text-align: center;
+}
+
+.grid {
+ display: inline-grid;
+ grid-template-columns: repeat(var(--grid-size), 1fr);
+ width: var(--size);
+ gap: calc(var(--size) / 20);
+
+ button {
+ border: 1px solid #000;
+ aspect-ratio: 1;
+ }
+}
+
+.selected {
+ background-color: green;
+}
diff --git a/apps/react/src/challenges/timeline/App.jsx b/apps/react/src/challenges/timeline/App.jsx
deleted file mode 100644
index 60f75b974..000000000
--- a/apps/react/src/challenges/timeline/App.jsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import React from 'react';
-import styles from './timeline.module.css';
-import TimelineData from './data';
-
-const App = () => {
- return (
- <>
-