Skip to content

Commit

Permalink
feat: header components styling
Browse files Browse the repository at this point in the history
  • Loading branch information
0xtiti committed Jul 31, 2024
1 parent a84114a commit a7769f1
Show file tree
Hide file tree
Showing 12 changed files with 253 additions and 81 deletions.
2 changes: 1 addition & 1 deletion public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"nativeToken": "Native token",
"tvl": "TVL - L1",
"type": "Type",
"search": "Search by chain name or id...",
"search": "Search",
"notFound": "Chain not found"
}
},
Expand Down
2 changes: 1 addition & 1 deletion public/locales/es/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"nativeToken": "Token nativo",
"tvl": "TVL - L1",
"type": "Tipo",
"search": "Buscar por nombre o ID de la cadena...",
"search": "Buscar",
"notFound": "Cadena no encontrada"
}
},
Expand Down
3 changes: 3 additions & 0 deletions src/assets/icons/arrowDown.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions src/assets/icons/lightMode.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/assets/icons/search.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
147 changes: 118 additions & 29 deletions src/components/BasicSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,140 @@
import { useState } from 'react';
import { styled, MenuProps, Menu, Box, Button, MenuItem } from '@mui/material';
import Image from 'next/image';

import arrowDown from '~/assets/icons/arrowDown.svg';
import { useCustomTheme } from '~/hooks';

interface BasicSelectProps {
label?: string;
value: string;
setValue: (explorer: string) => void;
list: string[];
disabled?: boolean;
dataTest?: string;
}

export const BasicSelect = ({ list, value, setValue }: BasicSelectProps) => {
const [isOpen, setIsOpen] = useState(false);
export const BasicSelect = ({ list, value, setValue, disabled, dataTest }: BasicSelectProps) => {
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);

const handleClick = () => {
setIsOpen(!isOpen);
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};

const selectItem = (explorer?: string) => {
setIsOpen(false);
setAnchorEl(null);

if (!explorer) return;
setValue(explorer);
};

const handleKeyDown = (event: React.KeyboardEvent<HTMLLIElement>, explorer?: string) => {
if (event.key === 'Enter' || event.key === ' ') {
selectItem(explorer);
}
};
const endIcon = disabled ? null : <Image src={arrowDown} alt='arrow-down' width={16} height={16} />;

return (
<div>
<button onClick={handleClick}>{value}</button>
{isOpen && (
<ul role='listbox'>
{list.map((item) => (
<li
key={item}
role='option'
tabIndex={0}
aria-selected={item === value}
onClick={() => selectItem(item)}
onKeyDown={(event) => handleKeyDown(event, item)}
>
{item}
</li>
))}
</ul>
)}
</div>
<SBox>
<MenuButton
aria-controls={open ? 'basic-select-menu' : undefined}
aria-haspopup='true'
aria-expanded={open ? 'true' : undefined}
variant='contained'
disableElevation
onClick={handleClick}
endIcon={endIcon}
fullWidth
disabled={disabled}
data-test={dataTest}
>
{value}
</MenuButton>

<StyledMenu
anchorEl={anchorEl}
open={open}
onClose={() => selectItem()}
MenuListProps={{
'aria-labelledby': 'basic-select-button',
}}
>
{list.map((explorer) => (
<MenuItem key={explorer} value={explorer} onClick={() => selectItem(explorer)}>
{explorer}
</MenuItem>
))}
</StyledMenu>
</SBox>
);
};

const SBox = styled(Box)({
display: 'flex',
flexDirection: 'column',
gap: '0.5rem',
});

const MenuButton = styled(Button)(() => {
const { currentTheme } = useCustomTheme();
return {
width: '7.5rem',
height: '3.5rem',
backgroundColor: `${currentTheme.backgroundSecondary}`,
borderRadius: `${currentTheme.borderRadius}`,
textTransform: 'none',
fontSize: '1rem',
color: `${currentTheme.textPrimary}`,
'&:hover': {
backgroundColor: `${currentTheme.backgroundSecondary}`,
},
};
});

