Commit 2d28a0e6 authored by tom's avatar tom

style file explorer

parent 4a18e2b4
......@@ -32,7 +32,7 @@ const CodeEditorFileExplorer = ({ data, onFileSelect }: Props) => {
}, []);
return (
<Box>
<Box pb="22px">
<CoderEditorCollapseButton onClick={ handleCollapseButtonClick } label="Collapse folders"/>
<CodeEditorFileTree key={ key } tree={ tree } onItemClick={ handleFileClick } isCollapsed={ key > 0 }/>
</Box>
......
import type { ChakraProps } from '@chakra-ui/react';
import { Accordion, AccordionButton, AccordionIcon, AccordionItem, AccordionPanel } from '@chakra-ui/react';
import { Accordion, AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, Icon, chakra, useColorModeValue } from '@chakra-ui/react';
import React from 'react';
import type { FileTree } from './types';
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';
interface Props {
tree: FileTree;
level?: number;
......@@ -13,35 +18,68 @@ interface Props {
const CodeEditorFileTree = ({ tree, level = 0, onItemClick, isCollapsed }: Props) => {
const itemProps: ChakraProps = {
ml: level ? 4 : 0,
borderWidth: '0px',
cursor: 'pointer',
lineHeight: '22px',
_last: {
borderBottomWidth: '0px',
},
cursor: 'pointer',
};
const rowHoverBgColor = useColorModeValue('blackAlpha.200', 'whiteAlpha.200');
return (
<Accordion allowMultiple defaultIndex={ isCollapsed ? undefined : tree.map((item, index) => index) } reduceMotion>
{
tree.map((leaf, index) => {
const leafName = <chakra.span overflow="hidden" textOverflow="ellipsis" whiteSpace="nowrap">{ leaf.name }</chakra.span>;
if ('children' in leaf) {
return (
<AccordionItem key={ index } { ...itemProps }>
<AccordionButton p={ 0 } _hover={{ bgColor: 'inherit' }} fontSize="sm">
<AccordionIcon/>
<span>{ leaf.name }</span>
</AccordionButton>
<AccordionPanel p={ 0 }>
<CodeEditorFileTree tree={ leaf.children } level={ level + 1 } onItemClick={ onItemClick } isCollapsed={ isCollapsed }/>
</AccordionPanel>
{ ({ isExpanded }) => (
<>
<AccordionButton
pr="8px"
py="0"
pl={ `${ 8 + 8 * level }px` }
_hover={{ bgColor: rowHoverBgColor }}
fontSize="13px"
lineHeight="22px"
h="22px"
transitionDuration="0"
>
<AccordionIcon transform={ isExpanded ? 'rotate(0deg)' : 'rotate(-90deg)' } boxSize="16px"/>
<Icon as={ isExpanded ? iconFolderOpen : iconFolder } boxSize="16px" mr="4px"/>
{ leafName }
</AccordionButton>
<AccordionPanel p="0">
<CodeEditorFileTree tree={ leaf.children } level={ level + 1 } onItemClick={ onItemClick } isCollapsed={ isCollapsed }/>
</AccordionPanel>
</>
) }
</AccordionItem>
);
}
const icon = /.sol|.yul|.vy$/.test(leaf.name) ? iconSolidity : iconFile;
return (
<AccordionItem key={ index } { ...itemProps } onClick={ onItemClick } data-file-path={ leaf.file_path }>
{ leaf.name }
<AccordionItem
key={ index }
{ ...itemProps }
pl={ `${ 24 + (level * 8) }px` }
pr="8px"
onClick={ onItemClick }
data-file-path={ leaf.file_path }
display="flex"
alignItems="center"
overflow="hidden"
_hover={{
bgColor: rowHoverBgColor,
}}
>
<Icon as={ icon } boxSize="16px" mr="4px"/>
{ leafName }
</AccordionItem>
);
})
......
......@@ -71,11 +71,12 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect }: Props) => {
}, [ expandedSections.length, searchResults ]);
return (
<Box>
<Box px={ 2 }>
<CoderEditorCollapseButton
onClick={ handleToggleCollapseClick }
label={ expandedSections.length === 0 ? 'Expand all' : 'Collapse all' }
isDisabled={ searchResults.length === 0 }
isCollapsed={ expandedSections.length === 0 }
/>
<Input size="xs" onChange={ handleSearchTermChange } value={ searchTerm } placeholder="Search"/>
<Accordion
......
import type { HTMLChakraProps } from '@chakra-ui/react';
import { Box, Tab, TabList, TabPanel, TabPanels, Tabs } from '@chakra-ui/react';
import { Box, Tab, TabList, TabPanel, TabPanels, Tabs, useColorModeValue } from '@chakra-ui/react';
import _throttle from 'lodash/throttle';
import React from 'react';
import type { File, Monaco } from './types';
......@@ -15,10 +16,13 @@ interface Props {
const CodeEditorSideBar = ({ onFileSelect, data, monaco }: Props) => {
const [ isStuck, setIsStuck ] = React.useState(false);
const tabProps: HTMLChakraProps<'button'> = {
fontFamily: 'heading',
textTransform: 'uppercase',
fontSize: 'xs',
fontSize: '11px',
lineHeight: '35px',
fontWeight: 500,
color: 'gray.600',
_selected: {
......@@ -28,10 +32,26 @@ const CodeEditorSideBar = ({ onFileSelect, data, monaco }: Props) => {
letterSpacing: 0.3,
};
const bgColor = useColorModeValue('#eee', '#222');
const handleScrollThrottled = React.useRef(_throttle((event: React.SyntheticEvent) => {
setIsStuck((event.target as HTMLDivElement).scrollTop > 0);
}, 100));
return (
<Box w="250px" flexShrink={ 0 } bgColor="lightpink" fontSize="sm" overflowY="scroll" px={ 3 }>
<Tabs isLazy lazyBehavior="keepMounted" variant="unstyled" size="sm">
<TabList columnGap={ 3 } position="sticky" top={ 0 } left={ 0 } bgColor="lightcoral" zIndex="sticky">
<Box w="250px" flexShrink={ 0 } bgColor={ bgColor } fontSize="13px" overflowY="scroll" onScroll={ handleScrollThrottled.current }>
<Tabs isLazy lazyBehavior="keepMounted" variant="unstyled" size="13px">
<TabList
columnGap={ 3 }
position="sticky"
top={ 0 }
left={ 0 }
bgColor={ bgColor }
zIndex="1"
px={ 2 }
boxShadow={ isStuck ? 'md' : 'none' }
borderTopRadius="md"
>
<Tab { ...tabProps }>Explorer</Tab>
<Tab { ...tabProps }>Search</Tab>
</TabList>
......
import { Flex, IconButton, Tooltip } from '@chakra-ui/react';
import { Tooltip, Box } from '@chakra-ui/react';
import React from 'react';
import iconCopy from 'icons/copy.svg';
interface Props {
onClick: () => void;
label: string;
isDisabled?: boolean;
isCollapsed?: boolean;
}
const CoderEditorCollapseButton = ({ onClick, label, isDisabled }: Props) => {
const CoderEditorCollapseButton = ({ onClick, label, isDisabled, isCollapsed }: Props) => {
return (
<Tooltip label={ label } isDisabled={ isDisabled }>
<Flex position="absolute" right={ 3 } top={ 2 } zIndex="sticky">
<IconButton
as={ iconCopy }
boxSize={ 4 }
variant="unstyled"
cursor="pointer"
aria-label="collapse"
onClick={ onClick }
isDisabled={ isDisabled }
/>
</Flex>
<Box
position="absolute"
right={ 3 }
top={ 2 }
zIndex="sticky1"
className={ isCollapsed ? 'codicon codicon-search-expand-results' : 'codicon codicon-collapse-all' }
opacity={ isDisabled ? 0.6 : 1 }
_before={{
content: isCollapsed ? '"\\eb95"' : '"\\eac5"',
}}
onClick={ onClick }
cursor="pointer"
/>
</Tooltip>
);
};
......
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M13 9h5.5L13 3.5V9M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4c0-1.11.89-2 2-2m5 2H6v16h12v-9h-7V4z" fill="#42a5f5"/>
</svg>
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7a2 2 0 0 1 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#90a4ae"/>
</svg>
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M10 4H4c-1.11 0-2 .89-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#90a4ae"/>
</svg>
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="#0288d1">
<path d="m5.747 14.046 6.254 8.61 6.252-8.61-6.254 3.807z"/>
<path d="M11.999 1.343 5.747 11.83l6.252 3.807 6.253-3.807z"/>
</g>
</svg>
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