diff --git a/pages/_app.tsx b/pages/_app.tsx
index aeff5dd..a331b70 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -4,9 +4,14 @@ import "@blueprintjs/core/lib/css/blueprint.css";
import "@blueprintjs/icons/lib/css/blueprint-icons.css";
import "react-mosaic-component/react-mosaic-component.css";
import type { AppProps } from "next/app";
+import { DarkModeProvider } from "../ui/providers/dark-mode-provider";
function MyApp({ Component, pageProps }: AppProps) {
- return ;
+ return (
+
+
+
+ );
}
export default MyApp;
diff --git a/pages/index.tsx b/pages/index.tsx
index 4e43e31..cfd0af4 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -2,6 +2,7 @@ import React from "react";
import { NextPage } from "next";
import { Mainframe } from "../ui/Mainframe";
import Head from "next/head";
+import { Header } from "../ui/header";
const Index: NextPage = () => {
return (
@@ -9,7 +10,12 @@ const Index: NextPage = () => {
Esolang Park
-
+
>
);
};
diff --git a/public/favicon.ico b/public/favicon.ico
index 718d6fe..cd58d04 100644
Binary files a/public/favicon.ico and b/public/favicon.ico differ
diff --git a/styles/globals.css b/styles/globals.css
index 8e1015f..34191a7 100644
--- a/styles/globals.css
+++ b/styles/globals.css
@@ -13,6 +13,14 @@ body,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}
+body {
+ background-color: #a7b6c2;
+}
+
+body.bp3-dark {
+ background-color: #202b33;
+}
+
a {
color: inherit;
text-decoration: none;
diff --git a/ui/MainLayout.tsx b/ui/MainLayout.tsx
index 7421d2f..8af54b3 100644
--- a/ui/MainLayout.tsx
+++ b/ui/MainLayout.tsx
@@ -1,5 +1,6 @@
import React from "react";
import { Mosaic, MosaicNode, MosaicWindow } from "react-mosaic-component";
+import { useDarkMode } from "./providers/dark-mode-provider";
// IDs of windows in the mosaic layout
type WINDOW_ID = "editor" | "renderer" | "input" | "output";
@@ -20,6 +21,9 @@ type Props = {
};
export const MainLayout = (props: Props) => {
+ const { isDark } = useDarkMode();
+ const mosaicClass = "mosaic-blueprint-theme" + (isDark ? " bp3-dark" : "");
+
const MOSAIC_MAP = {
editor: props.renderEditor,
renderer: props.renderRenderer,
@@ -43,7 +47,7 @@ export const MainLayout = (props: Props) => {
return (
- className="mosaic-blueprint-theme bp3-dark"
+ className={mosaicClass}
initialValue={INITIAL_LAYOUT}
renderTile={(windowId, path) => (
diff --git a/ui/custom-icons.tsx b/ui/custom-icons.tsx
new file mode 100644
index 0000000..0117dfe
--- /dev/null
+++ b/ui/custom-icons.tsx
@@ -0,0 +1,22 @@
+import { Colors } from "@blueprintjs/core";
+import { useDarkMode } from "./providers/dark-mode-provider";
+
+export const GitHubIcon = () => {
+ const { isDark } = useDarkMode();
+ const color = isDark ? Colors.GRAY4 : Colors.GRAY1;
+
+ return (
+
+ );
+};
diff --git a/ui/header.tsx b/ui/header.tsx
new file mode 100644
index 0000000..125bd5d
--- /dev/null
+++ b/ui/header.tsx
@@ -0,0 +1,49 @@
+import { Button, Card, Icon } from "@blueprintjs/core";
+import { GitHubIcon } from "./custom-icons";
+import { useDarkMode } from "./providers/dark-mode-provider";
+
+export const Header = () => {
+ const DarkMode = useDarkMode();
+
+ const brandSection = (
+
+ }>
+ Esolang Park
+
+
+ );
+
+ const langSection = (
+ Brainfuck
+ );
+
+ const infoSection = (
+
+ );
+
+ return (
+
+
+ {brandSection}
+ {langSection}
+ {infoSection}
+
+
+ );
+};
diff --git a/ui/providers/dark-mode-provider.tsx b/ui/providers/dark-mode-provider.tsx
new file mode 100644
index 0000000..ef1b206
--- /dev/null
+++ b/ui/providers/dark-mode-provider.tsx
@@ -0,0 +1,30 @@
+import { Classes } from "@blueprintjs/core";
+import React from "react";
+
+const DarkModeContext = React.createContext<{
+ isDark: boolean;
+ toggleDark: () => void;
+}>({ isDark: false, toggleDark: () => {} });
+
+/** Context provider for managing dark mode state */
+export const DarkModeProvider = ({
+ children,
+}: {
+ children: React.ReactNode;
+}) => {
+ const [isDark, setIsDark] = React.useState(false);
+
+ const toggleDark = () => {
+ document.body.classList.toggle(Classes.DARK);
+ setIsDark((d) => !d);
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+/** Utility hook to access dark mode state and controls */
+export const useDarkMode = () => React.useContext(DarkModeContext);