From 73e042b98b68b9031e67afce077cd02e4d7dd9be Mon Sep 17 00:00:00 2001 From: AykutSarac Date: Fri, 15 Apr 2022 22:36:51 +0300 Subject: [PATCH] add light theme --- src/components/Input/index.tsx | 6 +++- src/components/Sidebar/index.tsx | 4 +-- src/components/Tooltip/index.tsx | 5 ++- src/constants/data.ts | 1 + src/constants/theme.ts | 33 ++++++++++++++++++- src/containers/Editor/Tools.tsx | 9 ++++- src/containers/Editor/styles.tsx | 6 ++-- src/containers/JsonEditor/ErrorContainer.tsx | 9 +++-- src/containers/JsonEditor/index.tsx | 10 ++++-- .../LiveEditor/CustomNode/index.tsx | 14 ++------ src/containers/LiveEditor/index.tsx | 19 +++-------- src/hocs/config.tsx | 10 +++++- src/pages/_app.tsx | 11 +++++-- src/pages/editor/index.tsx | 5 +-- src/reducer/reducer.ts | 10 ++++++ src/typings/global.ts | 1 + src/typings/styled.d.ts | 1 + 17 files changed, 106 insertions(+), 48 deletions(-) diff --git a/src/components/Input/index.tsx b/src/components/Input/index.tsx index 3072f2b..dfe1774 100644 --- a/src/components/Input/index.tsx +++ b/src/components/Input/index.tsx @@ -39,9 +39,13 @@ const StyledInput = styled.input` const StyledSearchButton = styled.button` display: grid; background: none; - color: inherit; + color: ${({ theme }) => theme.INTERACTIVE_NORMAL}; padding: 0; min-height: unset; + + &:hover { + box-shadow: none; + } `; export const Input = () => { diff --git a/src/components/Sidebar/index.tsx b/src/components/Sidebar/index.tsx index a089f38..832cd50 100644 --- a/src/components/Sidebar/index.tsx +++ b/src/components/Sidebar/index.tsx @@ -36,7 +36,7 @@ const StyledSidebar = styled.div` width: 42px; background: ${({ theme }) => theme.BACKGROUND_TERTIARY}; padding: 8px; - border-right: 1px solid ${({ theme }) => theme.SILVER_DARK}; + border-right: 1px solid ${({ theme }) => theme.BACKGROUND_MODIFIER_ACCENT}; `; const StyledElement = styled.div` @@ -61,7 +61,7 @@ const StyledElement = styled.div` const StyledText = styled.span<{ secondary?: boolean }>` color: ${({ theme, secondary }) => - secondary ? theme.FULL_WHITE : theme.ORANGE}; + secondary ? theme.INTERACTIVE_NORMAL : theme.ORANGE}; `; const StyledTopWrapper = styled.nav` diff --git a/src/components/Tooltip/index.tsx b/src/components/Tooltip/index.tsx index 7623373..6b2c773 100644 --- a/src/components/Tooltip/index.tsx +++ b/src/components/Tooltip/index.tsx @@ -17,7 +17,7 @@ const StyledTooltip = styled.div<{ visible: boolean }>` right: 0; transform: translate(calc(100% + 15px), 25%); z-index: 5; - background: ${({ theme }) => theme.SILVER_DARK}; + background: ${({ theme }) => theme.BACKGROUND_PRIMARY}; color: ${({ theme }) => theme.TEXT_NORMAL}; border-radius: 5px; padding: 4px 8px; @@ -27,6 +27,9 @@ const StyledTooltip = styled.div<{ visible: boolean }>` font-size: 16px; user-select: none; font-weight: 600; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.07), 0 2px 4px rgba(0, 0, 0, 0.07), + 0 4px 8px rgba(0, 0, 0, 0.07), 0 8px 16px rgba(0, 0, 0, 0.07), + 0 16px 32px rgba(0, 0, 0, 0.07), 0 32px 64px rgba(0, 0, 0, 0.07); `; const StyledChildren = styled.div``; diff --git a/src/constants/data.ts b/src/constants/data.ts index dc467b5..bc36301 100644 --- a/src/constants/data.ts +++ b/src/constants/data.ts @@ -40,4 +40,5 @@ export const defaultConfig: StorageConfig = { hideEditor: false, searchNode: "", zoomPanPinch: null, + lightmode: false }; diff --git a/src/constants/theme.ts b/src/constants/theme.ts index 25fc5c1..78b28ee 100644 --- a/src/constants/theme.ts +++ b/src/constants/theme.ts @@ -20,11 +20,42 @@ export const darkTheme: DefaultTheme = { INTERACTIVE_NORMAL: "#b9bbbe", INTERACTIVE_HOVER: "#dcddde", INTERACTIVE_ACTIVE: "#fff", + BACKGROUND_NODE: "#2B2C3E", BACKGROUND_TERTIARY: "#202225", BACKGROUND_SECONDARY: "#2f3136", BACKGROUND_PRIMARY: "#36393f", BACKGROUND_MODIFIER_ACCENT: "rgba(79,84,92,0.48)", TEXT_NORMAL: "#dcddde", TEXT_POSITIVE: "hsl(139,calc(var(--saturation-factor, 1)*51.6%),52.2%)", - TEXT_DANGER: "hsl(359,calc(var(--saturation-factor, 1)*82%),73.9%)" + TEXT_DANGER: "hsl(359,calc(var(--saturation-factor, 1)*82%),73.9%)", +} as const; + +export const lightTheme: DefaultTheme = { + BLURPLE: "#5865F2", + FULL_WHITE: "#FFFFFF", + BLACK: "#202225", + BLACK_DARK: "#2C2F33", + BLACK_LIGHT: "#2F3136", + BLACK_PRIMARY: "#36393f", + BLACK_SECONDARY: "#23272A", + CRIMSON: "#DC143C", + DARK_SALMON: "#E9967A", + DANGER: "#db662e", + LIGHTGREEN: "#90EE90", + SEAGREEN: "#3BA55D", + ORANGE: "#FAA81A", + SILVER: "#B9BBBE", + SILVER_DARK: "#4D4D4D", + + INTERACTIVE_NORMAL: "#4f5660", + INTERACTIVE_HOVER: "#2e3338", + INTERACTIVE_ACTIVE: "#060607", + BACKGROUND_NODE: "#FFFFFF", + BACKGROUND_TERTIARY: "#e3e5e8", + BACKGROUND_SECONDARY: "#f2f3f5", + BACKGROUND_PRIMARY: "#FFFFFF", + BACKGROUND_MODIFIER_ACCENT: "rgba(106,116,128,0.24)", + TEXT_NORMAL: "#2e3338", + TEXT_POSITIVE: "hsl(139,calc(var(--saturation-factor, 1)*51.6%),52.2%)", + TEXT_DANGER: "hsl(359,calc(var(--saturation-factor, 1)*82%),73.9%)", } as const; diff --git a/src/containers/Editor/Tools.tsx b/src/containers/Editor/Tools.tsx index d766032..e8e813c 100644 --- a/src/containers/Editor/Tools.tsx +++ b/src/containers/Editor/Tools.tsx @@ -6,6 +6,7 @@ import { AiOutlineMinus, AiOutlinePlus, } from "react-icons/ai"; +import { HiOutlineSun, HiOutlineMoon } from "react-icons/hi"; import { MdCenterFocusWeak } from "react-icons/md"; import { Input } from "src/components/Input"; import { useConfig } from "src/hocs/config"; @@ -19,9 +20,10 @@ export const StyledTools = styled.div` flex-direction: row-reverse; height: 28px; padding: 4px 16px; - border-bottom: 1px solid #1f2124; background: ${({ theme }) => theme.BACKGROUND_PRIMARY}; color: ${({ theme }) => theme.SILVER}; + + box-shadow: 0 1px 0px ${({ theme }) => theme.BACKGROUND_TERTIARY}; `; const StyledToolElement = styled.button` @@ -53,11 +55,16 @@ export const Tools: React.FC = () => { const toggleEditor = () => dispatch({ type: ConfigActionType.TOGGLE_DOCK }); + const toggleTheme = () => dispatch({ type: ConfigActionType.TOGGLE_THEME }); + return ( + + {states.settings.lightmode ? : } + diff --git a/src/containers/Editor/styles.tsx b/src/containers/Editor/styles.tsx index 14d93e3..9bc2843 100644 --- a/src/containers/Editor/styles.tsx +++ b/src/containers/Editor/styles.tsx @@ -21,7 +21,7 @@ export const StyledEditor = styled(SplitPane)` background: ${({ theme }) => theme.BACKGROUND_SECONDARY}; .Resizer { - background: ${({ theme }) => theme.BLACK}; + background: ${({ theme }) => theme.BACKGROUND_MODIFIER_ACCENT}; box-sizing: border-box; background-clip: padding-box; z-index: 1; @@ -50,12 +50,12 @@ export const StyledEditor = styled(SplitPane)` } .Resizer.vertical { - width: 16px; + width: 14px; margin: 0 -5px; border-left: 5px solid rgba(255, 255, 255, 0); border-right: 5px solid rgba(255, 255, 255, 0); cursor: col-resize; - z-index: 0 !important; + z-index: 1; } .Resizer.vertical:hover { diff --git a/src/containers/JsonEditor/ErrorContainer.tsx b/src/containers/JsonEditor/ErrorContainer.tsx index fd6c9ba..cc65981 100644 --- a/src/containers/JsonEditor/ErrorContainer.tsx +++ b/src/containers/JsonEditor/ErrorContainer.tsx @@ -17,13 +17,16 @@ interface ErrorContainerProps { setError: React.Dispatch>; } -const StyledErrorWrapper = styled.div``; +const StyledErrorWrapper = styled.div` + z-index: 5; +`; const StyledErrorHeader = styled.div` height: 28px; padding: 4px 16px; - border-bottom: 1px solid #1f2124; - background: ${({ theme }) => theme.BLACK_DARK}; + background: ${({ theme }) => theme.BACKGROUND_SECONDARY}; + + box-shadow: 0 1px 0px ${({ theme }) => theme.BACKGROUND_TERTIARY}; `; const StyledErrorExpand = styled.button<{ error: boolean }>` diff --git a/src/containers/JsonEditor/index.tsx b/src/containers/JsonEditor/index.tsx index 269e139..6811258 100644 --- a/src/containers/JsonEditor/index.tsx +++ b/src/containers/JsonEditor/index.tsx @@ -2,11 +2,12 @@ import React from "react"; import AceEditor from "react-ace"; import parseJson from "parse-json"; import styled from "styled-components"; -import { Error, ErrorContainer } from "./ErrorContainer"; +import { ErrorContainer } from "./ErrorContainer"; import { ConfigActionType } from "src/reducer/reducer"; import { useConfig } from "src/hocs/config"; require("ace-builds/src-noconflict/mode-json"); require("ace-builds/src-noconflict/theme-tomorrow_night"); +require("ace-builds/src-noconflict/theme-github"); const StyledEditorWrapper = styled.div` display: flex; @@ -32,6 +33,11 @@ const JsonEditor: React.FC = () => { isExpanded: true, }); + const editorTheme = React.useMemo( + () => (settings.lightmode ? "github" : "tomorrow_night"), + [settings.lightmode] + ); + React.useEffect(() => { const resizeObserver = new ResizeObserver((observed) => { const width = observed[0].contentRect.width; @@ -83,7 +89,7 @@ const JsonEditor: React.FC = () => { value={value} onChange={setValue} mode="json" - theme="tomorrow_night" + theme={editorTheme} width={editorWidth} height="100%" fontSize={12} diff --git a/src/containers/LiveEditor/CustomNode/index.tsx b/src/containers/LiveEditor/CustomNode/index.tsx index 240a0b4..febc1c0 100644 --- a/src/containers/LiveEditor/CustomNode/index.tsx +++ b/src/containers/LiveEditor/CustomNode/index.tsx @@ -18,19 +18,11 @@ const baseLabelStyle = { strokeWidth: 0, }; -const basePortStyle = { - fill: "black", -}; - -export const CustomNode = (nodeProps: NodeProps) => { +export const CustomNode = React.memo((nodeProps: NodeProps) => { const { properties: data } = nodeProps; return ( - } - port={} - > + }> {(nodeProps: NodeProps) => { const { width, height } = nodeProps; @@ -60,4 +52,4 @@ export const CustomNode = (nodeProps: NodeProps) => { }} ); -}; +}); diff --git a/src/containers/LiveEditor/index.tsx b/src/containers/LiveEditor/index.tsx index 553987a..d5af482 100644 --- a/src/containers/LiveEditor/index.tsx +++ b/src/containers/LiveEditor/index.tsx @@ -20,20 +20,9 @@ const StyledLiveEditor = styled.div` const StyledEditorWrapper = styled.div` position: absolute; -`; -const StyledControls = styled.div` - position: fixed; - display: grid; - grid-template-columns: 1fr 1fr; - grid-template-rows: 1fr 1fr; - gap: 8px; - bottom: 8px; - right: 8px; - opacity: 0.9; - - button:hover { - opacity: 0.7; + rect { + fill: ${({ theme }) => theme.BACKGROUND_NODE}; } `; @@ -118,7 +107,7 @@ export const LiveEditor: React.FC = React.memo(function LiveEditor() { } edges={data.edges} maxWidth={20000} maxHeight={20000} @@ -127,7 +116,7 @@ export const LiveEditor: React.FC = React.memo(function LiveEditor() { fit={true} direction={settings.layout} readonly - key={settings.layout} + key={settings.layout || settings.lightmode} onCanvasClick={onCanvasClick} /> diff --git a/src/hocs/config.tsx b/src/hocs/config.tsx index 8199271..2439f8e 100644 --- a/src/hocs/config.tsx +++ b/src/hocs/config.tsx @@ -37,4 +37,12 @@ const WithConfig: React.FC = ({ children }) => { ); }; -export { WithConfig, useConfig, ConfigContext }; +const withConfig = (Component) => { + return (props) => ( + + + + ); +}; + +export { WithConfig, useConfig, ConfigContext, withConfig }; diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index e94608a..99f6e08 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -3,13 +3,18 @@ import type { AppProps } from "next/app"; import { ThemeProvider } from "styled-components"; import GlobalStyle from "src/constants/globalStyle"; -import { darkTheme } from "src/constants/theme"; +import { darkTheme, lightTheme } from "src/constants/theme"; import { Toaster } from "react-hot-toast"; +import { useConfig, withConfig, WithConfig } from "src/hocs/config"; function JsonVisio({ Component, pageProps }: AppProps) { + const { + states: { settings }, + } = useConfig(); + return ( <> - + { return ( @@ -13,9 +12,7 @@ const EditorPage: React.FC = () => { content="View your JSON data in graphs instantly." /> - - - + ); }; diff --git a/src/reducer/reducer.ts b/src/reducer/reducer.ts index b463456..cafaa49 100644 --- a/src/reducer/reducer.ts +++ b/src/reducer/reducer.ts @@ -8,6 +8,7 @@ export enum ConfigActionType { TOGGLE_EXPAND, TOGGLE_AUTOFORMAT, TOGGLE_DOCK, + TOGGLE_THEME, ZOOM_IN, ZOOM_OUT, CENTER_VIEW, @@ -29,6 +30,15 @@ export const useConfigReducer: React.Reducer = ( case ConfigActionType.SET_CONFIG: return { ...state, settings: action.payload }; + case ConfigActionType.TOGGLE_THEME: + return { + ...state, + settings: { + ...state.settings, + lightmode: !state.settings.lightmode, + }, + }; + case ConfigActionType.SET_ZOOM_PAN_PICNH_REF: return { ...state, diff --git a/src/typings/global.ts b/src/typings/global.ts index 8d8af38..ebd5cb3 100644 --- a/src/typings/global.ts +++ b/src/typings/global.ts @@ -8,4 +8,5 @@ export interface StorageConfig { hideEditor: boolean; searchNode: string; zoomPanPinch: ReactZoomPanPinchRef | null; + lightmode: boolean; } diff --git a/src/typings/styled.d.ts b/src/typings/styled.d.ts index f8f9834..72a5679 100644 --- a/src/typings/styled.d.ts +++ b/src/typings/styled.d.ts @@ -28,6 +28,7 @@ declare module "styled-components" { INTERACTIVE_NORMAL: string; INTERACTIVE_HOVER: string; INTERACTIVE_ACTIVE: string; + BACKGROUND_NODE: string; BACKGROUND_TERTIARY: string; BACKGROUND_SECONDARY: string; BACKGROUND_PRIMARY: string;