const StyledMenu = styled((props: MenuProps) => (
<Menu
elevation={0}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'left',
}}
{...props}
/>
))(() => {
const { currentTheme } = useCustomTheme();
return {
'& .MuiPaper-root': {
marginTop: '0.4rem',
width: '7.5rem',

'& .MuiMenu-list': {
padding: '0.4rem 0',
},

'& .MuiMenuItem-root': {
padding: '1.2rem 1.6rem',
gap: '0.8rem',

'&:hover': {
backgroundColor: currentTheme.backgroundSecondary,
},

'&:active': {
backgroundColor: currentTheme.backgroundSecondary,
},
},

'@media (max-width: 600px)': {
minWidth: 'calc(100% - 7.4rem)',
ul: {
padding: '0.2rem 0',
},

'& .MuiMenuItem-root': {
fontSize: '1.4rem',
},
},
},
};
});
56 changes: 45 additions & 11 deletions src/components/SearchBar.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,54 @@
import { useTranslation } from 'next-i18next';
import { useCustomTheme, useStateContext } from '~/hooks';
import { styled, TextField, InputAdornment } from '@mui/material';
import Image from 'next/image';

interface SearchBarProps {
value: string;
onChange: (value: string) => void;
}
import Search from '~/assets/icons/search.svg';

export const SearchBar = ({ value, onChange }: SearchBarProps) => {
export const SearchBar = () => {
const { t } = useTranslation();

const { searchTerm, setSearchTerm } = useStateContext();
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
onChange(event.target.value);
const value = event.target.value;
setSearchTerm(value);
};

return (
<form>
<input type='text' value={value} onChange={handleChange} placeholder={t('HOME.DASHBOARD.search')} />
</form>
<StyledTextField
variant='outlined'
value={searchTerm}
onChange={handleChange}
placeholder={t('HOME.DASHBOARD.search')}
InputProps={{
startAdornment: (
<InputAdornment position='start'>
<Image src={Search} alt='search' />
</InputAdornment>
),
}}
/>
);
};

const StyledTextField = styled(TextField)(() => {
const { currentTheme } = useCustomTheme();

return {
width: '15rem',
height: '3.5rem',
borderRadius: `${currentTheme.borderRadius}`,
border: `1px solid ${currentTheme.backgroundSecondary}`,
backgroundColor: `${currentTheme.backgroundTertiary}`,
opacity: 1,
'& .MuiOutlinedInput-root': {
'& fieldset': {
border: 'none',
},
'&:hover fieldset': {
border: 'none',
},
'&.Mui-focused fieldset': {
border: 'none',
},
},
};
});
9 changes: 6 additions & 3 deletions src/components/Theme/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,27 @@ export const darkTheme: Theme = {
textPrimary: '#ffffff',
textSecondary: '#99A4B8',
backgroundPrimary: '#000000',
backgroundSecondary: '#161616',
backgroundSecondary: '#262B33',
backgroundTertiary: '#11141A',
titleFontFamily: 'Open Sans',
textFontFamily: 'Open Sans',
borderRadius: '0.8rem',
borderRadius: '1.5rem',
secondaryBorderRadius: '0.4rem',
border: '0.1rem solid rgba(153, 164, 184, 0.1)',
};

export const lightTheme: Theme = {
// TBD
type: 'light',
titleColor: '#000000',
textPrimary: '#000000',
textSecondary: '#717171',
backgroundPrimary: '#ffffff',
backgroundSecondary: '#f8f8f8',
backgroundTertiary: '#f8f8f8',
titleFontFamily: 'Open Sans',
textFontFamily: 'Open Sans',
borderRadius: '0.8rem',
borderRadius: '1.5rem',
secondaryBorderRadius: '0.4rem',
border: '0.1rem solid rgba(183, 183, 183, 0.3)',
};
12 changes: 3 additions & 9 deletions src/containers/Dashboard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { useTranslation } from 'next-i18next';
import { useState } from 'react';

import { NotFound, SearchBar, Table, Title } from '~/components';
import { useData } from '~/hooks';
import { NotFound, Table, Title } from '~/components';
import { useData, useStateContext } from '~/hooks';

export const Dashboard = () => {
const { t } = useTranslation();
const { ecosystemData } = useData();
const [searchTerm, setSearchTerm] = useState<string>('');
const { searchTerm } = useStateContext();

const filteredChains = ecosystemData?.chains.filter((chain) => {
const chainIdStr = String(chain.id);
Expand All @@ -22,15 +21,10 @@ export const Dashboard = () => {

const availableChains = filteredChains?.length > 0;

const handleChange = (value: string) => {
setSearchTerm(value);
};

return (
<section>
<header>
<Title title={t('HOME.DASHBOARD.title')} />
<SearchBar value={searchTerm} onChange={handleChange} />
</header>

{availableChains && <Table chains={filteredChains} />}
Expand Down
Loading

0 comments on commit a7769f1

Please sign in to comment.