diff --git a/src/components/layout/Layout.tsx b/src/components/layout/Layout.tsx index 083ac93..84603c5 100644 --- a/src/components/layout/Layout.tsx +++ b/src/components/layout/Layout.tsx @@ -4,6 +4,7 @@ import { Container, Content, Footer } from 'rsuite'; import classNames from 'classnames'; import Sidebar from './Sidebar'; import '../../styles/Layout.global.css'; +import Titlebar from './Titlebar'; const Layout = ({ footer, children }: any) => { const [expandSidebar, setExpandSidebar] = useState(true); @@ -50,6 +51,7 @@ const Layout = ({ footer, children }: any) => { return ( <> + { + return ( +
+
+
+ {document.title} +
+
+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+
+
+ ); +}; + +export default Titlebar; diff --git a/src/icons/close-k-10.png b/src/icons/close-k-10.png new file mode 100644 index 0000000..7b66b18 Binary files /dev/null and b/src/icons/close-k-10.png differ diff --git a/src/icons/close-k-12.png b/src/icons/close-k-12.png new file mode 100644 index 0000000..eab40e3 Binary files /dev/null and b/src/icons/close-k-12.png differ diff --git a/src/icons/close-k-15.png b/src/icons/close-k-15.png new file mode 100644 index 0000000..0dda080 Binary files /dev/null and b/src/icons/close-k-15.png differ diff --git a/src/icons/close-k-20.png b/src/icons/close-k-20.png new file mode 100644 index 0000000..c6e9b4d Binary files /dev/null and b/src/icons/close-k-20.png differ diff --git a/src/icons/close-k-24.png b/src/icons/close-k-24.png new file mode 100644 index 0000000..85b7e30 Binary files /dev/null and b/src/icons/close-k-24.png differ diff --git a/src/icons/close-k-30.png b/src/icons/close-k-30.png new file mode 100644 index 0000000..1b3f71f Binary files /dev/null and b/src/icons/close-k-30.png differ diff --git a/src/icons/close-w-10.png b/src/icons/close-w-10.png new file mode 100644 index 0000000..b6c1065 Binary files /dev/null and b/src/icons/close-w-10.png differ diff --git a/src/icons/close-w-12.png b/src/icons/close-w-12.png new file mode 100644 index 0000000..e2fd6d8 Binary files /dev/null and b/src/icons/close-w-12.png differ diff --git a/src/icons/close-w-15.png b/src/icons/close-w-15.png new file mode 100644 index 0000000..c4ba984 Binary files /dev/null and b/src/icons/close-w-15.png differ diff --git a/src/icons/close-w-20.png b/src/icons/close-w-20.png new file mode 100644 index 0000000..38ae255 Binary files /dev/null and b/src/icons/close-w-20.png differ diff --git a/src/icons/close-w-24.png b/src/icons/close-w-24.png new file mode 100644 index 0000000..b46d29b Binary files /dev/null and b/src/icons/close-w-24.png differ diff --git a/src/icons/close-w-30.png b/src/icons/close-w-30.png new file mode 100644 index 0000000..537a77a Binary files /dev/null and b/src/icons/close-w-30.png differ diff --git a/src/icons/max-k-10.png b/src/icons/max-k-10.png new file mode 100644 index 0000000..4a49928 Binary files /dev/null and b/src/icons/max-k-10.png differ diff --git a/src/icons/max-k-12.png b/src/icons/max-k-12.png new file mode 100644 index 0000000..4d9083a Binary files /dev/null and b/src/icons/max-k-12.png differ diff --git a/src/icons/max-k-15.png b/src/icons/max-k-15.png new file mode 100644 index 0000000..a21d97b Binary files /dev/null and b/src/icons/max-k-15.png differ diff --git a/src/icons/max-k-20.png b/src/icons/max-k-20.png new file mode 100644 index 0000000..de7c12b Binary files /dev/null and b/src/icons/max-k-20.png differ diff --git a/src/icons/max-k-24.png b/src/icons/max-k-24.png new file mode 100644 index 0000000..2a7bce0 Binary files /dev/null and b/src/icons/max-k-24.png differ diff --git a/src/icons/max-k-30.png b/src/icons/max-k-30.png new file mode 100644 index 0000000..152d64e Binary files /dev/null and b/src/icons/max-k-30.png differ diff --git a/src/icons/max-w-10.png b/src/icons/max-w-10.png new file mode 100644 index 0000000..edb4249 Binary files /dev/null and b/src/icons/max-w-10.png differ diff --git a/src/icons/max-w-12.png b/src/icons/max-w-12.png new file mode 100644 index 0000000..9e5f11b Binary files /dev/null and b/src/icons/max-w-12.png differ diff --git a/src/icons/max-w-15.png b/src/icons/max-w-15.png new file mode 100644 index 0000000..5bedda1 Binary files /dev/null and b/src/icons/max-w-15.png differ diff --git a/src/icons/max-w-20.png b/src/icons/max-w-20.png new file mode 100644 index 0000000..6d2e90f Binary files /dev/null and b/src/icons/max-w-20.png differ diff --git a/src/icons/max-w-24.png b/src/icons/max-w-24.png new file mode 100644 index 0000000..fc7fd86 Binary files /dev/null and b/src/icons/max-w-24.png differ diff --git a/src/icons/max-w-30.png b/src/icons/max-w-30.png new file mode 100644 index 0000000..ee1564b Binary files /dev/null and b/src/icons/max-w-30.png differ diff --git a/src/icons/min-k-10.png b/src/icons/min-k-10.png new file mode 100644 index 0000000..07cf311 Binary files /dev/null and b/src/icons/min-k-10.png differ diff --git a/src/icons/min-k-12.png b/src/icons/min-k-12.png new file mode 100644 index 0000000..18576e9 Binary files /dev/null and b/src/icons/min-k-12.png differ diff --git a/src/icons/min-k-15.png b/src/icons/min-k-15.png new file mode 100644 index 0000000..2a91974 Binary files /dev/null and b/src/icons/min-k-15.png differ diff --git a/src/icons/min-k-20.png b/src/icons/min-k-20.png new file mode 100644 index 0000000..67f07c8 Binary files /dev/null and b/src/icons/min-k-20.png differ diff --git a/src/icons/min-k-24.png b/src/icons/min-k-24.png new file mode 100644 index 0000000..1cf594f Binary files /dev/null and b/src/icons/min-k-24.png differ diff --git a/src/icons/min-k-30.png b/src/icons/min-k-30.png new file mode 100644 index 0000000..1e34ece Binary files /dev/null and b/src/icons/min-k-30.png differ diff --git a/src/icons/min-w-10.png b/src/icons/min-w-10.png new file mode 100644 index 0000000..3eba9a9 Binary files /dev/null and b/src/icons/min-w-10.png differ diff --git a/src/icons/min-w-12.png b/src/icons/min-w-12.png new file mode 100644 index 0000000..8a44fcb Binary files /dev/null and b/src/icons/min-w-12.png differ diff --git a/src/icons/min-w-15.png b/src/icons/min-w-15.png new file mode 100644 index 0000000..a66c5e3 Binary files /dev/null and b/src/icons/min-w-15.png differ diff --git a/src/icons/min-w-20.png b/src/icons/min-w-20.png new file mode 100644 index 0000000..bcc649d Binary files /dev/null and b/src/icons/min-w-20.png differ diff --git a/src/icons/min-w-24.png b/src/icons/min-w-24.png new file mode 100644 index 0000000..d409438 Binary files /dev/null and b/src/icons/min-w-24.png differ diff --git a/src/icons/min-w-30.png b/src/icons/min-w-30.png new file mode 100644 index 0000000..c9a060d Binary files /dev/null and b/src/icons/min-w-30.png differ diff --git a/src/icons/restore-k-10.png b/src/icons/restore-k-10.png new file mode 100644 index 0000000..ae449ae Binary files /dev/null and b/src/icons/restore-k-10.png differ diff --git a/src/icons/restore-k-12.png b/src/icons/restore-k-12.png new file mode 100644 index 0000000..a612a52 Binary files /dev/null and b/src/icons/restore-k-12.png differ diff --git a/src/icons/restore-k-15.png b/src/icons/restore-k-15.png new file mode 100644 index 0000000..0495435 Binary files /dev/null and b/src/icons/restore-k-15.png differ diff --git a/src/icons/restore-k-20.png b/src/icons/restore-k-20.png new file mode 100644 index 0000000..6611186 Binary files /dev/null and b/src/icons/restore-k-20.png differ diff --git a/src/icons/restore-k-24.png b/src/icons/restore-k-24.png new file mode 100644 index 0000000..5d549c3 Binary files /dev/null and b/src/icons/restore-k-24.png differ diff --git a/src/icons/restore-k-30.png b/src/icons/restore-k-30.png new file mode 100644 index 0000000..66594d2 Binary files /dev/null and b/src/icons/restore-k-30.png differ diff --git a/src/icons/restore-w-10.png b/src/icons/restore-w-10.png new file mode 100644 index 0000000..9262191 Binary files /dev/null and b/src/icons/restore-w-10.png differ diff --git a/src/icons/restore-w-12.png b/src/icons/restore-w-12.png new file mode 100644 index 0000000..ea6a133 Binary files /dev/null and b/src/icons/restore-w-12.png differ diff --git a/src/icons/restore-w-15.png b/src/icons/restore-w-15.png new file mode 100644 index 0000000..8e6eddd Binary files /dev/null and b/src/icons/restore-w-15.png differ diff --git a/src/icons/restore-w-20.png b/src/icons/restore-w-20.png new file mode 100644 index 0000000..ec35abd Binary files /dev/null and b/src/icons/restore-w-20.png differ diff --git a/src/icons/restore-w-24.png b/src/icons/restore-w-24.png new file mode 100644 index 0000000..bdc9896 Binary files /dev/null and b/src/icons/restore-w-24.png differ diff --git a/src/icons/restore-w-30.png b/src/icons/restore-w-30.png new file mode 100644 index 0000000..1cf61cc Binary files /dev/null and b/src/icons/restore-w-30.png differ diff --git a/src/main.dev.ts b/src/main.dev.ts index 526988f..83d1cc6 100644 --- a/src/main.dev.ts +++ b/src/main.dev.ts @@ -75,10 +75,12 @@ const createWindow = async () => { webPreferences: { nodeIntegration: true, enableRemoteModule: true, + preload: path.join(__dirname, 'preload.ts'), // Add custom titlebar functionality }, autoHideMenuBar: true, minWidth: 800, minHeight: 600, + frame: false, }); mainWindow.loadURL(`file://${__dirname}/index.html`); diff --git a/src/preload.ts b/src/preload.ts new file mode 100644 index 0000000..40cc919 --- /dev/null +++ b/src/preload.ts @@ -0,0 +1,50 @@ +import { remote } from 'electron'; + +const win = remote.getCurrentWindow(); /* Note this is different to the +html global `window` variable */ + +window.onbeforeunload = () => { + /* If window is reloaded, remove win event listeners + (DOM element listeners get auto garbage collected but not + Electron win listeners as the win is not dereferenced unless closed) */ + win.removeAllListeners(); +}; + +function handleWindowControls() { + // Make minimise/maximise/restore/close buttons work when they are clicked + document.getElementById('min-button')?.addEventListener('click', () => { + win.minimize(); + }); + + document.getElementById('max-button')?.addEventListener('click', () => { + win.maximize(); + }); + + document.getElementById('restore-button')?.addEventListener('click', () => { + win.unmaximize(); + }); + + document.getElementById('close-button')?.addEventListener('click', () => { + win.close(); + }); + + function toggleMaxRestoreButtons() { + if (win.isMaximized()) { + document.body.classList.add('maximized'); + } else { + document.body.classList.remove('maximized'); + } + } + + // Toggle maximise/restore buttons when maximisation/unmaximisation occurs + toggleMaxRestoreButtons(); + win.on('maximize', toggleMaxRestoreButtons); + win.on('unmaximize', toggleMaxRestoreButtons); +} + +// When document has loaded, initialise +document.onreadystatechange = () => { + if (document.readyState === 'complete') { + handleWindowControls(); + } +}; diff --git a/src/styles/App.global.css b/src/styles/App.global.css index 2c34ac2..963599c 100644 --- a/src/styles/App.global.css +++ b/src/styles/App.global.css @@ -12,10 +12,19 @@ body { height: 100%; } +body { + border: 1px solid #48545c; + overflow-y: hidden; +} + #root { min-height: 100%; } +h1 { + font-size: 30px !important; +} + .rs-panel-heading { padding-bottom: 5px !important; } diff --git a/src/styles/Layout.global.css b/src/styles/Layout.global.css index 3efd8eb..cf4e8ab 100644 --- a/src/styles/Layout.global.css +++ b/src/styles/Layout.global.css @@ -23,5 +23,5 @@ } .container__page { - height: 100vh; + height: 100%; } diff --git a/src/styles/Sidebar.global.css b/src/styles/Sidebar.global.css index 93171ab..e2be354 100644 --- a/src/styles/Sidebar.global.css +++ b/src/styles/Sidebar.global.css @@ -1,5 +1,6 @@ .container__sidebar { position: fixed; + top: 33px; /* Account for custom titlebar */ z-index: 1; } diff --git a/src/styles/Titlebar.global.css b/src/styles/Titlebar.global.css new file mode 100644 index 0000000..a20731f --- /dev/null +++ b/src/styles/Titlebar.global.css @@ -0,0 +1,110 @@ +@media (-webkit-device-pixel-ratio: 1.5), + (device-pixel-ratio: 1.5), + (-webkit-device-pixel-ratio: 2), + (device-pixel-ratio: 2), + (-webkit-device-pixel-ratio: 3), + (device-pixel-ratio: 3) { + #window-controls .icon { + width: 10px; + height: 10px; + } +} + +#main { + height: calc(100% - 32px); + margin-top: 32px; + padding: 20px; + overflow-y: auto; +} + +#titlebar { + display: block; + position: fixed; + height: 32px; + width: calc(100% - 2px); /*Compensate for body 1px border*/ + background: #1a1d24; + padding: 4px; + color: #fff; +} + +#titlebar #drag-region { + width: 100%; + height: 100%; + -webkit-app-region: drag; +} + +#window-controls { + display: grid; + grid-template-columns: repeat(3, 46px); + position: absolute; + top: 0; + right: 0; + height: 100%; +} + +#window-controls .button { + grid-row: 1 / span 1; + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; +} + +#min-button { + grid-column: 1; +} + +#max-button, +#restore-button { + grid-column: 2; +} + +#close-button { + grid-column: 3; +} + +#window-controls { + -webkit-app-region: no-drag; +} + +#window-controls .button { + user-select: none; +} +#window-controls .button:hover { + background: rgba(255, 255, 255, 0.1); +} +#window-controls .button:active { + background: rgba(255, 255, 255, 0.2); +} + +#close-button:hover { + background: #e81123 !important; +} +#close-button:active { + background: #f1707a !important; +} +#close-button:active .icon { + filter: invert(1); +} + +#restore-button { + display: none !important; +} + +.maximized #titlebar { + width: 100%; + padding: 0; +} + +#window-title { + margin-left: 12px; +} + +.maximized #restore-button { + display: flex !important; +} + +.maximized #max-button { + display: none; +} diff --git a/src/styles/custom-theme.less b/src/styles/custom-theme.less index 97d9964..0a75076 100644 --- a/src/styles/custom-theme.less +++ b/src/styles/custom-theme.less @@ -3,6 +3,7 @@ @table-border-color: #0f131a; // Sidenav +@sidenav-default-bg: #0f131a; @sidenav-collapse-transition-config: 0s; // Panel