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 } });