Browse Source

feat: add dark mode functionality

Signed-off-by: SphericalKat <amolele@gmail.com>
SphericalKat 4 years ago
parent
commit
7bc4206b2b
3 changed files with 63 additions and 19 deletions
  1. 50 14
      src/App.tsx
  2. 3 2
      src/ConnectionStatus.tsx
  3. 10 3
      src/User.tsx

+ 50 - 14
src/App.tsx

@@ -14,6 +14,7 @@ import {
   Link,
   Link,
   Select,
   Select,
   Stack,
   Stack,
+  Switch,
   Text,
   Text,
   useToast,
   useToast,
 } from "@chakra-ui/react";
 } from "@chakra-ui/react";
@@ -62,6 +63,7 @@ function App() {
   const [name, setName] = useStorage("name", generateName);
   const [name, setName] = useStorage("name", generateName);
   const [hue, setHue] = useStorage("hue", generateHue);
   const [hue, setHue] = useStorage("hue", generateHue);
   const [editor, setEditor] = useState<editor.IStandaloneCodeEditor>();
   const [editor, setEditor] = useState<editor.IStandaloneCodeEditor>();
+  const [darkMode, setDarkMode] = useStorage("darkMode", () => false);
   const rustpad = useRef<Rustpad>();
   const rustpad = useRef<Rustpad>();
   const id = useHash();
   const id = useHash();
 
 
@@ -156,12 +158,16 @@ function App() {
     }
     }
   }
   }
 
 
+  function handleDarkMode() {
+    setDarkMode(!darkMode);
+  }
+
   return (
   return (
     <Flex direction="column" h="100vh" overflow="hidden">
     <Flex direction="column" h="100vh" overflow="hidden">
       <Box
       <Box
         flexShrink={0}
         flexShrink={0}
-        bgColor="#e8e8e8"
-        color="#383838"
+        bgColor={darkMode ? "#333333" : "#e8e8e8"}
+        color={darkMode ? "#cbcaca" : "#383838"}
         textAlign="center"
         textAlign="center"
         fontSize="sm"
         fontSize="sm"
         py={0.5}
         py={0.5}
@@ -171,15 +177,28 @@ function App() {
       <Flex flex="1 0" minH={0}>
       <Flex flex="1 0" minH={0}>
         <Container
         <Container
           w="xs"
           w="xs"
-          bgColor="#f3f3f3"
+          bgColor={darkMode ? "#252526" : "#f3f3f3"}
           overflowY="auto"
           overflowY="auto"
           maxW="full"
           maxW="full"
           lineHeight={1.4}
           lineHeight={1.4}
           py={4}
           py={4}
         >
         >
-          <ConnectionStatus connection={connection} />
+          <ConnectionStatus darkMode={darkMode} connection={connection} />
+
+          <Flex justifyContent="space-between" mt={4} mb={1.5} w="full">
+            <Heading color={darkMode ? "#cbcaca" : undefined} size="sm">
+              Dark mode
+            </Heading>
 
 
-          <Heading mt={4} mb={1.5} size="sm">
+            <Switch isChecked={darkMode} onChange={handleDarkMode} />
+          </Flex>
+
+          <Heading
+            color={darkMode ? "#cbcaca" : undefined}
+            mt={4}
+            mb={1.5}
+            size="sm"
+          >
             Language
             Language
           </Heading>
           </Heading>
           <Select
           <Select
@@ -195,7 +214,12 @@ function App() {
             ))}
             ))}
           </Select>
           </Select>
 
 
-          <Heading mt={4} mb={1.5} size="sm">
+          <Heading
+            color={darkMode ? "#cbcaca" : undefined}
+            mt={4}
+            mb={1.5}
+            size="sm"
+          >
             Share Link
             Share Link
           </Heading>
           </Heading>
           <InputGroup size="sm">
           <InputGroup size="sm">
