Skip to content

Commit

Permalink
feat: update components to play well with dark theme (#10)
Browse files Browse the repository at this point in the history
* chore: Add createStore function for managing state

* feat: Add theme provider for managing app theme

* chore: Update color palette in index.css

- add dark theme color palette

* chore: Update color palette in index.css

* feat: update to play well with dark theme
  • Loading branch information
DGCP3 authored Jun 18, 2024
1 parent e5cafbf commit 064efc4
Show file tree
Hide file tree
Showing 9 changed files with 242 additions and 240 deletions.
18 changes: 14 additions & 4 deletions ui/src/components/editor.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import "@/editorWorker";
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
import { FunctionComponent, useRef, useState, useEffect } from "react";
import { FunctionComponent, useEffect, useRef, useState } from "react";

import { useTheme } from "@/provider/theme.provider";
import { Card } from "./ui/card";

type Props = {
Expand All @@ -10,8 +11,8 @@ type Props = {
};

export const Editor: FunctionComponent<Props> = ({ value, onChange }) => {
const [editor, setEditor] =
useState<monaco.editor.IStandaloneCodeEditor | null>(null);
const currentTheme = useTheme();
const [editor, setEditor] = useState<monaco.editor.IStandaloneCodeEditor | null>(null);
const monacoEl = useRef(null);

useEffect(() => {
Expand All @@ -30,6 +31,7 @@ export const Editor: FunctionComponent<Props> = ({ value, onChange }) => {
top: 20,
bottom: 20,
},
cursorStyle: "block",
automaticLayout: true,
readOnly: onChange === undefined,
});
Expand All @@ -38,16 +40,24 @@ export const Editor: FunctionComponent<Props> = ({ value, onChange }) => {
onChange?.(newEditor.getValue());
});

// set theme
editor;
return newEditor;
});
}

return () => editor?.dispose();
}, [monacoEl.current]);

useEffect(() => {
if (monacoEl.current) {
monaco.editor.setTheme(currentTheme === "light" ? "vs" : "vs-dark");
}
}, [currentTheme]);

return (
<Card className="p-1">
<div className="w-full h-[200px]" ref={monacoEl}></div>
<div className="w-full h-[200px] bg-background" ref={monacoEl}></div>
</Card>
);
};
85 changes: 39 additions & 46 deletions ui/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,65 +4,58 @@

@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;

--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;

--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;

--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;

--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;

--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;

--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;

--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;

--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;

--text-foreground: 0 0% 0%;
--background: 175 30% 98%;
--foreground: 175 59% 4%;
--muted: 145 20% 95%;
--muted-foreground: 145 15% 37%;
--popover: 175 30% 97%;
--popover-foreground: 175 59% 3%;
--card: 175 30% 97%;
--card-foreground: 175 59% 3%;
--border: 175 4% 90%;
--input: 175 4% 90%;
--primary: 175 91% 12%;
--primary-foreground: 175 91% 52%;
--secondary: 145 91% 12%;
--secondary-foreground: 145 91% 52%;
--accent: 205 91% 12%;
--accent-foreground: 205 91% 72%;
--destructive: 19 92% 33%;
--destructive-foreground: 0 0% 100%;
--ring: 175 91% 12%;
--radius: 0.5rem;
}

.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--background: 159 65% 4%;
--foreground: 159 10% 97.5%;

--muted: 159 50% 15%;
--muted-foreground: 159 10% 55%;

--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;
--popover: 159 45% 6.5%;
--popover-foreground: 159 10% 97.5%;

--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;
--card: 159 45% 6.5%;
--card-foreground: 159 10% 97.5%;

--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;
--border: 159 50% 15%;
--input: 159 50% 15%;

--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
--primary: 159 100% 50%;
--primary-foreground: 159 10% 5%;

--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--secondary: 159 50% 15%;
--secondary-foreground: 159 10% 97.5%;

--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--accent: 159 50% 15%;
--accent-foreground: 159 10% 97.5%;

--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
--destructive-foreground: 159 10% 97.5%;

--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;
--ring: 159 100% 50%;
}
}

Expand Down
37 changes: 37 additions & 0 deletions ui/src/lib/makeStore.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Dispatch, PropsWithChildren, createContext, useContext, useReducer } from "react";

/**
* Creates a store with the specified reducer and initial state.
*
* @template State - The type of the state.
* @template Action - The type of the action.
* @param {function(state: State, action: Action): State} reducer - The reducer function that updates the state based on the action.
* @param {State} initialState - The initial state of the store.
* @returns {{ StoreProvider: React.ComponentType<PropsWithChildren>, useDispatch: function(): Dispatch<Action>, useStore: function(): State }} - An object containing the StoreProvider component, useDispatch hook, and useStore hook.
*/
export default function createStore<State, Action>(
reducer: (state: State, action: Action) => State,
initialState: State
) {
const StoreContext = createContext(initialState);
const DispatchContext = createContext<Dispatch<Action>>(() => {});

function StoreProvider({ children }: PropsWithChildren) {
const [store, dispatch] = useReducer(reducer, initialState);

return (
<StoreContext.Provider value={store}>
<DispatchContext.Provider value={dispatch}>{children}</DispatchContext.Provider>
</StoreContext.Provider>
);
}

function useStore() {
return useContext(StoreContext);
}

function useDispatch() {
return useContext(DispatchContext);
}
return { StoreProvider, useDispatch, useStore };
}
16 changes: 9 additions & 7 deletions ui/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import "./index.css";

import React from "react";
import { StrictMode } from "react";
import ReactDOM from "react-dom/client";
import { RouterProvider, createRouter } from "@tanstack/react-router";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { RouterProvider, createRouter } from "@tanstack/react-router";
import React, { StrictMode } from "react";
import ReactDOM from "react-dom/client";

// Import the generated route tree
import { ThemeProvider } from "./provider/theme.provider";
import { routeTree } from "./routeTree.gen";

// Create a new router instance
Expand All @@ -24,7 +24,7 @@ const ReactQueryDevtools = import.meta.env.PROD
: React.lazy(() =>
import("@tanstack/react-query-devtools").then((res) => ({
default: res.ReactQueryDevtools,
})),
}))
);

const queryClient = new QueryClient();
Expand All @@ -36,9 +36,11 @@ if (!rootElement.innerHTML) {
root.render(
<StrictMode>
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
<ThemeProvider>
<RouterProvider router={router} />
</ThemeProvider>
<ReactQueryDevtools />
</QueryClientProvider>
</StrictMode>,
</StrictMode>
);
}
15 changes: 15 additions & 0 deletions ui/src/provider/theme.provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import createStore from "@/lib/makeStore";

export type Theme = "dark" | "light";

export const {
StoreProvider: ThemeProvider,
useDispatch: setTheme,
useStore: useTheme,
} = createStore(
(_, next: Theme) => {
localStorage.setItem("theme", next);
return next;
},
(localStorage.getItem("theme") === "dark" ? "dark" : "light") as Theme
);
Loading

0 comments on commit 064efc4

Please sign in to comment.