Add chain list views

This commit is contained in:
HeesungB 2022-12-07 18:17:59 +09:00
parent 4ba6812c9a
commit 32caa5bf87
12 changed files with 598 additions and 228 deletions

View File

@ -1,5 +1,6 @@
// NextJs // NextJs
import Image from "next/image"; import Image from "next/image";
import Link from "next/link";
// Image Assets // Image Assets
import LogoIcon from "../../public/images/svg/logo.svg"; import LogoIcon from "../../public/images/svg/logo.svg";
@ -10,8 +11,10 @@ import { FunctionComponent } from "react";
export const Logo: FunctionComponent = () => { export const Logo: FunctionComponent = () => {
return ( return (
<Link href="/">
<LogoContainer> <LogoContainer>
<Image src={LogoIcon} fill={true} alt="Home Logo" /> <Image src={LogoIcon} fill={true} alt="Home Logo" />
</LogoContainer> </LogoContainer>
</Link>
); );
}; };

View File

@ -0,0 +1,3 @@
export * from "./skeleton-animation";
export * from "./skeleton-circle";
export * from "./skeleton-text";

View File

@ -0,0 +1,29 @@
import styled from "styled-components";
import color from "../../styles/color";
export const SkeletonAnimation = styled.div`
opacity: 0.35 !important;
background-image: linear-gradient(
0.25turn,
transparent,
${color.grey["400"]},
transparent
),
linear-gradient(${color.grey["500"]}, ${color.grey["500"]}),
radial-gradient(
38px circle at 19px 19px,
${color.grey["500"]} 50%,
transparent 51%
),
linear-gradient(${color.grey["500"]}, ${color.grey["500"]});
background-repeat: no-repeat;
background-size: 315px 250px, 315px 180px, 100px 100px, 225px 30px;
background-position: -315px 0, 0 0, 0px 190px, 50px 195px;
animation: loading 2s infinite;
@keyframes loading {
to {
background-position: 315px 0, 0 0, 0 190px, 50px 195px;
}
}
`;

View File

@ -0,0 +1,17 @@
// Styles
import color from "../../styles/color";
import styled from "styled-components";
// Components
import { SkeletonAnimation } from "./skeleton-animation";
// Types
import { WidthHeightProps } from "../../types";
export const SkeletonCircle = styled(SkeletonAnimation)<WidthHeightProps>`
width: ${(props) => props.width};
height: ${(props) => props.height};
background-color: ${color.grey["500"]};
border-radius: 50%;
`;

View File

@ -0,0 +1,13 @@
// Styles
import styled from "styled-components";
// Components
import { SkeletonAnimation } from "./skeleton-animation";
// Types
import { WidthHeightProps } from "../../types";
export const SkeletonText = styled(SkeletonAnimation)<WidthHeightProps>`
width: ${(props) => props.width};
height: ${(props) => props.height};
`;

View File

@ -5,6 +5,18 @@ const nextConfig = {
compiler: { compiler: {
styledComponents: true, styledComponents: true,
}, },
images: {
remotePatterns: [
{
protocol: "https",
hostname: "pbs.twimg.com",
},
{
protocol: "https",
hostname: "raw.githubusercontent.com",
},
],
},
}; };
module.exports = nextConfig; module.exports = nextConfig;

View File

