feat: dark-mode (code editor)

This commit is contained in:
Anoop M D 2022-10-23 04:48:43 +05:30
parent 23400a77f8
commit 04a0a37ca4
14 changed files with 75 additions and 24 deletions

View File

@ -2,12 +2,31 @@ import styled from 'styled-components';
const StyledWrapper = styled.div` const StyledWrapper = styled.div`
div.CodeMirror { div.CodeMirror {
border: solid 1px var(--color-codemirror-border); background: ${(props) => props.theme.codemirror.bg};
border: solid 1px ${(props) => props.theme.codemirror.border};
} }
textarea.cm-editor { textarea.cm-editor {
position: relative; position: relative;
} }
// Todo: dark mode temporary fix
// Clean this
.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute {
color: #9cdcfe !important;
}
.cm-s-monokai span.cm-string {
color: #ce9178 !important;
}
.cm-s-monokai span.cm-number{
color: #b5cea8 !important;
}
.cm-s-monokai span.cm-atom{
color: #569cd6 !important;
}
`; `;
export default StyledWrapper; export default StyledWrapper;

View File

@ -39,6 +39,7 @@ export default class QueryEditor extends React.Component {
foldGutter: true, foldGutter: true,
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'], gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
readOnly: this.props.readOnly ? 'nocursor' : false, readOnly: this.props.readOnly ? 'nocursor' : false,
theme: this.props.theme === 'dark' ? 'monokai' : 'default',
extraKeys: { extraKeys: {
'Cmd-Enter': () => { 'Cmd-Enter': () => {
if (this.props.onRun) { if (this.props.onRun) {
@ -87,6 +88,12 @@ export default class QueryEditor extends React.Component {
this.editor.setValue(this.props.value); this.editor.setValue(this.props.value);
this.editor.setOption('mode', this.props.mode); this.editor.setOption('mode', this.props.mode);
} }
if (this.props.theme !== prevProps.theme && this.editor) {
this.cachedValue = this.props.value;
this.editor.setValue(this.props.value);
this.editor.setOption('theme', this.props.theme === 'dark' ? 'monokai' : 'default');
}
this.ignoreChangeEvent = false; this.ignoreChangeEvent = false;
} }

View File

@ -2,7 +2,8 @@ import styled from 'styled-components';
const StyledWrapper = styled.div` const StyledWrapper = styled.div`
div.CodeMirror { div.CodeMirror {
border: solid 1px var(--color-codemirror-border); background: ${(props) => props.theme.codemirror.bg};
border: solid 1px ${(props) => props.theme.codemirror.border};
/* todo: find a better way */ /* todo: find a better way */
height: calc(100vh - 250px); height: calc(100vh - 250px);
} }

View File

@ -4,7 +4,7 @@ const Wrapper = styled.div`
font-size: 0.8125rem; font-size: 0.8125rem;
.body-mode-selector { .body-mode-selector {
background: #efefef; background: ${(props) => props.theme.requestTabPanel.bodyModeSelect.color};
border-radius: 3px; border-radius: 3px;
.dropdown-item { .dropdown-item {

View File

@ -4,6 +4,7 @@ import CodeEditor from 'components/CodeEditor';
import FormUrlEncodedParams from 'components/RequestPane/FormUrlEncodedParams'; import FormUrlEncodedParams from 'components/RequestPane/FormUrlEncodedParams';
import MultipartFormParams from 'components/RequestPane/MultipartFormParams'; import MultipartFormParams from 'components/RequestPane/MultipartFormParams';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { useTheme } from 'providers/Theme';
import { updateRequestBody } from 'providers/ReduxStore/slices/collections'; import { updateRequestBody } from 'providers/ReduxStore/slices/collections';
import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions'; import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions';
import StyledWrapper from './StyledWrapper'; import StyledWrapper from './StyledWrapper';
@ -12,6 +13,9 @@ const RequestBody = ({ item, collection }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const body = item.draft ? get(item, 'draft.request.body') : get(item, 'request.body'); const body = item.draft ? get(item, 'draft.request.body') : get(item, 'request.body');
const bodyMode = item.draft ? get(item, 'draft.request.body.mode') : get(item, 'request.body.mode'); const bodyMode = item.draft ? get(item, 'draft.request.body.mode') : get(item, 'request.body.mode');
const {
storedTheme
} = useTheme();
const onEdit = (value) => { const onEdit = (value) => {
dispatch( dispatch(
@ -41,7 +45,7 @@ const RequestBody = ({ item, collection }) => {
return ( return (
<StyledWrapper className="w-full"> <StyledWrapper className="w-full">
<CodeEditor value={bodyContent[bodyMode] || ''} onEdit={onEdit} onRun={onRun} onSave={onSave} mode={codeMirrorMode[bodyMode]} /> <CodeEditor theme={storedTheme} value={bodyContent[bodyMode] || ''} onEdit={onEdit} onRun={onRun} onSave={onSave} mode={codeMirrorMode[bodyMode]} />
</StyledWrapper> </StyledWrapper>
); );
} }

View File

@ -12,7 +12,7 @@ const Wrapper = styled.div`
} }
thead { thead {
color: ${(props) => props.theme.table.thead.color};; color: ${(props) => props.theme.table.thead.color};
font-size: 0.8125rem; font-size: 0.8125rem;
user-select: none; user-select: none;
} }
@ -23,8 +23,6 @@ const Wrapper = styled.div`
.btn-add-header { .btn-add-header {
font-size: 0.8125rem; font-size: 0.8125rem;
margin-block: 10px;
padding: 5px;
} }
input[type='text'] { input[type='text'] {

View File

@ -124,7 +124,7 @@ const RequestHeaders = ({ item, collection }) => {
: null} : null}
</tbody> </tbody>
</table> </table>
<button className="btn-add-header select-none" onClick={addHeader}> <button className="btn-add-header text-link pr-2 py-3 mt-2 select-none" onClick={addHeader}>
+ Add Header + Add Header
</button> </button>
</StyledWrapper> </StyledWrapper>

View File

@ -1,12 +1,17 @@
import React from 'react'; import React from 'react';
import CodeEditor from 'components/CodeEditor'; import CodeEditor from 'components/CodeEditor';
import { useTheme } from 'providers/Theme';
import StyledWrapper from './StyledWrapper'; import StyledWrapper from './StyledWrapper';
const QueryResult = ({ value, width }) => { const QueryResult = ({ value, width }) => {
const {
storedTheme
} = useTheme();
return ( return (
<StyledWrapper className="px-3 w-full" style={{ maxWidth: width }}> <StyledWrapper className="px-3 w-full" style={{ maxWidth: width }}>
<div className="h-full"> <div className="h-full">
<CodeEditor value={value || ''} readOnly /> <CodeEditor theme={storedTheme} value={value || ''} readOnly />
</div> </div>
</StyledWrapper> </StyledWrapper>
); );

View File

@ -22,7 +22,7 @@ const Wrapper = styled.div`
tbody { tbody {
tr:nth-child(odd) { tr:nth-child(odd) {
background-color: var(--color-table-stripe); background-color: ${(props) => props.theme.table.striped};
} }
} }
} }

