mirror of
https://github.com/usebruno/bruno.git
synced 2024-12-23 15:19:01 +01:00
Features/dark mode (#37)
* Added use local storage hook * Added theme * Added theme support * Added theme provider * Added dark theme for sidebar * Added dark theme for main content area * Added theme * Added theme support * Added theme provider * Added dark theme for sidebar * Added dark theme for main content area
This commit is contained in:
parent
3c3c9a6026
commit
cbdfabb4db
30
packages/bruno-app/public/theme/dark.js
Normal file
30
packages/bruno-app/public/theme/dark.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
const darkTheme = {
|
||||||
|
brand: '#546de5',
|
||||||
|
text: 'rgb(52 52 52)',
|
||||||
|
'primary-text': '#ffffff',
|
||||||
|
'primary-theme': '#1e1e1e',
|
||||||
|
'secondary-text': '#929292',
|
||||||
|
'sidebar-collection-item-active-indent-border': '#d0d0d0',
|
||||||
|
'sidebar-collection-item-active-background': '#e1e1e1',
|
||||||
|
'sidebar-background': '#252526',
|
||||||
|
'sidebar-bottom-bg': '#68217a',
|
||||||
|
'request-dragbar-background': '#efefef',
|
||||||
|
'request-dragbar-background-active': 'rgb(200, 200, 200)',
|
||||||
|
'tab-inactive': 'rgb(155 155 155)',
|
||||||
|
'tab-active-border': '#546de5',
|
||||||
|
'layout-border': '#dedede',
|
||||||
|
'codemirror-border': '#efefef',
|
||||||
|
'codemirror-background': 'rgb(243, 243, 243)',
|
||||||
|
'text-link': '#1663bb',
|
||||||
|
'text-danger': 'rgb(185, 28, 28)',
|
||||||
|
'background-danger': '#dc3545',
|
||||||
|
'method-get': 'rgb(5, 150, 105)',
|
||||||
|
'method-post': '#8e44ad',
|
||||||
|
'method-delete': 'rgb(185, 28, 28)',
|
||||||
|
'method-patch': 'rgb(52 52 52)',
|
||||||
|
'method-options': 'rgb(52 52 52)',
|
||||||
|
'method-head': 'rgb(52 52 52)',
|
||||||
|
'table-stripe': '#f3f3f3'
|
||||||
|
};
|
||||||
|
|
||||||
|
export default darkTheme;
|
7
packages/bruno-app/public/theme/index.js
Normal file
7
packages/bruno-app/public/theme/index.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import darkTheme from './dark';
|
||||||
|
import lightTheme from './light';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
Light: lightTheme,
|
||||||
|
Dark: darkTheme
|
||||||
|
};
|
30
packages/bruno-app/public/theme/light.js
Normal file
30
packages/bruno-app/public/theme/light.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
const lightTheme = {
|
||||||
|
brand: '#546de5',
|
||||||
|
text: 'rgb(52 52 52)',
|
||||||
|
'primary-text': 'rgb(52 52 52)',
|
||||||
|
'primary-theme': '#ffffff',
|
||||||
|
'secondary-text': '#929292',
|
||||||
|
'sidebar-collection-item-active-indent-border': '#d0d0d0',
|
||||||
|
'sidebar-collection-item-active-background': '#e1e1e1',
|
||||||
|
'sidebar-background': '#f3f3f3',
|
||||||
|
'sidebar-bottom-bg': '#f3f3f3',
|
||||||
|
'request-dragbar-background': '#efefef',
|
||||||
|
'request-dragbar-background-active': 'rgb(200, 200, 200)',
|
||||||
|
'tab-inactive': 'rgb(155 155 155)',
|
||||||
|
'tab-active-border': '#546de5',
|
||||||
|
'layout-border': '#dedede',
|
||||||
|
'codemirror-border': '#efefef',
|
||||||
|
'codemirror-background': 'rgb(243, 243, 243)',
|
||||||
|
'text-link': '#1663bb',
|
||||||
|
'text-danger': 'rgb(185, 28, 28)',
|
||||||
|
'background-danger': '#dc3545',
|
||||||
|
'method-get': 'rgb(5, 150, 105)',
|
||||||
|
'method-post': '#8e44ad',
|
||||||
|
'method-delete': 'rgb(185, 28, 28)',
|
||||||
|
'method-patch': 'rgb(52 52 52)',
|
||||||
|
'method-options': 'rgb(52 52 52)',
|
||||||
|
'method-head': 'rgb(52 52 52)',
|
||||||
|
'table-stripe': '#f3f3f3'
|
||||||
|
};
|
||||||
|
|
||||||
|
export default lightTheme;
|
@ -1,12 +1,20 @@
|
|||||||
import React, { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import toast from 'react-hot-toast';
|
import { useTheme } from '../../../../providers/Theme';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import CreateCollection from 'components/Sidebar/CreateCollection';
|
|
||||||
import SelectCollection from 'components/Sidebar/Collections/SelectCollection';
|
|
||||||
import { createCollection } from 'providers/ReduxStore/slices/collections/actions';
|
import { createCollection } from 'providers/ReduxStore/slices/collections/actions';
|
||||||
import { addCollectionToWorkspace } from 'providers/ReduxStore/slices/workspaces/actions';
|
import { addCollectionToWorkspace } from 'providers/ReduxStore/slices/workspaces/actions';
|
||||||
|
|
||||||
|
import toast from 'react-hot-toast';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import CreateCollection from 'components/Sidebar/CreateCollection';
|
||||||
|
import SelectCollection from 'components/Sidebar/Collections/SelectCollection';
|
||||||
|
|
||||||
|
const LinkStyle = styled.span`
|
||||||
|
color: ${(props) => props.theme['text-link']};
|
||||||
|
`;
|
||||||
|
|
||||||
const CreateOrAddCollection = () => {
|
const CreateOrAddCollection = () => {
|
||||||
|
const { theme } = useTheme();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [createCollectionModalOpen, setCreateCollectionModalOpen] = useState(false);
|
const [createCollectionModalOpen, setCreateCollectionModalOpen] = useState(false);
|
||||||
const [addCollectionToWSModalOpen, setAddCollectionToWSModalOpen] = useState(false);
|
const [addCollectionToWSModalOpen, setAddCollectionToWSModalOpen] = useState(false);
|
||||||
@ -31,14 +39,14 @@ const CreateOrAddCollection = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const CreateLink = () => (
|
const CreateLink = () => (
|
||||||
<span className="underline text-link cursor-pointer" onClick={() => setCreateCollectionModalOpen(true)}>
|
<LinkStyle className="underline text-link cursor-pointer" theme={theme} onClick={() => setCreateCollectionModalOpen(true)}>
|
||||||
Create
|
Create
|
||||||
</span>
|
</LinkStyle>
|
||||||
);
|
);
|
||||||
const AddLink = () => (
|
const AddLink = () => (
|
||||||
<span className="underline text-link cursor-pointer" onClick={() => setAddCollectionToWSModalOpen(true)}>
|
<LinkStyle className="underline text-link cursor-pointer" theme={theme} onClick={() => setAddCollectionToWSModalOpen(true)}>
|
||||||
Add
|
Add
|
||||||
</span>
|
</LinkStyle>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
import React, { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import Link from 'next/link';
|
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { IconCode, IconFiles, IconUser, IconUsers, IconSettings, IconChevronsLeft, IconLifebuoy } from '@tabler/icons';
|
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import { toggleLeftMenuBar } from 'providers/ReduxStore/slices/app';
|
|
||||||
import BrunoSupport from 'components/BrunoSupport';
|
|
||||||
import { isElectron } from 'utils/common/platform';
|
import { isElectron } from 'utils/common/platform';
|
||||||
|
import { toggleLeftMenuBar } from 'providers/ReduxStore/slices/app';
|
||||||
|
import { IconCode, IconFiles, IconMoon, IconChevronsLeft, IconLifebuoy } from '@tabler/icons';
|
||||||
|
|
||||||
|
import Link from 'next/link';
|
||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
import BrunoSupport from 'components/BrunoSupport';
|
||||||
|
import ThemeSupport from 'components/ThemeSupport/index';
|
||||||
|
|
||||||
const MenuBar = () => {
|
const MenuBar = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
const [openTheme, setOpenTheme] = useState(false);
|
||||||
const [openBrunoSupport, setOpenBrunoSupport] = useState(false);
|
const [openBrunoSupport, setOpenBrunoSupport] = useState(false);
|
||||||
const isPlatformElectron = isElectron();
|
const isPlatformElectron = isElectron();
|
||||||
|
|
||||||
@ -46,11 +49,15 @@ const MenuBar = () => {
|
|||||||
<div className="menu-item">
|
<div className="menu-item">
|
||||||
<IconLifebuoy size={28} strokeWidth={1.5} onClick={() => setOpenBrunoSupport(true)} />
|
<IconLifebuoy size={28} strokeWidth={1.5} onClick={() => setOpenBrunoSupport(true)} />
|
||||||
</div>
|
</div>
|
||||||
|
<div className="menu-item">
|
||||||
|
<IconMoon size={28} strokeWidth={1.5} onClick={() => setOpenTheme(true)} />
|
||||||
|
</div>
|
||||||
<div className="menu-item" onClick={() => dispatch(toggleLeftMenuBar())}>
|
<div className="menu-item" onClick={() => dispatch(toggleLeftMenuBar())}>
|
||||||
<IconChevronsLeft size={28} strokeWidth={1.5} />
|
<IconChevronsLeft size={28} strokeWidth={1.5} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{openBrunoSupport && <BrunoSupport onClose={() => setOpenBrunoSupport(false)} />}
|
{openBrunoSupport && <BrunoSupport onClose={() => setOpenBrunoSupport(false)} />}
|
||||||
|
{openTheme && <ThemeSupport onClose={() => setOpenTheme(false)} />}
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -2,7 +2,7 @@ import styled from 'styled-components';
|
|||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
aside {
|
aside {
|
||||||
background-color: var(--color-sidebar-background);
|
background-color: ${(props) => props.theme.theme['sidebar-background']};
|
||||||
|
|
||||||
.collection-title {
|
.collection-title {
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
@ -45,4 +45,12 @@ const Wrapper = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const BottomWrapper = styled.div`
|
||||||
|
background-color: ${(props) => props.theme.theme['sidebar-bottom-bg']};
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const VersionNumber = styled.div`
|
||||||
|
color: ${(props) => props.theme.theme['primary-text']};
|
||||||
|
`;
|
||||||
|
|
||||||
export default Wrapper;
|
export default Wrapper;
|
||||||
|
@ -25,4 +25,8 @@ const StyledWrapper = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const SiteTitle = styled.div`
|
||||||
|
color: ${(props) => props.theme.theme['primary-text']};
|
||||||
|
`;
|
||||||
|
|
||||||
export default StyledWrapper;
|
export default StyledWrapper;
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
import React, { useState, forwardRef, useRef } from 'react';
|
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import Dropdown from 'components/Dropdown';
|
|
||||||
import Bruno from 'components/Bruno';
|
import Bruno from 'components/Bruno';
|
||||||
|
import Dropdown from 'components/Dropdown';
|
||||||
|
import CreateCollection from '../CreateCollection';
|
||||||
|
import importCollection from 'utils/collections/import';
|
||||||
|
import SelectCollection from 'components/Sidebar/Collections/SelectCollection';
|
||||||
|
|
||||||
|
import { IconDots } from '@tabler/icons';
|
||||||
import { IconFolders } from '@tabler/icons';
|
import { IconFolders } from '@tabler/icons';
|
||||||
|
import { isElectron } from 'utils/common/platform';
|
||||||
|
import { useState, forwardRef, useRef } from 'react';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
|
import StyledWrapper, { SiteTitle } from './StyledWrapper';
|
||||||
|
import { showHomePage } from 'providers/ReduxStore/slices/app';
|
||||||
import { collectionImported } from 'providers/ReduxStore/slices/collections';
|
import { collectionImported } from 'providers/ReduxStore/slices/collections';
|
||||||
import { openLocalCollection } from 'providers/ReduxStore/slices/collections/actions';
|
import { openLocalCollection } from 'providers/ReduxStore/slices/collections/actions';
|
||||||
import { addCollectionToWorkspace } from 'providers/ReduxStore/slices/workspaces/actions';
|
import { addCollectionToWorkspace } from 'providers/ReduxStore/slices/workspaces/actions';
|
||||||
import { showHomePage } from 'providers/ReduxStore/slices/app';
|
|
||||||
import { IconDots } from '@tabler/icons';
|
|
||||||
import CreateCollection from '../CreateCollection';
|
|
||||||
import SelectCollection from 'components/Sidebar/Collections/SelectCollection';
|
|
||||||
import importCollection from 'utils/collections/import';
|
|
||||||
import { isElectron } from 'utils/common/platform';
|
|
||||||
import StyledWrapper from './StyledWrapper';
|
|
||||||
|
|
||||||
const TitleBar = () => {
|
const TitleBar = () => {
|
||||||
const [createCollectionModalOpen, setCreateCollectionModalOpen] = useState(false);
|
const [createCollectionModalOpen, setCreateCollectionModalOpen] = useState(false);
|
||||||
@ -68,13 +69,13 @@ const TitleBar = () => {
|
|||||||
<div className="flex items-center cursor-pointer" onClick={handleTitleClick}>
|
<div className="flex items-center cursor-pointer" onClick={handleTitleClick}>
|
||||||
<Bruno width={30} />
|
<Bruno width={30} />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<SiteTitle
|
||||||
onClick={handleTitleClick}
|
onClick={handleTitleClick}
|
||||||
className=" flex items-center font-medium select-none cursor-pointer"
|
className=" flex items-center font-medium select-none cursor-pointer"
|
||||||
style={{ fontSize: 14, paddingLeft: 6, position: 'relative', top: -1 }}
|
style={{ fontSize: 14, paddingLeft: 6, position: 'relative', top: -1 }}
|
||||||
>
|
>
|
||||||
bruno
|
bruno
|
||||||
</div>
|
</SiteTitle>
|
||||||
<div className="collection-dropdown flex flex-grow items-center justify-end">
|
<div className="collection-dropdown flex flex-grow items-center justify-end">
|
||||||
<Dropdown onCreate={onMenuDropdownCreate} icon={<MenuIcon />} placement="bottom-start">
|
<Dropdown onCreate={onMenuDropdownCreate} icon={<MenuIcon />} placement="bottom-start">
|
||||||
<div
|
<div
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import MenuBar from './MenuBar';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import TitleBar from './TitleBar';
|
||||||
import Collections from './Collections';
|
import Collections from './Collections';
|
||||||
import LocalCollections from './LocalCollections';
|
import LocalCollections from './LocalCollections';
|
||||||
import TitleBar from './TitleBar';
|
import StyledWrapper, { BottomWrapper, VersionNumber } from './StyledWrapper';
|
||||||
import MenuBar from './MenuBar';
|
import WorkspaceSelector from 'components/Workspaces/WorkspaceSelector';
|
||||||
|
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import { IconSearch, IconChevronsRight } from '@tabler/icons';
|
import { IconSearch, IconChevronsRight } from '@tabler/icons';
|
||||||
import { updateLeftSidebarWidth, updateIsDragging, toggleLeftMenuBar } from 'providers/ReduxStore/slices/app';
|
import { updateLeftSidebarWidth, updateIsDragging, toggleLeftMenuBar } from 'providers/ReduxStore/slices/app';
|
||||||
import StyledWrapper from './StyledWrapper';
|
|
||||||
import WorkspaceSelector from 'components/Workspaces/WorkspaceSelector';
|
|
||||||
|
|
||||||
const MIN_LEFT_SIDEBAR_WIDTH = 222;
|
const MIN_LEFT_SIDEBAR_WIDTH = 222;
|
||||||
const MAX_LEFT_SIDEBAR_WIDTH = 600;
|
const MAX_LEFT_SIDEBAR_WIDTH = 600;
|
||||||
@ -106,7 +107,8 @@ const Sidebar = () => {
|
|||||||
<Collections searchText={searchText} />
|
<Collections searchText={searchText} />
|
||||||
<LocalCollections searchText={searchText} />
|
<LocalCollections searchText={searchText} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex px-1 py-2 items-center cursor-pointer text-gray-500 select-none">
|
|
||||||
|
<BottomWrapper className="flex px-1 py-2 items-center cursor-pointer text-gray-500 select-none">
|
||||||
<div className="flex items-center ml-1 text-xs ">
|
<div className="flex items-center ml-1 text-xs ">
|
||||||
{!leftMenuBarOpen && <IconChevronsRight size={24} strokeWidth={1.5} className="mr-2 hover:text-gray-700" onClick={() => dispatch(toggleLeftMenuBar())} />}
|
{!leftMenuBarOpen && <IconChevronsRight size={24} strokeWidth={1.5} className="mr-2 hover:text-gray-700" onClick={() => dispatch(toggleLeftMenuBar())} />}
|
||||||
{/* <IconLayoutGrid size={20} strokeWidth={1.5} className="mr-2"/> */}
|
{/* <IconLayoutGrid size={20} strokeWidth={1.5} className="mr-2"/> */}
|
||||||
@ -122,8 +124,8 @@ const Sidebar = () => {
|
|||||||
title="GitHub"
|
title="GitHub"
|
||||||
></iframe>
|
></iframe>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-grow items-center justify-end text-xs mr-2">v1.25.2</div>
|
<VersionNumber className="flex flex-grow items-center justify-end text-xs mr-2">v1.25.2</VersionNumber>
|
||||||
</div>
|
</BottomWrapper>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
const StyledWrapper = styled.div`
|
||||||
|
color: var(--color-text);
|
||||||
|
.collection-options {
|
||||||
|
svg {
|
||||||
|
position: relative;
|
||||||
|
top: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default StyledWrapper;
|
32
packages/bruno-app/src/components/ThemeSupport/index.js
Normal file
32
packages/bruno-app/src/components/ThemeSupport/index.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Modal from 'components/Modal/index';
|
||||||
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
import { useTheme } from 'styled-components';
|
||||||
|
|
||||||
|
const ThemeSupport = ({ onClose }) => {
|
||||||
|
const { storedTheme, themeKeys, setStoredTheme } = useTheme();
|
||||||
|
|
||||||
|
const handleThemeChange = (e) => {
|
||||||
|
setStoredTheme(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledWrapper>
|
||||||
|
<Modal size="sm" title={'Support'} handleCancel={onClose} hideFooter={true}>
|
||||||
|
<div className="collection-options">
|
||||||
|
<select name="theme_switcher" onChange={handleThemeChange} defaultValue={storedTheme}>
|
||||||
|
{themeKeys.map((tk, index) => {
|
||||||
|
return (
|
||||||
|
<option value={tk} key={index}>
|
||||||
|
{tk}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</StyledWrapper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ThemeSupport;
|
@ -1,6 +1,8 @@
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
const StyledWrapper = styled.div`
|
const StyledWrapper = styled.div`
|
||||||
|
color: ${(props) => props.theme.theme['primary-text']};
|
||||||
|
|
||||||
.create-request {
|
.create-request {
|
||||||
color: #737373;
|
color: #737373;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
@ -21,4 +23,8 @@ const StyledWrapper = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const SiteTitle = styled.div`
|
||||||
|
color: ${(props) => props.theme.theme['primary-text']};
|
||||||
|
`;
|
||||||
|
|
||||||
export default StyledWrapper;
|
export default StyledWrapper;
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
import React, { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import { IconPlus, IconUpload, IconFiles, IconFolders, IconPlayerPlay, IconBrandChrome, IconSpeakerphone, IconDeviceDesktop } from '@tabler/icons';
|
import { isElectron } from 'utils/common/platform';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import { collectionImported } from 'providers/ReduxStore/slices/collections';
|
import { collectionImported } from 'providers/ReduxStore/slices/collections';
|
||||||
import { openLocalCollection } from 'providers/ReduxStore/slices/collections/actions';
|
import { openLocalCollection } from 'providers/ReduxStore/slices/collections/actions';
|
||||||
import { addCollectionToWorkspace } from 'providers/ReduxStore/slices/workspaces/actions';
|
import { addCollectionToWorkspace } from 'providers/ReduxStore/slices/workspaces/actions';
|
||||||
|
import { IconPlus, IconUpload, IconFiles, IconFolders, IconPlayerPlay, IconBrandChrome, IconSpeakerphone, IconDeviceDesktop } from '@tabler/icons';
|
||||||
|
|
||||||
import Bruno from 'components/Bruno';
|
import Bruno from 'components/Bruno';
|
||||||
|
import GithubSvg from 'assets/github.svg';
|
||||||
|
import StyledWrapper, { SiteTitle } from './StyledWrapper';
|
||||||
import CreateCollection from 'components/Sidebar/CreateCollection';
|
import CreateCollection from 'components/Sidebar/CreateCollection';
|
||||||
import SelectCollection from 'components/Sidebar/Collections/SelectCollection';
|
import SelectCollection from 'components/Sidebar/Collections/SelectCollection';
|
||||||
import importCollection, { importSampleCollection } from 'utils/collections/import';
|
import importCollection, { importSampleCollection } from 'utils/collections/import';
|
||||||
import { isElectron } from 'utils/common/platform';
|
|
||||||
import GithubSvg from 'assets/github.svg';
|
|
||||||
import StyledWrapper from './StyledWrapper';
|
|
||||||
|
|
||||||
const Welcome = () => {
|
const Welcome = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@ -66,7 +67,7 @@ const Welcome = () => {
|
|||||||
<div className="">
|
<div className="">
|
||||||
<Bruno width={50} />
|
<Bruno width={50} />
|
||||||
</div>
|
</div>
|
||||||
<div className="text-xl font-semibold select-none">bruno</div>
|
<SiteTitle className="text-xl font-semibold select-none">bruno</SiteTitle>
|
||||||
<div className="mt-4">Opensource API Client.</div>
|
<div className="mt-4">Opensource API Client.</div>
|
||||||
|
|
||||||
<div className="uppercase font-semibold create-request mt-10">Collections</div>
|
<div className="uppercase font-semibold create-request mt-10">Collections</div>
|
||||||
|
@ -6,6 +6,8 @@ const Wrapper = styled.div`
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
|
||||||
|
background-color: ${(props) => props.theme.theme['primary-theme']};
|
||||||
|
|
||||||
&.is-dragging {
|
&.is-dragging {
|
||||||
cursor: col-resize !important;
|
cursor: col-resize !important;
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
import { HotkeysProvider } from 'providers/Hotkeys';
|
|
||||||
import { AuthProvider } from 'providers/Auth';
|
|
||||||
import { AppProvider } from 'providers/App';
|
|
||||||
import ReduxStore from 'providers/ReduxStore';
|
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import { Toaster } from 'react-hot-toast';
|
import { Toaster } from 'react-hot-toast';
|
||||||
|
import { AppProvider } from 'providers/App';
|
||||||
|
import { AuthProvider } from 'providers/Auth';
|
||||||
|
import { HotkeysProvider } from 'providers/Hotkeys';
|
||||||
|
|
||||||
|
import ReduxStore from 'providers/ReduxStore';
|
||||||
|
import ThemeProvider from 'providers/Theme/index';
|
||||||
|
|
||||||
|
import '../styles/app.scss';
|
||||||
import '../styles/globals.css';
|
import '../styles/globals.css';
|
||||||
import 'tailwindcss/dist/tailwind.min.css';
|
import 'tailwindcss/dist/tailwind.min.css';
|
||||||
import 'react-tabs/style/react-tabs.css';
|
import 'react-tabs/style/react-tabs.css';
|
||||||
import 'codemirror/lib/codemirror.css';
|
import 'codemirror/lib/codemirror.css';
|
||||||
import 'graphiql/graphiql.min.css';
|
import 'graphiql/graphiql.min.css';
|
||||||
|
|
||||||
import '../styles/app.scss';
|
|
||||||
|
|
||||||
function SafeHydrate({ children }) {
|
function SafeHydrate({ children }) {
|
||||||
return <div suppressHydrationWarning>{typeof window === 'undefined' ? null : children}</div>;
|
return <div suppressHydrationWarning>{typeof window === 'undefined' ? null : children}</div>;
|
||||||
}
|
}
|
||||||
@ -33,10 +34,12 @@ function MyApp({ Component, pageProps }) {
|
|||||||
<NoSsr>
|
<NoSsr>
|
||||||
<Provider store={ReduxStore}>
|
<Provider store={ReduxStore}>
|
||||||
<AppProvider>
|
<AppProvider>
|
||||||
|
<ThemeProvider>
|
||||||
<HotkeysProvider>
|
<HotkeysProvider>
|
||||||
<Toaster toastOptions={{ duration: 2000 }} />
|
<Toaster toastOptions={{ duration: 2000 }} />
|
||||||
<Component {...pageProps} />
|
<Component {...pageProps} />
|
||||||
</HotkeysProvider>
|
</HotkeysProvider>
|
||||||
|
</ThemeProvider>
|
||||||
</AppProvider>
|
</AppProvider>
|
||||||
</Provider>
|
</Provider>
|
||||||
</NoSsr>
|
</NoSsr>
|
||||||
|
37
packages/bruno-app/src/providers/Theme/index.js
Normal file
37
packages/bruno-app/src/providers/Theme/index.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import ThemeManager from '../../../public/theme/index';
|
||||||
|
import useLocalStorage from 'src/hooks/useLocalStorage/index';
|
||||||
|
|
||||||
|
import { createContext, useContext } from 'react';
|
||||||
|
import { ThemeProvider as SCThemeProvider } from 'styled-components';
|
||||||
|
|
||||||
|
export const ThemeContext = createContext();
|
||||||
|
export const ThemeProvider = (props) => {
|
||||||
|
const [storedTheme, setStoredTheme] = useLocalStorage('bruno.theme', 'Light');
|
||||||
|
|
||||||
|
const theme = ThemeManager[storedTheme];
|
||||||
|
const themeKeys = Object.keys(ThemeManager);
|
||||||
|
const value = {
|
||||||
|
theme,
|
||||||
|
themeKeys,
|
||||||
|
storedTheme,
|
||||||
|
setStoredTheme
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeContext.Provider value={value}>
|
||||||
|
<SCThemeProvider theme={value} {...props} />
|
||||||
|
</ThemeContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useTheme = () => {
|
||||||
|
const context = useContext(ThemeContext);
|
||||||
|
|
||||||
|
if (context === undefined) {
|
||||||
|
throw new Error(`useTheme must be used within a ThemeProvider`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ThemeProvider;
|
Loading…
Reference in New Issue
Block a user