@ -1,19 +1,71 @@
// Style // React
import styled from "styled-components"; import { useEffect, useState } from "react";
import { Logo } from "../../components/logo";
// NextJs
import Image from "next/image";
// Styles
import color from "../../styles/color"; import color from "../../styles/color";
// Components
import { Logo } from "../../components/logo";
import { SkeletonCircle, SkeletonText } from "../../components/skeleton";
import {
Container,
MainContainer,
ContentContainer,
ProfileContainer,
ProfileFollowContainer,
ProfileContentContainer,
ProfileImageContainer,
ProfileNameContainer,
ProfileFollowerContainer,
ProfileFollowBold,
ProfileUserNameContainer,
ProfileDescriptionContainer,
ChainListTitle,
SearchContainer,
ChainContainer,
ChainItemContainer,
ChainImageContainer,
ChainInfoContainer,
ChainListTitleContainer,
ChainName,
WalletAddress,
Flex1,
ChainCheckBox,
ButtonContainer,
SkeletonDivider,
SkeletonButton,
} from "./styled";
import { PrimaryButton } from "../../components/primary-button";
export default function VerificationPage() { export default function VerificationPage() {
const [isLoading, setIsLoading] = useState(true);
const dummy = new Array(5);
useEffect(() => {
setTimeout(() => setIsLoading(false), 1500);
}, []);
return ( return (
<Container> <Container>
<Logo /> <Logo />
<MainContainer> <MainContainer>
{isLoading ? (
<ContentContainer> <ContentContainer>
<ProfileContainer color={color.grey["700"]}> <ProfileContainer color={color.grey["700"]}>
<SkeletonCircle width="5.5rem" height="5.5rem" /> <SkeletonCircle width="5.5rem" height="5.5rem" />
<ProfileContentContainer> <ProfileContentContainer>
<ProfileNameContainer>
<SkeletonText width="5rem" height="1.5rem" /> <SkeletonText width="5rem" height="1.5rem" />
</ProfileNameContainer>
<ProfileUserNameContainer>
<SkeletonText width="5rem" height="1rem" />
</ProfileUserNameContainer>
<ProfileFollowContainer> <ProfileFollowContainer>
<SkeletonText width="8rem" height="1rem" /> <SkeletonText width="8rem" height="1rem" />
<SkeletonText width="8rem" height="1rem" /> <SkeletonText width="8rem" height="1rem" />
@ -23,7 +75,9 @@ export default function VerificationPage() {
</ProfileContentContainer> </ProfileContentContainer>
</ProfileContainer> </ProfileContainer>
<SkeletonTitle /> <ChainListTitleContainer>
<SkeletonText width="8rem" height="1.5rem" />
</ChainListTitleContainer>
<ChainContainer color={color.grey["700"]}> <ChainContainer color={color.grey["700"]}>
<ChainItemContainer> <ChainItemContainer>
@ -83,167 +137,180 @@ export default function VerificationPage() {
<SkeletonText width="12rem" height="1rem" /> <SkeletonText width="12rem" height="1rem" />
</ChainInfoContainer> </ChainInfoContainer>
</ChainItemContainer> </ChainItemContainer>
<SkeletonDivider />
</ChainContainer> </ChainContainer>
<ButtonContainer> <ButtonContainer>
<SkeletonButton /> <SkeletonButton />
</ButtonContainer> </ButtonContainer>
</ContentContainer> </ContentContainer>
) : (
<ContentContainer>
<ProfileContainer color={color.grey["700"]}>
<ProfileImageContainer>
<Image
src="https://pbs.twimg.com/profile_images/1503375455532974084/KWG1XmEc_400x400.jpg"
alt="profile image"
fill={true}
/>
</ProfileImageContainer>
<ProfileContentContainer>
<ProfileNameContainer>BaeHeesung</ProfileNameContainer>
<ProfileUserNameContainer>
@BaeHeesung25
</ProfileUserNameContainer>
<ProfileFollowContainer>
<ProfileFollowerContainer>
<ProfileFollowBold>42</ProfileFollowBold> Following
</ProfileFollowerContainer>
<ProfileFollowerContainer>
<ProfileFollowBold>42</ProfileFollowBold> Following
</ProfileFollowerContainer>
</ProfileFollowContainer>
<ProfileDescriptionContainer>
Product UIUX designer @Keplrwallet and I like @regen_network🌿
</ProfileDescriptionContainer>
</ProfileContentContainer>
</ProfileContainer>
<ChainListTitleContainer>
<ChainListTitle>Chain List</ChainListTitle>
<SearchContainer>Search</SearchContainer>
</ChainListTitleContainer>
<ChainContainer color={color.grey["700"]}>
<ChainItemContainer>
<ChainImageContainer width="3rem" height="3rem">
<Image
src="https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/osmosis/chain.png"
alt="chain image"
fill={true}
/>
</ChainImageContainer>
<ChainInfoContainer>
<ChainName>.osmo</ChainName>
<WalletAddress>
cosmos14ky6udatsvdx859050mrnr7rvml0huue2wszvs
</WalletAddress>
</ChainInfoContainer>
<Flex1 />
<ChainCheckBox />
</ChainItemContainer>
<ChainItemContainer>
<ChainImageContainer width="3rem" height="3rem">
<Image
src="https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/osmosis/chain.png"
alt="chain image"
fill={true}
/>
</ChainImageContainer>
<ChainInfoContainer>
<ChainName>.osmo</ChainName>
<WalletAddress>
cosmos14ky6udatsvdx859050mrnr7rvml0huue2wszvs
</WalletAddress>
</ChainInfoContainer>
<Flex1 />
<ChainCheckBox />
</ChainItemContainer>
<ChainItemContainer>
<ChainImageContainer width="3rem" height="3rem">
<Image
src="https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/osmosis/chain.png"
alt="chain image"
fill={true}
/>
</ChainImageContainer>
<ChainInfoContainer>
<ChainName>.osmo</ChainName>
<WalletAddress>
cosmos14ky6udatsvdx859050mrnr7rvml0huue2wszvs
</WalletAddress>
</ChainInfoContainer>
<Flex1 />
<ChainCheckBox />
</ChainItemContainer>
<ChainItemContainer>
<ChainImageContainer width="3rem" height="3rem">
<Image
src="https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/osmosis/chain.png"
alt="chain image"
fill={true}
/>
</ChainImageContainer>
<ChainInfoContainer>
<ChainName>.osmo</ChainName>
<WalletAddress>
cosmos14ky6udatsvdx859050mrnr7rvml0huue2wszvs
</WalletAddress>
</ChainInfoContainer>
<Flex1 />
<ChainCheckBox />
</ChainItemContainer>
<ChainItemContainer>
<ChainImageContainer width="3rem" height="3rem">
<Image
src="https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/osmosis/chain.png"
alt="chain image"
fill={true}
/>
</ChainImageContainer>
<ChainInfoContainer>
<ChainName>.osmo</ChainName>
<WalletAddress>
cosmos14ky6udatsvdx859050mrnr7rvml0huue2wszvs
</WalletAddress>
</ChainInfoContainer>
<Flex1 />
<ChainCheckBox />
</ChainItemContainer>
<ChainItemContainer>
<ChainImageContainer width="3rem" height="3rem">
<Image
src="https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/osmosis/chain.png"
alt="chain image"
fill={true}
/>
</ChainImageContainer>
<ChainInfoContainer>
<ChainName>.osmo</ChainName>
<WalletAddress>
cosmos14ky6udatsvdx859050mrnr7rvml0huue2wszvs
</WalletAddress>
</ChainInfoContainer>
<Flex1 />
<ChainCheckBox />
</ChainItemContainer>
</ChainContainer>
<ButtonContainer>
<PrimaryButton>Register</PrimaryButton>
</ButtonContainer>
</ContentContainer>
)}
</MainContainer> </MainContainer>
</Container> </Container>
); );
} }
const Container = styled.div`
width: 100vw;
height: 100vh;
`;
const MainContainer = styled.div`
display: flex;
justify-content: center;
color: white;
`;
const ContentContainer = styled.div`
display: flex;
flex-direction: column;
width: 40rem;
margin-top: 5rem;
`;
const ProfileContainer = styled.div`
display: flex;
flex-direction: row;
width: 100%;
padding: 2rem 2rem;
background-color: ${(props) => props.color};
`;
const ProfileContentContainer = styled.div`
display: flex;
flex-direction: column;
gap: 1rem;
margin-left: 1.5rem;
`;
const ProfileFollowContainer = styled.div`
display: flex;
flex-direction: row;
gap: 2rem;
`;
const ChainContainer = styled.div`
display: flex;
flex-direction: column;
gap: 1rem;
width: 100%;
padding: 2rem 2rem 1rem 2rem;
background-color: ${(props) => props.color};
`;
const ChainItemContainer = styled.div`
display: flex;
flex-direction: row;
gap: 1rem;
`;
const ChainImageContainer = styled.div<WidthHeightProps>`
width: ${(props) => props.width};
height: ${(props) => props.height};
position: relative;
`;
const ChainInfoContainer = styled.div`
display: flex;
flex-direction: column;
gap: 0.5rem;
`;
const ButtonContainer = styled.div`
display: flex;
justify-content: center;
margin-top: 2rem;
`;
interface WidthHeightProps {
width: string | number;
height: string | number;
}
const SkeletonAnimation = styled.div`
opacity: 0.35 !important;
background-image: linear-gradient(
0.25turn,
transparent,
${color.grey["400"]},
transparent
),
linear-gradient(${color.grey["500"]}, ${color.grey["500"]}),
radial-gradient(
38px circle at 19px 19px,
${color.grey["500"]} 50%,
transparent 51%
),
linear-gradient(${color.grey["500"]}, ${color.grey["500"]});
background-repeat: no-repeat;
background-size: 315px 250px, 315px 180px, 100px 100px, 225px 30px;
background-position: -315px 0, 0 0, 0px 190px, 50px 195px;
animation: loading 2s infinite;
@keyframes loading {
to {
background-position: 315px 0, 0 0, 0 190px, 50px 195px;
}
}
`;
const SkeletonCircle = styled(SkeletonAnimation)<WidthHeightProps>`
width: ${(props) => props.width};
height: ${(props) => props.height};
background-color: ${color.grey["500"]};
border-radius: 50%;
`;
const SkeletonText = styled(SkeletonAnimation)<WidthHeightProps>`
width: ${(props) => props.width};
height: ${(props) => props.height};
`;
const SkeletonTitle = styled.div`
width: 8rem;
height: 1.5rem;
margin-top: 3rem;
margin-bottom: 1rem;
background-color: ${color.grey["700"]};
`;
const SkeletonButton = styled.div`
width: 12rem;
height: 4rem;
background-color: ${color.grey["700"]};
`;
const SkeletonDivider = styled(SkeletonAnimation)`
width: 100%;
height: 1px;
background-color: ${color.grey["600"]};
`;

View File

@ -0,0 +1,219 @@
import styled from "styled-components";
import color from "../../styles/color";
import { WidthHeightProps } from "../../types";
import { SkeletonAnimation } from "../../components/skeleton";
export const Container = styled.div`
width: 100vw;
height: 100vh;
`;
export const MainContainer = styled.div`
display: flex;
justify-content: center;
color: white;
`;
export const ContentContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
width: 40rem;
margin-top: 5rem;
`;
export const ProfileContainer = styled.div`
display: flex;
flex-direction: row;
width: 100%;
padding: 1.5rem 2rem;
background-color: ${(props) => props.color};
`;
export const ProfileContentContainer = styled.div`
display: flex;
flex-direction: column;
gap: 0.85rem;
margin-left: 1.5rem;
`;
export const ProfileFollowContainer = styled.div`
display: flex;
flex-direction: row;
gap: 1.5rem;
`;
export const ChainContainer = styled.div`
display: flex;
flex-direction: column;
width: 100%;
max-height: 33rem;
overflow: scroll;
background-color: ${(props) => props.color};
`;
export const ChainItemContainer = styled.div`
display: flex;
flex-direction: row;
align-items: center;
gap: 1rem;
padding: 1.5rem;
&:hover {
background: ${color.grey["900"]};
}
`;
export const ChainImageContainer = styled.div<WidthHeightProps>`
width: ${(props) => props.width};
height: ${(props) => props.height};
position: relative;
`;
export const ChainInfoContainer = styled.div`
display: flex;
flex-direction: column;
gap: 0.5rem;
`;
export const ButtonContainer = styled.div`
width: 10rem;
height: 4rem;
margin-top: 2rem;
`;
export const SkeletonButton = styled.div`
width: 12rem;
height: 4rem;
background-color: ${color.grey["700"]};
`;
export const SkeletonDivider = styled(SkeletonAnimation)`
width: 100%;
height: 1px;
background-color: ${color.grey["600"]};
`;
export const ProfileImageContainer = styled.div`
width: 5rem;
height: 5rem;
margin-top: -3rem;
border-radius: 50%;
overflow: hidden;
position: relative;
`;
export const ProfileNameContainer = styled.div`
font-weight: 600;
font-size: 1.2rem;
line-height: 1.5rem;
color: ${color.white};
`;
export const ProfileUserNameContainer = styled.div`
font-weight: 500;
font-size: 0.8rem;
line-height: 1rem;
color: ${color.grey["100"]};
`;
export const ProfileFollowerContainer = styled.div`
font-weight: 500;
font-size: 0.8rem;
line-height: 1rem;
color: ${color.grey["400"]};
`;
export const ProfileFollowBold = styled.span`
font-weight: 600;
font-size: 0.8rem;
line-height: 1rem;
color: ${color.white};
`;
export const ProfileDescriptionContainer = styled.div`
font-weight: 500;
font-size: 0.8rem;
line-height: 1rem;
color: ${color.grey["300"]};
`;
export const ChainListTitleContainer = styled.div`
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
margin-top: 2rem;
margin-bottom: 1rem;
`;
export const ChainListTitle = styled.div`
font-weight: 700;
font-size: 1.5rem;
line-height: 1.9rem;
color: ${color.white};
`;
export const SearchContainer = styled.div`
display: flex;
align-items: center;
border-radius: 3rem;
min-width: 10rem;
height: 2rem;
background-color: ${color.grey["700"]};
`;
export const ChainName = styled.div`
font-weight: 600;
font-size: 0.8rem;
line-height: 1rem;
color: ${color.grey["100"]};
`;
export const WalletAddress = styled.div`
font-weight: 500;
font-size: 0.8rem;
line-height: 1rem;
color: ${color.grey["400"]};
`;
export const Flex1 = styled.div`
flex: 1;
`;
export const ChainCheckBox = styled.input.attrs({ type: "checkbox" })`
width: 1.5rem;
height: 1.5rem;
`;

View File

@ -14,11 +14,13 @@ const grey = {
900: "#181818", 900: "#181818",
}; };
const white = "#FFFFFF";
const black = "#121212"; const black = "#121212";
const color = { const color = {
primary, primary,
grey, grey,
white,
black, black,
orange, orange,
}; };

1
types/index.ts Normal file
View File

@ -0,0 +1 @@
export * from "./width-height-props";

View File

@ -0,0 +1,4 @@
export interface WidthHeightProps {
width: string | number;
height: string | number;
}