diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 9c27a5d..97052a7 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -11,8 +11,10 @@ "nativeToken": "Native token", "tvl": "TVL (L1)", "type": "Type", - "search": "Search", - "notFound": "Chain not found" + "search": "Search (Chain)", + "notFound": "Chain not found", + "noRPC": "No RPC", + "noMetadata": "No Metadata" } }, "CHAIN": { diff --git a/public/locales/es/common.json b/public/locales/es/common.json index 5085c7f..264b126 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -11,8 +11,10 @@ "nativeToken": "Token nativo", "tvl": "TVL (L1)", "type": "Tipo", - "search": "Buscar", - "notFound": "Cadena no encontrada" + "search": "Buscar (Cadena)", + "notFound": "Cadena no encontrada", + "noRPC": "Sin RPC", + "noMetadata": "Sin Metadata" } }, "CHAIN": { diff --git a/src/assets/icons/infoDark.svg b/src/assets/icons/infoDark.svg new file mode 100644 index 0000000..93d0755 --- /dev/null +++ b/src/assets/icons/infoDark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icons/infoLight.svg b/src/assets/icons/infoLight.svg new file mode 100644 index 0000000..aa0e9fe --- /dev/null +++ b/src/assets/icons/infoLight.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/components/InfoTag.tsx b/src/components/InfoTag.tsx new file mode 100644 index 0000000..1d81fd3 --- /dev/null +++ b/src/components/InfoTag.tsx @@ -0,0 +1,44 @@ +import { styled, Box, Typography } from '@mui/material'; +import Image from 'next/image'; + +import { useCustomTheme } from '~/hooks'; +import informationIconDark from '~/assets/icons/infoDark.svg'; +import informationIconLight from '~/assets/icons/infoLight.svg'; + +interface InfoTagProps { + information: string; +} + +export const InfoTag = ({ information }: InfoTagProps) => { + const { theme } = useCustomTheme(); + return ( + + {information} + {information} + + ); +}; + +const InfoTagContainer = styled(Box)(() => { + const { currentTheme } = useCustomTheme(); + + return { + display: 'flex', + alignItems: 'center', + fontSize: '0.7rem', + gap: currentTheme.gap, + backgroundColor: currentTheme.warningBackground, + borderRadius: currentTheme.borderRadius, + padding: '0.1rem 0.5rem 0.1rem 0.1rem', + border: currentTheme.warningBorder, + }; +}); + +const InfoText = styled(Typography)(() => { + const { currentTheme } = useCustomTheme(); + + return { + fontSize: '0.7rem', + color: currentTheme.warningText, + }; +}); diff --git a/src/components/Table.tsx b/src/components/Table.tsx index 582ac82..9e34554 100644 --- a/src/components/Table.tsx +++ b/src/components/Table.tsx @@ -1,10 +1,21 @@ import { useTranslation } from 'next-i18next'; import { useRouter } from 'next/router'; -import { styled, TableContainer, Table, TableHead, TableRow, TableCell, TableBody } from '@mui/material'; +import { + styled, + TableContainer, + Table, + TableHead, + TableRow, + TableCell, + TableBody, + Typography, + Avatar, +} from '@mui/material'; import { EcosystemChainData } from '~/types'; import { formatDataNumber } from '~/utils'; import { useCustomTheme } from '~/hooks'; +import { InfoTag } from './InfoTag'; interface TableProps { chains: EcosystemChainData[]; @@ -34,9 +45,17 @@ export const DataTable = ({ chains }: TableProps) => { {chains?.map((data, index) => { return ( handleChainNavigation(data.chainId)}> - {data.chainName} + + + {data.chainName} + {!data.rpc && } + {!data.metadata && } + {data.chainId} - {data.nativeToken} + + + {data.nativeToken} + {formatDataNumber(data.tvl, 0, true)} {data.chainType} @@ -50,18 +69,16 @@ export const DataTable = ({ chains }: TableProps) => { const STableContainer = styled(TableContainer)(() => { const { currentTheme } = useCustomTheme(); - return { width: '75rem', borderRadius: `${currentTheme.borderRadius}`, - border: '1px solid #FFFFFF0D', - zIndex: '1', + border: `1px solid ${currentTheme.neutral[700]}`, + overflow: 'hidden', }; }); const STableHead = styled(TableHead)(() => { const { currentTheme } = useCustomTheme(); - return { backgroundColor: `${currentTheme.backgroundTertiary}`, color: `${currentTheme.textSecondary}`, @@ -70,7 +87,6 @@ const STableHead = styled(TableHead)(() => { const STableBody = styled(TableBody)(() => { const { currentTheme } = useCustomTheme(); - return { backgroundColor: `${currentTheme.backgroundSecondary}`, }; @@ -79,7 +95,11 @@ const STableBody = styled(TableBody)(() => { const STableRow = styled(TableRow)(() => { const { currentTheme } = useCustomTheme(); return { - border: `${currentTheme.border}`, + '&:not(:last-child)': { + borderBottom: `1px solid ${currentTheme.neutral[700]}`, + }, + cursor: 'pointer', + transition: currentTheme.transition, }; }); @@ -87,6 +107,7 @@ const STableCellHead = styled(TableCell)(() => { const { currentTheme } = useCustomTheme(); return { color: `${currentTheme.textSecondary}`, + textAlign: 'left', }; }); @@ -94,5 +115,34 @@ const STableCell = styled(TableCell)(() => { const { currentTheme } = useCustomTheme(); return { color: `${currentTheme.textPrimary}`, + textAlign: 'left', + }; +}); + +const LogoCell = styled(TableCell)(() => { + const { currentTheme } = useCustomTheme(); + return { + color: `${currentTheme.textPrimary}`, + display: 'flex', + alignItems: 'center', + gap: `${currentTheme.gap}`, + border: 'none', + textAlign: 'left', + }; +}); + +const ChainAvatar = styled(Avatar)(() => { + return { + width: '2rem', + height: '2rem', + }; +}); + +const TokenAvatar = styled(Avatar)(() => { + const { currentTheme } = useCustomTheme(); + return { + width: '1.5rem', + height: '1.5rem', + backgroundColor: `${currentTheme.backgroundTertiary}`, }; }); diff --git a/src/components/Theme/theme.ts b/src/components/Theme/theme.ts index 2f91151..d510795 100644 --- a/src/components/Theme/theme.ts +++ b/src/components/Theme/theme.ts @@ -1,5 +1,75 @@ import { Theme } from '~/types'; +const neutral: { [key: number]: string } = { + 50: '#F7F9FC', + 100: '#E8ECF2', + 200: '#DADDE5', + 300: '#BEC2CC', + 400: '#A1A7B3', + 500: '#858C99', + 600: '#6C7380', + 700: '#555A66', + 800: '#3D424D', + 900: '#262B33', + 950: '#11141A', +}; + +const primary: { [key: number]: string } = { + 50: '#D9E3FF', + 100: '#A6BFFF', + 200: '#739AFF', + 300: '#4075FF', + 400: '#1755F4', + 500: '#1650E5', + 600: '#2663FF', + 700: '#1347CC', + 800: '#113EB2', + 900: '#0C2C80', + 950: '#071B4D', +}; + +const warning: { [key: number]: string } = { + 50: '#FFF9E5', + 100: '#FFECB2', + 200: '#FFE080', + 300: '#FFD44D', + 400: '#FFC81A', + 500: '#FFC200', + 600: '#E5AF00', + 700: '#CC9B00', + 800: '#997500', + 900: '#664E00', + 950: '#4D3A00', +}; + +const error: { [key: number]: string } = { + 50: '#FFCCCC', + 100: '#FFB2B2', + 200: '#FF8C8C', + 300: '#FF6666', + 400: '#FF6666', + 500: '#FF0000', + 600: '#CC0000', + 700: '#A60000', + 800: '#800000', + 900: '#590000', + 950: '#330000', +}; + +const success: { [key: number]: string } = { + 50: '#CCFFE5', + 100: '#B2FFD9', + 200: '#8CFFC6', + 300: '#66FFB2', + 400: '#33FF99', + 500: '#00FF80', + 600: '#00CC66', + 700: '#00A653', + 800: '#008040', + 900: '#00592D', + 950: '#00331A', +}; + export const darkTheme: Theme = { type: 'dark', titleColor: '#000000', @@ -12,7 +82,17 @@ export const darkTheme: Theme = { textFontFamily: 'Open Sans', borderRadius: '1.5rem', secondaryBorderRadius: '0.4rem', + transition: 'all 180ms ease-in-out', border: '0.1rem solid rgba(255, 255, 255, 0.05)', + gap: '0.25rem', + warningText: warning[400], + warningBackground: 'rgba(255, 200, 26, 0.1)', + warningBorder: '1px solid rgba(255, 200, 26, 0.051)', + neutral, + primary, + warning, + error, + success, }; export const lightTheme: Theme = { @@ -28,5 +108,15 @@ export const lightTheme: Theme = { textFontFamily: 'Open Sans', borderRadius: '1.5rem', secondaryBorderRadius: '0.4rem', + transition: 'all 180ms ease-in-out', border: '0.1rem solid rgba(0, 0, 0, 0.05)', + gap: '0.25rem', + warningText: warning[800], + warningBackground: 'rgba(153, 117, 0, 0.051)', + warningBorder: '1px solid rgba(153, 117, 0, 0.01)', + neutral, + primary, + warning, + error, + success, }; diff --git a/src/data/ecosystemMockData.json b/src/data/ecosystemMockData.json index 0e5bad7..fe39716 100644 --- a/src/data/ecosystemMockData.json +++ b/src/data/ecosystemMockData.json @@ -53,6 +53,7 @@ "iconUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/24091.png", "chainType": "Rollup", "nativeToken": "ETH", + "tokenImgUrl": "https://coin-images.coingecko.com/coins/images/279/large/ethereum.png?1696501628", "tvl": 1000000, "metadata": true, "rpc": true @@ -63,6 +64,7 @@ "iconUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/24091.png", "chainType": "Validium", "nativeToken": "ETH", + "tokenImgUrl": "https://coin-images.coingecko.com/coins/images/279/large/ethereum.png?1696501628", "tvl": 500000, "metadata": true, "rpc": false @@ -72,6 +74,8 @@ "chainName": "ZKsyncERA", "iconUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/24091.png", "chainType": "Rollup", + "nativeToken": "ETH", + "tokenImgUrl": "https://coin-images.coingecko.com/coins/images/279/large/ethereum.png?1696501628", "tvl": 300000, "metadata": false, "rpc": true @@ -81,6 +85,8 @@ "chainName": "ZKsyncERA", "iconUrl": "https://s2.coinmarketcap.com/static/img/coins/64x64/24091.png", "chainType": "Rollup", + "nativeToken": "ETH", + "tokenImgUrl": "https://coin-images.coingecko.com/coins/images/279/large/ethereum.png?1696501628", "tvl": 10000, "metadata": false, "rpc": false diff --git a/src/types/Data.ts b/src/types/Data.ts index 90c0f13..30bb671 100644 --- a/src/types/Data.ts +++ b/src/types/Data.ts @@ -42,6 +42,7 @@ export interface EcosystemChainData { chainId: number; iconUrl: string; nativeToken: string; + tokenImgUrl: string; tvl: number; chainType: string; metadata: boolean; diff --git a/src/types/Theme.ts b/src/types/Theme.ts index e2b0e90..a93fadf 100644 --- a/src/types/Theme.ts +++ b/src/types/Theme.ts @@ -12,7 +12,17 @@ export interface Theme { textFontFamily: string; borderRadius: string; secondaryBorderRadius: string; + transition: string; border: string; + gap: string; + warningText: string; + warningBackground: string; + warningBorder: string; + neutral: { [key: number]: string }; + primary: { [key: number]: string }; + warning: { [key: number]: string }; + error: { [key: number]: string }; + success: { [key: number]: string }; } export interface PropTheme {