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