diff --git a/src/renderer/App.css b/src/renderer/App.css
index 4e4e321..5da4c9c 100644
--- a/src/renderer/App.css
+++ b/src/renderer/App.css
@@ -7,11 +7,14 @@ body {
flex-direction: row;
}
.App-modal-container {
+ position: fixed;
+ top: 0;
+ left: 0;
width: 100%;
height: 100%;
- position: fixed;
- background-color: rgb(0 0 0 / 80%);
+ background-color: rgb(0 0 0 / 50%);
display: none;
+ z-index: 4;
}
.App-modal-container:has(.modal-active) {
display: block;
diff --git a/src/renderer/ConnectionConfig.tsx b/src/renderer/ConnectionConfig.tsx
index cd5ab93..65bd17e 100644
--- a/src/renderer/ConnectionConfig.tsx
+++ b/src/renderer/ConnectionConfig.tsx
@@ -1,8 +1,17 @@
+import { useDispatch } from 'react-redux';
+import { modalActions, Modals } from './store/modalSlice';
+
/**
* Button component that opens the ConnectionConfigModal.
*/
export default function ConnectionConfig() {
+ const dispatch = useDispatch();
return (
-
+
+
+
);
}
diff --git a/src/renderer/ResizeBar.css b/src/renderer/ResizeBar.css
index fed8f05..c7e4cee 100644
--- a/src/renderer/ResizeBar.css
+++ b/src/renderer/ResizeBar.css
@@ -1,5 +1,5 @@
.ResizeBar {
- background-color: black;
+ background-color: gray;
width: 5px;
cursor: col-resize;
}
diff --git a/src/renderer/ResizeBar.tsx b/src/renderer/ResizeBar.tsx
index 129432e..69fbd00 100644
--- a/src/renderer/ResizeBar.tsx
+++ b/src/renderer/ResizeBar.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { editorActions } from './store/editorSlice';
-import { State } from './store/store';
+import type { State } from './store/store';
import './ResizeBar.css'
/**
diff --git a/src/renderer/index.tsx b/src/renderer/index.tsx
index 99880e7..e72424d 100644
--- a/src/renderer/index.tsx
+++ b/src/renderer/index.tsx
@@ -7,6 +7,6 @@ const root = createRoot(container);
root.render();
window.electron.ipcRenderer.on('renderer-store-dispatch', (action) => {
- console.log('renderer store dispatch');
+ //console.log('renderer store dispatch');
store.dispatch(action);
});
diff --git a/src/renderer/modals/ConnectionInfoModal.tsx b/src/renderer/modals/ConnectionInfoModal.tsx
index 1d8584f..a99e3ba 100644
--- a/src/renderer/modals/ConnectionInfoModal.tsx
+++ b/src/renderer/modals/ConnectionInfoModal.tsx
@@ -1,8 +1,13 @@
+import Modal from './Modal';
+import { Modals } from '../store/modalSlice';
+
/**
* Modal component exposing info about the connection to the robot (IP address, port, etc.)
*/
export default function ConnectionInfoModal() {
return (
- Connection info modal
+
+ Test
+
);
}
diff --git a/src/renderer/modals/GamepadInfoModal.tsx b/src/renderer/modals/GamepadInfoModal.tsx
index bd6677d..dbf7b5e 100644
--- a/src/renderer/modals/GamepadInfoModal.tsx
+++ b/src/renderer/modals/GamepadInfoModal.tsx
@@ -1,8 +1,13 @@
+import { Modals } from '../store/modalSlice';
+import Modal from './Modal';
+
/**
* Modal component displaying info about a connected gamepad.
*/
export default function GamepadInfoModal() {
return (
- Gamepad info modal
+
+ Test
+
);
}
diff --git a/src/renderer/modals/Modal.css b/src/renderer/modals/Modal.css
new file mode 100644
index 0000000..04560f7
--- /dev/null
+++ b/src/renderer/modals/Modal.css
@@ -0,0 +1,28 @@
+.Modal {
+ display: none;
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ background-color: white;
+ border-radius: 5px;
+}
+.modal-active {
+ display: block;
+}
+.Modal-title-bar {
+ white-space: nowrap;
+ padding: 20px;
+ background-color: blue;
+ border-radius: inherit;
+}
+.Modal-title {
+ padding-right: 20vw;
+}
+.Modal-close-button {
+ background-color: transparent;
+ border: none;
+}
+.Modal-content {
+ padding: 20px;
+}
diff --git a/src/renderer/modals/Modal.tsx b/src/renderer/modals/Modal.tsx
new file mode 100644
index 0000000..480ce94
--- /dev/null
+++ b/src/renderer/modals/Modal.tsx
@@ -0,0 +1,28 @@
+import { useSelector, useDispatch } from 'react-redux';
+import { modalActions, Modals } from '../store/modalSlice';
+import type { State } from '../store/store';
+import './Modal.css';
+
+/**
+ * Generic modal component.
+ */
+export default function Modal({ modalType, modalTitle, children }) {
+ const isActive = useSelector((state: State) => state.modal.activeModal === modalType);
+ const dispatch = useDispatch();
+ return (
+
+
+
+ {modalTitle}
+
+
+
+
+ {children}
+
+
+ );
+}
diff --git a/src/renderer/store/modalSlice.tsx b/src/renderer/store/modalSlice.tsx
new file mode 100644
index 0000000..7afe39e
--- /dev/null
+++ b/src/renderer/store/modalSlice.tsx
@@ -0,0 +1,27 @@
+import { createSlice } from '@reduxjs/toolkit';
+
+export enum Modals {
+ None,
+ ConnectionConfig,
+ GamepadInfo
+}
+const initialState = {
+ activeModal: Modals.None
+};
+export const modalSlice = createSlice({
+ name: 'modal',
+ initialState: initialState,
+ reducers: {
+ /**
+ * Sets the currently active modal.
+ */
+ setActive: (state, { payload }) => {
+ console.log('set active to ' + payload.toString());
+ state.activeModal = payload;
+ }
+ }
+});
+
+export const modalActions = modalSlice.actions;
+export type ModalState = typeof initialState;
+export default modalSlice.reducer;
diff --git a/src/renderer/store/store.tsx b/src/renderer/store/store.tsx
index 4d74015..03587f5 100644
--- a/src/renderer/store/store.tsx
+++ b/src/renderer/store/store.tsx
@@ -1,14 +1,17 @@
import { configureStore } from '@reduxjs/toolkit';
import robotInfoReducer, { RobotInfoState } from './robotInfoSlice';
import editorReducer, { EditorState } from './editorSlice';
+import modalReducer, { ModalState } from './modalSlice';
export interface State {
robotInfo: RobotInfoState,
- editor: EditorState
+ editor: EditorState,
+ modal: ModalState
}
export default configureStore({
reducer: {
robotInfo: robotInfoReducer,
- editor: editorReducer
+ editor: editorReducer,
+ modal: modalReducer
}
});