Commit 245f505d authored by tom's avatar tom

use theme colors in custom components

parent 20b5f062
import { Flex, Box, useColorModeValue } from '@chakra-ui/react';
import { Flex, Box } from '@chakra-ui/react';
import React from 'react';
import stripLeadingSlash from 'lib/stripLeadingSlash';
import * as themes from 'ui/shared/monaco/utils/themes';
import useThemeColors from 'ui/shared/monaco/utils/useThemeColors';
interface Props {
path: string;
......@@ -10,12 +10,12 @@ interface Props {
const CodeEditorBreadcrumbs = ({ path }: Props) => {
const chunks = stripLeadingSlash(path).split('/');
const bgColor = useColorModeValue(themes.light.colors['editor.background'], themes.dark.colors['editor.background']);
const themeColors = useThemeColors();
return (
<Flex
color="text_secondary"
bgColor={ bgColor }
color={ themeColors['breadcrumbs.foreground'] }
bgColor={ themeColors['editor.background'] }
pl="16px"
pr="8px"
flexWrap="wrap"
......
import type { ChakraProps } from '@chakra-ui/react';
import { Accordion, AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, Icon, chakra, useColorModeValue } from '@chakra-ui/react';
import { Accordion, AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, Icon, chakra } from '@chakra-ui/react';
import React from 'react';
import type { FileTree } from './types';
......@@ -8,7 +8,7 @@ import iconFile from './icons/file.svg';
import iconFolderOpen from './icons/folder-open.svg';
import iconFolder from './icons/folder.svg';
import iconSolidity from './icons/solidity.svg';
import useColors from './utils/useColors';
import useThemeColors from './utils/useThemeColors';
interface Props {
tree: FileTree;
......@@ -27,8 +27,7 @@ const CodeEditorFileTree = ({ tree, level = 0, onItemClick, isCollapsed, selecte
borderBottomWidth: '0px',
},
};
const rowHoverBgColor = useColorModeValue('blackAlpha.200', 'whiteAlpha.200');
const colors = useColors();
const themeColors = useThemeColors();
return (
<Accordion allowMultiple defaultIndex={ isCollapsed ? undefined : tree.map((item, index) => index) } reduceMotion>
......@@ -45,13 +44,13 @@ const CodeEditorFileTree = ({ tree, level = 0, onItemClick, isCollapsed, selecte
pr="8px"
py="0"
pl={ `${ 8 + 8 * level }px` }
_hover={{ bgColor: rowHoverBgColor }}
_hover={{ bgColor: themeColors['list.hoverBackground'] }}
fontSize="13px"
lineHeight="22px"
h="22px"
transitionDuration="0"
>
<AccordionIcon transform={ isExpanded ? 'rotate(0deg)' : 'rotate(-90deg)' } boxSize="16px" color={ colors.buttons.color }/>
<AccordionIcon transform={ isExpanded ? 'rotate(0deg)' : 'rotate(-90deg)' } boxSize="16px" color={ themeColors['icon.foreground'] }/>
<Icon as={ isExpanded ? iconFolderOpen : iconFolder } boxSize="16px" mr="4px"/>
{ leafName }
</AccordionButton>
......@@ -84,9 +83,9 @@ const CodeEditorFileTree = ({ tree, level = 0, onItemClick, isCollapsed, selecte
alignItems="center"
overflow="hidden"
_hover={{
bgColor: selectedFile === leaf.file_path ? colors.selection.bgColorSelected : rowHoverBgColor,
bgColor: selectedFile === leaf.file_path ? themeColors['list.inactiveSelectionBackground'] : themeColors['list.hoverBackground'],
}}
bgColor={ selectedFile === leaf.file_path ? colors.selection.bgColorSelected : 'none' }
bgColor={ selectedFile === leaf.file_path ? themeColors['list.inactiveSelectionBackground'] : 'none' }
>
<Icon as={ icon } boxSize="16px" mr="4px"/>
{ leafName }
......
import type { ChakraProps } from '@chakra-ui/react';
import { Accordion, Box, Input, InputGroup, InputRightElement, useColorModeValue, useBoolean } from '@chakra-ui/react';
import { Accordion, Box, Input, InputGroup, InputRightElement, useBoolean } from '@chakra-ui/react';
import React from 'react';
import type { File, Monaco, SearchResult } from './types';
......@@ -8,7 +8,7 @@ import useDebounce from 'lib/hooks/useDebounce';
import CodeEditorSearchSection from './CodeEditorSearchSection';
import CoderEditorCollapseButton from './CoderEditorCollapseButton';
import useColors from './utils/useColors';
import useThemeColors from './utils/useThemeColors';
interface Props {
data: Array<File>;
......@@ -25,6 +25,8 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) =
const [ isMatchWholeWord, setMatchWholeWord ] = useBoolean();
const [ isMatchRegex, setMatchRegex ] = useBoolean();
const themeColors = useThemeColors();
const debouncedSearchTerm = useDebounce(searchTerm, 300);
React.useEffect(() => {
......@@ -76,11 +78,6 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) =
}
}, [ expandedSections.length, searchResults ]);
const inputColor = useColorModeValue('rgb(97, 97, 97)', 'rgb(204, 204, 204)');
const inputBgColor = useColorModeValue('white', 'rgb(60, 60, 60)');
const inputFocusBorderColor = useColorModeValue('#0090f1', '#007fd4');
const buttonActiveBgColor = useColorModeValue('rgba(0, 144, 241, 0.2)', 'rgba(0, 127, 212, 0.4)');
const colors = useColors();
const buttonProps: ChakraProps = {
boxSize: '20px',
p: '1px',
......@@ -126,7 +123,7 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) =
top="35px"
left="0"
zIndex="2"
bgColor={ colors.panels.bgColor }
bgColor={ themeColors['sideBar.background'] }
pb="8px"
boxShadow={ isInputStuck ? 'md' : 'none' }
>
......@@ -136,18 +133,18 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) =
value={ searchTerm }
placeholder="Search"
variant="unstyled"
color={ inputColor }
bgColor={ inputBgColor }
color={ themeColors['input.foreground'] }
bgColor={ themeColors['input.background'] }
borderRadius="none"
fontSize="13px"
lineHeight="20px"
borderWidth="1px"
borderColor={ inputBgColor }
borderColor={ themeColors['input.background'] }
py="2px"
px="4px"
transitionDuration="0"
_focus={{
borderColor: inputFocusBorderColor,
borderColor: themeColors.focusBorder,
}}
/>
<InputRightElement w="auto" h="auto" right="12px" top="3px" columnGap="2px">
......@@ -155,26 +152,26 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) =
{ ...buttonProps }
className="codicon codicon-case-sensitive"
onClick={ setMatchCase.toggle }
bgColor={ isMatchCase ? buttonActiveBgColor : 'transparent' }
_hover={{ bgColor: isMatchCase ? buttonActiveBgColor : colors.buttons.bgColorHover }}
bgColor={ isMatchCase ? themeColors['inputOption.activeBackground'] : 'transparent' }
_hover={{ bgColor: isMatchCase ? themeColors['inputOption.activeBackground'] : themeColors['inputOption.hoverBackground'] }}
title="Match Case"
aria-label="Match Case"
/>
<Box
{ ...buttonProps }
className="codicon codicon-whole-word"
bgColor={ isMatchWholeWord ? buttonActiveBgColor : 'transparent' }
bgColor={ isMatchWholeWord ? themeColors['inputOption.activeBackground'] : 'transparent' }
onClick={ setMatchWholeWord.toggle }
_hover={{ bgColor: isMatchWholeWord ? buttonActiveBgColor : colors.buttons.bgColorHover }}
_hover={{ bgColor: isMatchWholeWord ? themeColors['inputOption.activeBackground'] : themeColors['inputOption.hoverBackground'] }}
title="Match Whole Word"
aria-label="Match Whole Word"
/>
<Box
{ ...buttonProps }
className="codicon codicon-regex"
bgColor={ isMatchRegex ? buttonActiveBgColor : 'transparent' }
bgColor={ isMatchRegex ? themeColors['inputOption.activeBackground'] : 'transparent' }
onClick={ setMatchRegex.toggle }
_hover={{ bgColor: isMatchRegex ? buttonActiveBgColor : colors.buttons.bgColorHover }}
_hover={{ bgColor: isMatchRegex ? themeColors['inputOption.activeBackground'] : themeColors['inputOption.hoverBackground'] }}
title="Use Regular Expression"
aria-label="Use Regular Expression"
/>
......
import { Box, chakra, useColorModeValue } from '@chakra-ui/react';
import { Box, chakra } from '@chakra-ui/react';
import React from 'react';
import type { SearchResult } from './types';
import type ArrayElement from 'types/utils/ArrayElement';
import useThemeColors from './utils/useThemeColors';
interface Props extends ArrayElement<SearchResult['matches']> {
filePath: string;
onClick: (event: React.MouseEvent) => void;
......@@ -27,7 +29,7 @@ const calculateStartPosition = (lineContent: string, startColumn: number) => {
const CodeEditorSearchResultItem = ({ lineContent, filePath, onClick, startLineNumber, startColumn, endColumn }: Props) => {
const start = calculateStartPosition(lineContent, startColumn);
const rowHoverBgColor = useColorModeValue('blackAlpha.200', 'whiteAlpha.200');
const themeColors = useThemeColors();
return (
<Box
......@@ -43,10 +45,12 @@ const CodeEditorSearchResultItem = ({ lineContent, filePath, onClick, startLineN
data-line-number={ startLineNumber }
onClick={ onClick }
transitionDuration="0"
_hover={{ bgColor: rowHoverBgColor }}
_hover={{ bgColor: themeColors['list.hoverBackground'] }}
>
<span>{ lineContent.slice(start, startColumn - 1) }</span>
<chakra.span bgColor="rgba(234, 92, 0, 0.33)">{ lineContent.slice(startColumn - 1, endColumn - 1) }</chakra.span>
<chakra.span bgColor={ themeColors['editor.findMatchHighlightBackground'] }>
{ lineContent.slice(startColumn - 1, endColumn - 1) }
</chakra.span>
<span>{ lineContent.slice(endColumn - 1) }</span>
</Box>
);
......
import { AccordionButton, AccordionItem, AccordionIcon, AccordionPanel, useColorModeValue, Icon, Box } from '@chakra-ui/react';
import { AccordionButton, AccordionItem, AccordionIcon, AccordionPanel, Icon, Box } from '@chakra-ui/react';
import React from 'react';
import type { SearchResult } from './types';
......@@ -7,7 +7,7 @@ import CodeEditorSearchResultItem from './CodeEditorSearchResultItem';
import iconFile from './icons/file.svg';
import iconSolidity from './icons/solidity.svg';
import getFileName from './utils/getFileName';
import useColors from './utils/useColors';
import useThemeColors from './utils/useThemeColors';
interface Props {
data: SearchResult;
......@@ -24,11 +24,9 @@ const CodeEditorSearchSection = ({ data, onItemClick }: Props) => {
}
}, [ data.file_path, onItemClick ]);
const rowHoverBgColor = useColorModeValue('blackAlpha.200', 'whiteAlpha.200');
const icon = /.sol|.yul|.vy$/.test(fileName) ? iconSolidity : iconFile;
const badgeBgColor = useColorModeValue('#c4c4c4', '#4d4d4d');
const colors = useColors();
const themeColors = useThemeColors();
return (
<AccordionItem borderWidth="0px" _last={{ borderBottomWidth: '0px' }} >
......@@ -37,16 +35,16 @@ const CodeEditorSearchSection = ({ data, onItemClick }: Props) => {
<AccordionButton
py={ 0 }
px={ 2 }
_hover={{ bgColor: rowHoverBgColor }}
_hover={{ bgColor: themeColors['list.hoverBackground'] }}
fontSize="13px"
transitionDuration="0"
lineHeight="22px"
alignItems="center"
>
<AccordionIcon transform={ isExpanded ? 'rotate(0deg)' : 'rotate(-90deg)' } boxSize="16px" color={ colors.buttons.color }/>
<AccordionIcon transform={ isExpanded ? 'rotate(0deg)' : 'rotate(-90deg)' } boxSize="16px" color={ themeColors['icon.foreground'] }/>
<Icon as={ icon } boxSize="16px" mr="4px"/>
<span>{ fileName }</span>
<Box className="monaco-count-badge" ml="auto" bgColor={ badgeBgColor }>{ data.matches.length }</Box>
<Box className="monaco-count-badge" ml="auto" bgColor={ themeColors['badge.background'] }>{ data.matches.length }</Box>
</AccordionButton>
<AccordionPanel p={ 0 }>
{ data.matches.map((match) => (
......
import type { HTMLChakraProps } from '@chakra-ui/react';
import { Box, Tab, TabList, TabPanel, TabPanels, Tabs, useColorModeValue } from '@chakra-ui/react';
import { Box, Tab, TabList, TabPanel, TabPanels, Tabs } from '@chakra-ui/react';
import _throttle from 'lodash/throttle';
import React from 'react';
......@@ -7,7 +7,7 @@ import type { File, Monaco } from './types';
import CodeEditorFileExplorer from './CodeEditorFileExplorer';
import CodeEditorSearch from './CodeEditorSearch';
import useColors from './utils/useColors';
import useThemeColors from './utils/useThemeColors';
interface Props {
monaco: Monaco | undefined;
......@@ -20,35 +20,43 @@ const CodeEditorSideBar = ({ onFileSelect, data, monaco, selectedFile }: Props)
const [ isStuck, setIsStuck ] = React.useState(false);
const themeColors = useThemeColors();
const tabProps: HTMLChakraProps<'button'> = {
fontFamily: 'heading',
textTransform: 'uppercase',
fontSize: '11px',
lineHeight: '35px',
fontWeight: 500,
color: useColorModeValue('gray.600', 'gray.400'),
color: themeColors['tab.inactiveForeground'],
_selected: {
color: useColorModeValue('black', 'white'),
color: themeColors['tab.activeForeground'],
},
px: 0,
letterSpacing: 0.3,
};
const colors = useColors();
const handleScrollThrottled = React.useRef(_throttle((event: React.SyntheticEvent) => {
setIsStuck((event.target as HTMLDivElement).scrollTop > 0);
}, 100));
return (
<Box w="250px" flexShrink={ 0 } bgColor={ colors.panels.bgColor } fontSize="13px" overflowY="scroll" onScroll={ handleScrollThrottled.current } pb="22px">
<Box
w="250px"
flexShrink={ 0 }
bgColor={ themeColors['sideBar.background'] }
fontSize="13px"
overflowY="scroll"
onScroll={ handleScrollThrottled.current }
pb="22px"
>
<Tabs isLazy lazyBehavior="keepMounted" variant="unstyled" size="13px">
<TabList
columnGap={ 3 }
position="sticky"
top={ 0 }
left={ 0 }
bgColor={ colors.panels.bgColor }
bgColor={ themeColors['sideBar.background'] }
zIndex="1"
px={ 2 }
boxShadow={ isStuck ? 'md' : 'none' }
......
import { Flex, Icon, chakra, useColorModeValue, Box } from '@chakra-ui/react';
import { Flex, Icon, chakra, Box } from '@chakra-ui/react';
import React from 'react';
import useThemeColors from 'ui/shared/monaco/utils/useThemeColors';
import iconFile from './icons/file.svg';
import iconSolidity from './icons/solidity.svg';
import getFilePathParts from './utils/getFilePathParts';
import * as themes from './utils/themes';
import useColors from './utils/useColors';
interface Props {
isActive?: boolean;
path: string;
......@@ -17,7 +18,7 @@ interface Props {
const CodeEditorTab = ({ isActive, path, onClick, onClose, isCloseDisabled, tabsPathChunks }: Props) => {
const [ fileName, folderName ] = getFilePathParts(path, tabsPathChunks);
const colors = useColors();
const themeColors = useThemeColors();
const handleClick = React.useCallback(() => {
onClick(path);
......@@ -28,12 +29,7 @@ const CodeEditorTab = ({ isActive, path, onClick, onClose, isCloseDisabled, tabs
!isCloseDisabled && onClose(path);
}, [ isCloseDisabled, onClose, path ]);
const color = useColorModeValue('black', 'white');
const colorInactive = useColorModeValue('gray.600', 'gray.400');
const bgColor = useColorModeValue(themes.light.colors['editor.background'], themes.dark.colors['editor.background']);
const bgColorInactive = useColorModeValue('rgb(236, 236, 236)', 'rgb(45, 45, 45)');
const icon = /.sol|.yul|.vy$/.test(fileName) ? iconSolidity : iconFile;
const borderColorInactive = useColorModeValue('rgb(243, 243, 243)', 'rgb(37, 37, 38)');
return (
<Flex
......@@ -41,12 +37,12 @@ const CodeEditorTab = ({ isActive, path, onClick, onClose, isCloseDisabled, tabs
pr="4px"
fontSize="13px"
lineHeight="34px"
bgColor={ isActive ? bgColor : bgColorInactive }
bgColor={ isActive ? themeColors['tab.activeBackground'] : themeColors['tab.inactiveBackground'] }
borderRightWidth="1px"
borderRightColor={ borderColorInactive }
borderRightColor={ themeColors['tab.border'] }
borderBottomWidth="1px"
borderBottomColor={ isActive ? 'transparent' : borderColorInactive }
color={ isActive ? color : colorInactive }
borderBottomColor={ isActive ? 'transparent' : themeColors['tab.border'] }
color={ isActive ? themeColors['tab.activeForeground'] : themeColors['tab.inactiveForeground'] }
alignItems="center"
fontWeight={ 400 }
cursor="pointer"
......@@ -60,7 +56,7 @@ const CodeEditorTab = ({ isActive, path, onClick, onClose, isCloseDisabled, tabs
>
<Icon as={ icon } boxSize="16px" mr="4px"/>
<span>{ fileName }</span>
{ folderName && <chakra.span fontSize="xs" color="text_secondary" ml={ 1 }>{ folderName[0] === '.' ? '' : '...' }{ folderName }</chakra.span> }
{ folderName && <chakra.span fontSize="11px" opacity={ 0.8 } ml={ 1 }>{ folderName[0] === '.' ? '' : '...' }{ folderName }</chakra.span> }
<Box
className="codicon codicon-close"
boxSize="20px"
......@@ -72,8 +68,8 @@ const CodeEditorTab = ({ isActive, path, onClick, onClose, isCloseDisabled, tabs
borderRadius="sm"
opacity={ isCloseDisabled ? 0.3 : 1 }
visibility={ isActive ? 'visible' : 'hidden' }
color={ colors.buttons.color }
_hover={{ bgColor: isCloseDisabled ? 'transparent' : colors.buttons.bgColorHover }}
color={ themeColors['icon.foreground'] }
_hover={{ bgColor: isCloseDisabled ? 'transparent' : themeColors['inputOption.hoverBackground'] }}
/>
</Flex>
);
......
......@@ -2,7 +2,7 @@ import { Flex } from '@chakra-ui/react';
import React from 'react';
import CodeEditorTab from './CodeEditorTab';
import useColors from './utils/useColors';
import useThemeColors from './utils/useThemeColors';
interface Props {
tabs: Array<string>;
......@@ -12,7 +12,7 @@ interface Props {
}
const CodeEditorTabs = ({ tabs, activeTab, onTabSelect, onTabClose }: Props) => {
const colors = useColors();
const themeColors = useThemeColors();
const tabsPathChunks = React.useMemo(() => {
return tabs.map((tab) => tab.split('/'));
......@@ -20,7 +20,7 @@ const CodeEditorTabs = ({ tabs, activeTab, onTabSelect, onTabClose }: Props) =>
return (
<Flex
bgColor={ colors.panels.bgColor }
bgColor={ themeColors['sideBar.background'] }
flexWrap="wrap"
>
{ tabs.map((tab) => (
......
import { Box } from '@chakra-ui/react';
import React from 'react';
import useColors from './utils/useColors';
import useThemeColors from './utils/useThemeColors';
interface Props {
onClick: () => void;
......@@ -11,7 +11,8 @@ interface Props {
}
const CoderEditorCollapseButton = ({ onClick, label, isDisabled, isCollapsed }: Props) => {
const colors = useColors();
const themeColors = useThemeColors();
return (
<Box
position="absolute"
......@@ -27,7 +28,7 @@ const CoderEditorCollapseButton = ({ onClick, label, isDisabled, isCollapsed }:
content: isCollapsed ? '"\\eb95"' : '"\\eac5"',
}}
_hover={{
bgColor: colors.buttons.bgColorHover,
bgColor: themeColors['inputOption.hoverBackground'],
}}
onClick={ onClick }
cursor="pointer"
......
import type * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
export const light: monaco.editor.IStandaloneThemeData = {
base: 'vs',
export const light = {
base: 'vs' as const,
inherit: true,
rules: [],
colors: {
'editor.background': '#f5f5f6',
},
'editor.findMatchHighlightBackground': 'rgba(234, 92, 0, 0.33)',
'tab.activeBackground': '#f5f5f6',
'tab.inactiveBackground': 'rgb(236, 236, 236)',
'tab.activeForeground': '#101112', // black
'tab.inactiveForeground': '#4a5568', // gray.600
'tab.border': 'rgb(243, 243, 243)',
'icon.foreground': '#616161',
'input.foreground': 'rgb(97, 97, 97)',
'input.background': '#fff',
'inputOption.activeBackground': 'rgba(0, 144, 241, 0.2)',
'inputOption.hoverBackground': 'rgba(184, 184, 184, 0.31)',
'list.hoverBackground': 'rgba(16, 17, 18, 0.08)', // blackAlpha.200
'list.inactiveSelectionBackground': '#e4e6f1',
'breadcrumbs.foreground': 'rgb(97, 97, 97)',
'badge.background': '#c4c4c4',
'sideBar.background': '#eee',
focusBorder: '#0090f1',
} as const,
};
export const dark: monaco.editor.IStandaloneThemeData = {
base: 'vs-dark',
export const dark = {
base: 'vs-dark' as const,
inherit: true,
rules: [],
colors: {
'editor.background': '#1a1b1b',
},
'editor.findMatchHighlightBackground': 'rgba(234, 92, 0, 0.33)',
'tab.activeBackground': '#1a1b1b', // black
'tab.inactiveBackground': 'rgb(45, 45, 45)',
'tab.activeForeground': '#fff', // white
'tab.inactiveForeground': '#a0aec0', // gray.400
'tab.border': 'rgb(37, 37, 38)',
'icon.foreground': '#616161',
'input.foreground': 'rgb(204, 204, 204)',
'input.background': 'rgb(60, 60, 60)',
'inputOption.activeBackground': 'rgba(0, 127, 212, 0.4)',
'inputOption.hoverBackground': 'rgba(90, 93, 94, 0.31)',
'list.hoverBackground': 'rgba(255, 255, 255, 0.08)', // whiteAlpha.200
'list.inactiveSelectionBackground': '#37373d',
'badge.background': '#4d4d4d',
'breadcrumbs.foreground': 'rgb(97, 97, 97)',
'sideBar.background': '#222',
focusBorder: '#007fd4',
} as const,
};
import { useColorModeValue } from '@chakra-ui/react';
export default function useColors() {
return {
panels: {
bgColor: useColorModeValue('#eee', '#222'),
},
buttons: {
bgColorHover: useColorModeValue('rgba(184, 184, 184, 0.31)', 'rgba(90, 93, 94, 0.31)'),
color: '#616161',
},
selection: {
bgColorSelected: useColorModeValue('#e4e6f1', '#37373d'),
},
};
}
import { useColorModeValue } from '@chakra-ui/react';
import * as themes from './themes';
export default function useThemeColors() {
const theme = useColorModeValue(themes.light, themes.dark);
return theme.colors;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment