Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change UI's #445

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,6 @@ yarn-error.log*

# vercel
.vercel

# packages
package-lock.json
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,33 @@
## Watch the muted youtube video of all changes

[![Watch the video](https://img.youtube.com/vi/R2_T4pLGm-A/maxresdefault.jpg)](https://youtu.be/R2_T4pLGm-A)

## Updated Chainlist

# Changelog:

1. Added ability to copy RPC link to clipboard after clicking on the link text
2. Added an effect of adding icon to the clipboard when hovering over a cell with a link
3. Added effect of highlighting a cell with color when pointing with cursor
4. Added animation of adding a link to the clipboard
5. Fixed bug when switching to dark mode, scrolling remained always white in chrome. Now when you change the theme, scrolling is always in the theme color
6. Added full screen mode, side menu folds into side menu. Looks much more convenient, especially for laptops.
7. Tables on mobile resolution became more organic.
8. Small bugs on mobile resolution.
9. Added remembering the position of the side menu or full screen mode in localStorage.

# Motivation 1

I really dislike horizontal scrolling in tables, so my main motivation was to get rid of them.

# Motivation 2

It really annoyed me when I was doing a multichain project and to copy the RPC I had to add the metamask to the blockchain first and then copy the RPC. This update makes it much more convenient.

## Decision

Take the best, leave the rest

## Getting Started

First, run the development server:
Expand Down
8 changes: 4 additions & 4 deletions components/Layout/Logo.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

109 changes: 88 additions & 21 deletions components/Layout/index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,51 @@
import * as React from "react";
import { useEffect } from "react";
import { useEffect, useState } from "react";

import Header from "../header";
// import { useTranslations } from "next-intl";
import { notTranslation as useTranslations } from "../../utils";
import Logo from "./Logo";
import { useRouter } from "next/router";



const globalStylesDark = `
@media (prefers-color-scheme: dark) {
html body.dark {
color-scheme: dark;
}
}
@media (prefers-color-scheme: light) {
html {
color-scheme: dark;
}
}
`
const toggleDarkThemeBrowserStyles = () =>
{
// support chrome dark mode ui, such as scrollbar :)
let style = document.getElementById("darkStyle");
if(style){
document.head.removeChild(style);
} else {
style = document.createElement('style');
style.id = "darkStyle";
style.innerHTML = globalStylesDark
document.head.append(style)
}
}

const toggleTheme = (e) => {
e.preventDefault();
const element = document.body;
document.getElementById("theme-toggle-dark-icon").classList.toggle("hidden");
document.getElementById("theme-toggle-light-icon").classList.toggle("hidden");
const result = element.classList.toggle("dark");
localStorage.setItem('theme', result ? 'dark' : 'light');

// toggle dark mode in chrome for ui
toggleDarkThemeBrowserStyles()

}

const initTheme = () => {
Expand All @@ -26,10 +59,17 @@ const initTheme = () => {
}




export default function Layout({ children, lang }) {
useEffect(() => {
initTheme();
initMinimize();
}, []);
const [browserDarkStyles, setBrowserDarkStyles] = useState('')


const [isCompact, setIsCompact] = useState(false)

const t = useTranslations("Common", lang);

Expand All @@ -39,25 +79,40 @@ export default function Layout({ children, lang }) {

const chainName = typeof search === "string" ? search : "";

const handleMinimize = () => {
setIsCompact(!isCompact)
localStorage.setItem('isCompactLayout', isCompact);
console.log(localStorage.getItem('isCompactLayout'))
}

const initMinimize = () => {
const layoutStorage = localStorage.getItem('isCompactLayout');

if(layoutStorage) setIsCompact(Boolean(layoutStorage))
// console.log(JSON.parse(isMinimizeStorage))

}

return (
<div className="grid grid-cols-1 lg:grid-cols-[40vw,_auto]">
<div className="dark:text-[#B3B3B3] text-black dark:bg-[#0D0D0D] bg-white relative h-full">
<div className="p-5 sticky top-0 bottom-0 m-auto flex flex-col items-center gap-8 justify-center h-screen max-w-[480px] mx-auto">
<figure className="lg:mr-auto">
<Logo />
<figcaption className="font-bold text-2xl">{t("help-info")}</figcaption>
<div className={`grid grid-cols-1 ${isCompact ? 'md:grid-cols-[16vw,_auto] lg:grid-cols-[10vw,_auto] xl:grid-cols-[11vw,_auto]' : 'md:grid-cols-[40vw,_auto]'}`}>
<style>{browserDarkStyles}</style>
<div className="dark:text-[#B3B3B3] z-[60] text-black dark:bg-[#0D0D0D] bg-white relative h-full flex flex-row">
<div className="p-5 sticky top-0 bottom-0 m-auto grid items-center gap-8 justify-center h-screen max-w-[480px] mx-auto">
<figure className="">
<Logo isCompact={isCompact} />
<figcaption className={`font-bold text-2xl ${isCompact ? "md:hidden" : ""}`}>{t("help-info")}</figcaption>
</figure>

<h1 className="font-medium text-base">{t("description")}</h1>
<h1 className={`font-medium text-base ${isCompact ? "md:hidden" : ""}`}>{t("description")}</h1>

<div className="flex flex-col gap-4 w-full">
<a
className="flex items-center justify-center mx-auto lg:ml-0 gap-2 rounded-[50px] max-w-[16.25rem] font-medium py-[18px] px-6 shadow-lg w-full dark:bg-[#2F80ED] bg-[#2F80ED] dark:text-black text-white"
className={`flex items-center justify-center mx-auto lg:ml-0 gap-2 rounded-[50px] max-w-[16.25rem] font-medium shadow-lg w-full dark:bg-[#2F80ED] bg-[#2F80ED] dark:text-black text-white ${isCompact ? 'md:py-2 lg:py-[18px] md:px-0' : ''} py-[18px] px-6`}
href="https://github.com/ethereum-lists/chains"
target="_blank"
rel="noopener noreferrer"
>
<span className="text-base font-medium">{t("add-your-network")}</span>
<span className={`text-base font-medium ${isCompact ? "md:hidden" : ""}`}>{t("add-your-network")}</span>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
Expand All @@ -71,12 +126,12 @@ export default function Layout({ children, lang }) {
</a>

<a
className="flex items-center justify-center mx-auto lg:ml-0 gap-2 rounded-[50px] max-w-[16.25rem] font-medium py-[17px] px-6 w-full dark:bg-[#0D0D0D] bg-white dark:text-[#2F80ED] text-[#2F80ED] border dark:border-[#171717] border-[#EAEAEA]"
className={`flex items-center justify-center mx-auto lg:ml-0 gap-2 rounded-[50px] max-w-[16.25rem] font-medium py-[17px] px-6 w-full dark:bg-[#0D0D0D] bg-white dark:text-[#2F80ED] text-[#2F80ED] border dark:border-[#171717] border-[#EAEAEA] ${isCompact ? 'md:py-2 lg:py-[18px] md:px-0' : ''} py-[18px] px-6`}
href="https://github.com/DefiLlama/chainlist/blob/main/constants/extraRpcs.js"
target="_blank"
rel="noopener noreferrer"
>
<span className="text-base font-medium">{t("add-your-rpc")}</span>
<span className={`text-base font-medium ${isCompact ? "md:hidden" : ""}`}>{t("add-your-rpc")}</span>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
Expand All @@ -91,29 +146,29 @@ export default function Layout({ children, lang }) {
</div>

<a
className="flex items-center gap-2 mx-auto lg:ml-0"
className={`flex items-center gap-2 mx-auto ${isCompact ? '' : 'lg:ml-0'}`}
href="https://github.com/DefiLlama/chainlist"
target="_blank"
rel="noopener noreferrer"
>
<svg version="1.1" className="w-6 h-6" viewBox="0 0 24 24">
<svg version="1.1" className={`${isCompact ? "w-12 h-12" : "w-6 h-6"}`} viewBox="0 0 24 24">
<path
fill={"#2F80ED"}
d="M12,2A10,10 0 0,0 2,12C2,16.42 4.87,20.17 8.84,21.5C9.34,21.58 9.5,21.27 9.5,21C9.5,20.77 9.5,20.14 9.5,19.31C6.73,19.91 6.14,17.97 6.14,17.97C5.68,16.81 5.03,16.5 5.03,16.5C4.12,15.88 5.1,15.9 5.1,15.9C6.1,15.97 6.63,16.93 6.63,16.93C7.5,18.45 8.97,18 9.54,17.76C9.63,17.11 9.89,16.67 10.17,16.42C7.95,16.17 5.62,15.31 5.62,11.5C5.62,10.39 6,9.5 6.65,8.79C6.55,8.54 6.2,7.5 6.75,6.15C6.75,6.15 7.59,5.88 9.5,7.17C10.29,6.95 11.15,6.84 12,6.84C12.85,6.84 13.71,6.95 14.5,7.17C16.41,5.88 17.25,6.15 17.25,6.15C17.8,7.5 17.45,8.54 17.35,8.79C18,9.5 18.38,10.39 18.38,11.5C18.38,15.32 16.04,16.16 13.81,16.41C14.17,16.72 14.5,17.33 14.5,18.26C14.5,19.6 14.5,20.68 14.5,21C14.5,21.27 14.66,21.59 15.17,21.5C19.14,20.16 22,16.42 22,12A10,10 0 0,0 12,2Z"
/>
</svg>
<span className="text-base font-medium">{t("view-source-code")}</span>
<span className={`text-base font-medium ${isCompact ? "md:hidden" : ""}`}>{t("view-source-code")}</span>
</a>

<a
className="flex items-center gap-2 mx-auto lg:ml-0"
className={`flex items-center gap-2 mx-auto ${isCompact ? '' : 'lg:ml-0'}`}
href="#"
onClick={toggleTheme}
id="theme-toggle"
>
<svg
id="theme-toggle-dark-icon"
class="w-5 h-5 hidden"
className={`${isCompact ? "w-10 h-10" : "w-5 h-5"}`}
fill="#2F80ED"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
Expand All @@ -124,20 +179,32 @@ export default function Layout({ children, lang }) {
</svg>
<svg
id="theme-toggle-light-icon"
class="w-5 h-5 hidden"
className={`${isCompact ? "w-10 h-10" : "w-5 h-5"} hidden`}
fill="#2F80ED"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
fill-rule="evenodd"
clip-rule="evenodd"
fillRule="evenodd"
clipRule="evenodd"
></path>
</svg>
<span className="text-base font-medium">{t("toggle-theme")}</span>
<span className={`text-base font-medium ${isCompact ? "md:hidden" : ""}`}>{t("toggle-theme")}</span>
</a>
</div>
<button className="z-[1] w-4 sticky h-screen top-0 right-0 -ml-[17px] hidden md:block dark:text-[#B3B3B3] text-black dark:hover:bg-[#181818] hover:bg-[#f6f6f6] transition-colors rounded-lg dark:border-[#171717] border-[#EAEAEA]" type="button" onClick={handleMinimize}>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={3}
stroke="currentColor"
className={`w-4 h-4 transform transition-transform duration-500 ${isCompact ? " -rotate-90" : "rotate-90"}`}
>
<path strokeLinecap="round" strokeLinejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
</svg>
</button>
</div>
<div className="dark:bg-[#181818] bg-[#f3f3f3] p-5 relative flex flex-col gap-5">
<Header lang={lang} chainName={chainName} key={chainName} />
Expand Down
68 changes: 52 additions & 16 deletions components/RPCList/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export default function RPCList({ chain, lang }) {
const isEthMainnet = chain?.name === "Ethereum Mainnet";

return (
<div className="shadow dark:bg-[#0D0D0D] bg-white p-8 rounded-[10px] flex flex-col gap-3 overflow-hidden col-span-full relative overflow-x-auto">
<div className="shadow dark:bg-[#0D0D0D] bg-white md:p-8 rounded-[10px] flex flex-col gap-3 overflow-hidden col-span-full relative overflow-x-auto">
{isEthMainnet && (
<p className="text-center">
Follow{" "}
Expand All @@ -99,7 +99,7 @@ export default function RPCList({ chain, lang }) {
)}

<table className="m-0 border-collapse whitespace-nowrap dark:text-[#B3B3B3] text-black">
<caption className="relative w-full px-3 py-1 text-base font-medium border border-b-0">
<caption className="relative w-full px-3 py-1 text-left sm:text-center text-base font-medium border border-b-0">
<span className="mr-4">{`${chain.name} RPC URL List`}</span>
<button
className="text-sm font-normal flex items-center gap-1 absolute right-4 top-[2px] bottom-[2px] dark:hover:bg-[#171717] hover:bg-[#EAEAEA] px-2 rounded-[10px]"
Expand All @@ -124,13 +124,18 @@ export default function RPCList({ chain, lang }) {
</button>
</caption>
<thead>
<tr>
<tr className="">
<th className="px-3 py-1 font-medium border">RPC Server Address</th>
<th className="px-3 py-1 font-medium border">Height</th>
<th className="px-3 py-1 font-medium border">Latency</th>
<th className="px-3 py-1 font-medium border">Score</th>
<th className="px-3 py-1 font-medium border">Privacy</th>
<th className="px-3 py-1 font-medium border"></th>
<th className="px-3 py-1 font-medium border
hidden sm:table-cell">Height</th>
<th className="px-3 py-1 font-medium border
hidden sm:table-cell">Latency</th>
<th className="px-3 py-1 font-medium border
hidden sm:table-cell">Score</th>
<th className="px-3 py-1 font-medium border
hidden sm:table-cell">Privacy</th>
<th className="px-3 py-1 font-medium border
hidden sm:table-cell"></th>
</tr>
</thead>

Expand All @@ -150,7 +155,7 @@ export default function RPCList({ chain, lang }) {
key={index}
privacy={urlToData[item.data.url]}
lang={lang}
className={className}
className={`flex flex-col wrap sm:table-row odd:bg-gray-100 even:bg-white dark:odd:bg-neutral-900 dark:even:bg-black ${className}`}
/>
)
})}
Expand Down Expand Up @@ -182,6 +187,8 @@ function PrivacyIcon({ tracking, isOpenSource = false }) {
}

const Row = ({ values, chain, isEthMainnet, privacy, lang, className }) => {
const [effect, setEffect] = useState(false);

const t = useTranslations("Common", lang);
const { data, isLoading, refetch } = values;

Expand All @@ -203,14 +210,39 @@ const Row = ({ values, chain, isEthMainnet, privacy, lang, className }) => {

const { mutate: addToNetwork } = useAddToNetwork();

const handleCopyText = (event) => {
const textToCopy = event.target.innerText;
console.log(textToCopy)
navigator.clipboard.writeText(textToCopy);
console.log('Text copied to clipboard!');
setEffect(true);
};
// display: inline;
// position: absolute;
// left: 3px;
// content: "copied!";
// animation: 1s ease-in-out 0s 1 normal forwards running copyit;
// font-size: .8em;
return (
<tr className={className}>
<td className="border px-3 text-sm py-1 max-w-[40ch] overflow-hidden whitespace-nowrap text-ellipsis">
<tr className={`${className} [&>*]:h-8`}>
<td before={data?.url} className={`border px-3 text-sm py-1 w-full md:max-w-[40ch] overflow-hidden whitespace-nowrap text-ellipsis
relative cursor-pointer

dark:hover:bg-gray-800 hover:bg-gray-100
dark:hover:after:content-copyIconLight hover:after:content-copyIconDark after:w-6 after:h-6 after:absolute after:right-[-8px]
before:content-[attr(before)] before:inline before:absolute before:text-ellipsis
${effect ? "before:animate-copied" : "before:content-['']"}`} onClick={handleCopyText} onAnimationEnd={() => setEffect(false)}>
{isLoading ? <Shimmer /> : data?.url}
</td>
<td className="px-3 py-1 text-sm text-center border">{isLoading ? <Shimmer /> : data?.height}</td>
<td className="px-3 py-1 text-sm text-center border">{isLoading ? <Shimmer /> : data?.latency}</td>
<td className="px-3 py-1 text-sm border">
<td className="px-3 py-1 text-sm text-center border
relative align-middle sm:text-right
before:content-['Height'] before:absolute before:left-2 before:font-bold sm:before:hidden">{isLoading ? <Shimmer /> : data?.height}</td>
<td className="px-3 py-1 text-sm text-center border
relative align-middle sm:text-right
before:content-['Latency'] before:absolute before:left-2 before:font-bold sm:before:hidden">{isLoading ? <Shimmer /> : data?.latency}</td>
<td className="px-3 py-1 text-sm border
relative align-middle sm:text-right
before:content-['Score'] before:absolute before:left-2 before:font-bold sm:before:hidden">
{isLoading ? (
<Shimmer />
) : (
Expand All @@ -225,12 +257,16 @@ const Row = ({ values, chain, isEthMainnet, privacy, lang, className }) => {
</>
)}
</td>
<td className="px-3 py-1 text-sm border">
<td className="px-3 py-1 text-sm text-center border
relative align-middle sm:text-right
before:content-['Privacy'] before:absolute before:left-2 before:font-bold sm:before:hidden">
<Tooltip content={privacy?.trackingDetails || t('no-privacy-info')}>
{isLoading ? <Shimmer /> : <PrivacyIcon tracking={privacy?.tracking} isOpenSource={privacy?.isOpenSource} />}
</Tooltip>
</td>
<td className="px-3 py-1 text-sm text-center border">
<td className="px-3 py-1 text-sm text-center border
relative align-middle sm:text-center
before:content-[''] before:absolute before:left-2 before:font-bold sm:before:hidden">
{isLoading ? (
<Shimmer />
) : (
Expand Down
Loading