@@ -213,7 +237,12 @@ function App() {
             </InputRightElement>
             </InputRightElement>
           </InputGroup>
           </InputGroup>
 
 
-          <Heading mt={4} mb={1.5} size="sm">
+          <Heading
+            color={darkMode ? "#cbcaca" : undefined}
+            mt={4}
+            mb={1.5}
+            size="sm"
+          >
             Active Users
             Active Users
           </Heading>
           </Heading>
           <Stack spacing={0} mb={1.5} fontSize="sm">
           <Stack spacing={0} mb={1.5} fontSize="sm">
@@ -222,24 +251,30 @@ function App() {
               isMe
               isMe
               onChangeName={(name) => name.length > 0 && setName(name)}
               onChangeName={(name) => name.length > 0 && setName(name)}
               onChangeColor={() => setHue(generateHue())}
               onChangeColor={() => setHue(generateHue())}
+              darkMode={darkMode}
             />
             />
             {Object.entries(users).map(([id, info]) => (
             {Object.entries(users).map(([id, info]) => (
-              <User key={id} info={info} />
+              <User key={id} info={info} darkMode={darkMode} />
             ))}
             ))}
           </Stack>
           </Stack>
 
 
-          <Heading mt={4} mb={1.5} size="sm">
+          <Heading
+            color={darkMode ? "#cbcaca" : undefined}
+            mt={4}
+            mb={1.5}
+            size="sm"
+          >
             About
             About
           </Heading>
           </Heading>
-          <Text fontSize="sm" mb={1.5}>
+          <Text color={darkMode ? "#cbcaca" : undefined} fontSize="sm" mb={1.5}>
             <strong>Rustpad</strong> is an open-source collaborative text editor
             <strong>Rustpad</strong> is an open-source collaborative text editor
             based on the <em>operational transformation</em> algorithm.
             based on the <em>operational transformation</em> algorithm.
           </Text>
           </Text>
-          <Text fontSize="sm" mb={1.5}>
+          <Text color={darkMode ? "#cbcaca" : undefined} fontSize="sm" mb={1.5}>
             Share a link to this pad with others, and they can edit from their
             Share a link to this pad with others, and they can edit from their
             browser while seeing your changes in real time.
             browser while seeing your changes in real time.
           </Text>
           </Text>
-          <Text fontSize="sm" mb={1.5}>
+          <Text color={darkMode ? "#cbcaca" : undefined} fontSize="sm" mb={1.5}>
             Built using Rust and TypeScript. See the{" "}
             Built using Rust and TypeScript. See the{" "}
             <Link
             <Link
               color="blue.600"
               color="blue.600"
@@ -267,7 +302,8 @@ function App() {
           <HStack
           <HStack
             h={6}
             h={6}
             spacing={1}
             spacing={1}
-            color="gray.500"
+            color={darkMode ? "#cbcaca" : "gray.400"}
+            backgroundColor={darkMode ? "#1e1e1e" : "#fffffe"}
             fontWeight="medium"
             fontWeight="medium"
             fontSize="13px"
             fontSize="13px"
             px={3.5}
             px={3.5}
@@ -281,7 +317,7 @@ function App() {
           </HStack>
           </HStack>
           <Box flex={1} minH={0}>
           <Box flex={1} minH={0}>
             <Editor
             <Editor
-              theme="vs"
+              theme={darkMode ? "vs-dark" : "vs"}
               language={language}
               language={language}
               options={{
               options={{
                 automaticLayout: true,
                 automaticLayout: true,

+ 3 - 2
src/ConnectionStatus.tsx

@@ -3,9 +3,10 @@ import { VscCircleFilled } from "react-icons/vsc";
 
 
 type ConnectionStatusProps = {
 type ConnectionStatusProps = {
   connection: "connected" | "disconnected" | "desynchronized";
   connection: "connected" | "disconnected" | "desynchronized";
+  darkMode: boolean;
 };
 };
 
 
-function ConnectionStatus({ connection }: ConnectionStatusProps) {
+function ConnectionStatus({ connection, darkMode }: ConnectionStatusProps) {
   return (
   return (
     <HStack spacing={1}>
     <HStack spacing={1}>
       <Icon
       <Icon
@@ -18,7 +19,7 @@ function ConnectionStatus({ connection }: ConnectionStatusProps) {
           }[connection]
           }[connection]
         }
         }
       />
       />
-      <Text fontSize="sm" fontStyle="italic" color="gray.600">
+      <Text fontSize="sm" fontStyle="italic" color={darkMode ? "gray.300" : "gray.600"}>
         {
         {
           {
           {
             connected: "You are connected!",
             connected: "You are connected!",

+ 10 - 3
src/User.tsx

@@ -25,9 +25,16 @@ type UserProps = {
   isMe?: boolean;
   isMe?: boolean;
   onChangeName?: (name: string) => unknown;
   onChangeName?: (name: string) => unknown;
   onChangeColor?: () => unknown;
   onChangeColor?: () => unknown;
+  darkMode: boolean;
 };
 };
 
 
-function User({ info, isMe = false, onChangeName, onChangeColor }: UserProps) {
+function User({
+  info,
+  isMe = false,
+  onChangeName,
+  onChangeColor,
+  darkMode,
+}: UserProps) {
   const inputRef = useRef<HTMLInputElement>(null);
   const inputRef = useRef<HTMLInputElement>(null);
   const { isOpen, onOpen, onClose } = useDisclosure();
   const { isOpen, onOpen, onClose } = useDisclosure();
 
 
@@ -46,11 +53,11 @@ function User({ info, isMe = false, onChangeName, onChangeColor }: UserProps) {
           _hover={{ bgColor: "gray.200", cursor: "pointer" }}
           _hover={{ bgColor: "gray.200", cursor: "pointer" }}
           onClick={() => isMe && onOpen()}
           onClick={() => isMe && onOpen()}
         >
         >
-          <Icon as={VscAccount} />
+          <Icon color={darkMode ? "#cbcaca" : undefined} as={VscAccount} />
           <Text fontWeight="medium" color={nameColor}>
           <Text fontWeight="medium" color={nameColor}>
             {info.name}
             {info.name}
           </Text>
           </Text>
-          {isMe && <Text>(you)</Text>}
+          {isMe && <Text color={darkMode ? "#cbcaca" : undefined}>(you)</Text>}
         </HStack>
         </HStack>
       </PopoverTrigger>
       </PopoverTrigger>
       <PopoverContent>
       <PopoverContent>