View File

@ -2,8 +2,12 @@ import { createGlobalStyle } from 'styled-components';
const GlobalStyle = createGlobalStyle` const GlobalStyle = createGlobalStyle`
.CodeMirror-gutters { .CodeMirror-gutters {
background-color: var(--color-codemirror-background); background-color: ${(props) => props.theme.codemirror.gutter.bg} !important;
border-right: solid 1px var(--color-codemirror-border); border-right: solid 1px ${(props) => props.theme.codemirror.border};
}
.text-link {
color: ${(props) => props.theme.textLink};
} }
.btn { .btn {

View File

@ -6,6 +6,8 @@ import RequestTabPanel from 'components/RequestTabPanel';
import Sidebar from 'components/Sidebar'; import Sidebar from 'components/Sidebar';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import StyledWrapper from './StyledWrapper'; import StyledWrapper from './StyledWrapper';
import 'codemirror/theme/material.css';
import 'codemirror/theme/monokai.css';
const SERVER_RENDERED = typeof navigator === 'undefined' || global['PREVENT_CODEMIRROR_RENDER'] === true; const SERVER_RENDERED = typeof navigator === 'undefined' || global['PREVENT_CODEMIRROR_RENDER'] === true;
if (!SERVER_RENDERED) { if (!SERVER_RENDERED) {

View File

@ -9,8 +9,6 @@
--color-tab-inactive: rgb(155 155 155); --color-tab-inactive: rgb(155 155 155);
--color-tab-active-border: #546de5; --color-tab-active-border: #546de5;
--color-layout-border: #dedede; --color-layout-border: #dedede;
--color-codemirror-border: #efefef;
--color-codemirror-background: rgb(243, 243, 243);
--color-text-link: #1663bb; --color-text-link: #1663bb;
--color-text-danger: rgb(185, 28, 28); --color-text-danger: rgb(185, 28, 28);
--color-background-danger: #dc3545; --color-background-danger: #dc3545;
@ -21,7 +19,6 @@
--color-method-patch: rgb(52 52 52); --color-method-patch: rgb(52 52 52);
--color-method-options: rgb(52 52 52); --color-method-options: rgb(52 52 52);
--color-method-head: rgb(52 52 52); --color-method-head: rgb(52 52 52);
--color-table-stripe: #f3f3f3;
} }
html, body { html, body {
@ -53,7 +50,3 @@ body::-webkit-scrollbar-thumb, .CodeMirror-vscrollbar::-webkit-scrollbar-thumb {
background-color: #cdcdcd; background-color: #cdcdcd;
border-radius: 5rem; border-radius: 5rem;
} }
.text-link {
color: var(--color-text-link);
}

View File

@ -1,6 +1,7 @@
const darkTheme = { const darkTheme = {
brand: '#546de5', brand: '#546de5',
text: '#d4d4d4', text: '#d4d4d4',
textLink: '#569cd6',
bg: '#1e1e1e', bg: '#1e1e1e',
menubar: { menubar: {
@ -61,6 +62,9 @@ const darkTheme = {
dragbar: { dragbar: {
border: '#444', border: '#444',
activeBorder: '#8a8a8a' activeBorder: '#8a8a8a'
},
bodyModeSelect: {
color: 'transparent'
} }
}, },
@ -130,14 +134,19 @@ const darkTheme = {
}, },
codemirror: { codemirror: {
bg: '#1e1e1e',
border: 'transparent',
gutter: {
bg: '#1e1e1e'
}
}, },
table: { table: {
border: '#333', border: '#333',
thead : { thead : {
color: 'rgb(204, 204, 204)' color: 'rgb(204, 204, 204)'
} },
striped: '#2A2D2F'
}, },
'primary-text': '#ffffff', 'primary-text': '#ffffff',

View File

@ -1,6 +1,7 @@
const lightTheme = { const lightTheme = {
brand: '#546de5', brand: '#546de5',
text: 'rgb(52, 52, 52)', text: 'rgb(52, 52, 52)',
textLink: '#1663bb',
bg: '#fff', bg: '#fff',
menubar: { menubar: {
@ -61,6 +62,9 @@ const lightTheme = {
dragbar: { dragbar: {
border: '#efefef', border: '#efefef',
activeBorder: 'rgb(200, 200, 200)' activeBorder: 'rgb(200, 200, 200)'
},
bodyModeSelect: {
color: '#efefef'
} }
}, },
@ -104,7 +108,7 @@ const lightTheme = {
tabs: { tabs: {
active: { active: {
color: '${(props) => props.theme.tabs.active.color}', color: 'rgb(50, 46, 44)',
border: '#546de5' border: '#546de5'
} }
}, },
@ -130,14 +134,19 @@ const lightTheme = {
}, },
codemirror: { codemirror: {
bg: 'white',
border: '#efefef',
gutter: {
bg: '#f3f3f3'
}
}, },
table: { table: {
border: '#efefef', border: '#efefef',
thead : { thead : {
color: '#616161' color: '#616161'
} },
striped: '#f3f3f3'
}, },
'primary-text': 'rgb(52 52 52)', 'primary-text': 'rgb(52 52 52)',