Skip to content

Commit

Permalink
feat: carousel & search icon & hovers
Browse files Browse the repository at this point in the history
  • Loading branch information
Karlen9 committed Jul 31, 2024
1 parent 794b952 commit 4dd2585
Show file tree
Hide file tree
Showing 12 changed files with 168 additions and 69 deletions.
9 changes: 8 additions & 1 deletion apps/common/components/AppCard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Image from 'next/image';
import Link from 'next/link';
import {IconShare} from '@common/icons/IconShare';

import type {TApp} from 'pages/home/[category]';
import type {ReactElement} from 'react';
Expand All @@ -12,8 +13,14 @@ export function AppCard(props: TAppCardProps): ReactElement {
return (
<Link
href={props.app.link ?? ''}
className={'bg-grey-900 border border-gray-800/50 p-6 hover:bg-[#29292966]'}>
className={'bg-grey-900 group relative border border-gray-500/50 p-6 hover:bg-gray-600/40'}>
<div className={'mb-10'}>
<div
className={
'absolute right-2 top-2 hidden size-10 items-center justify-center bg-gray-900 group-hover:flex'
}>
<IconShare className={'size-[10px]'} />
</div>
{props.app.image ? (
<Image
src={props.app.image}
Expand Down
34 changes: 34 additions & 0 deletions apps/common/components/AppsCarousel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {useEffect, useRef, useState} from 'react';
import {motion} from 'framer-motion';

import {FeaturedApp} from './FeaturedApp';

import type {TApp} from 'pages/home/[category]';
import type {ReactElement} from 'react';

export function AppsCarousel(props: {apps: TApp[]}): ReactElement {
const targetRef = useRef<HTMLDivElement | null>(null);
const [width, set_width] = useState(0);

useEffect(() => {
set_width(Number(targetRef.current?.scrollWidth) - Number(targetRef.current?.offsetWidth));
}, []);

return (
<section
ref={targetRef}
className={'relative'}>
<motion.div
drag={'x'}
dragConstraints={{
right: 0,
left: -width
}}
className={'flex gap-x-6'}>
{props.apps.map(app => (
<FeaturedApp app={app} />
))}
</motion.div>
</section>
);
}
19 changes: 7 additions & 12 deletions apps/common/components/CategorySection.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {Button} from '@yearn-finance/web-lib/components/Button';
import {IconChevron} from '@common/icons/IconChevron';

import {AppCard} from './AppCard';
Expand All @@ -15,18 +14,14 @@ type TAppSectionProps = {
export function CategorySection(props: TAppSectionProps): ReactElement {
return (
<div className={'flex flex-col gap-y-6 overflow-hidden'}>
<div className={'flex w-full items-center justify-between'}>
<div className={'flex h-12 w-full items-center justify-between px-1'}>
<div className={'text-lg font-bold text-white'}>{props.title}</div>
<div>
<Button
onClick={props.onExpandClick}
className={
'!rounded-none !border !border-white px-4 py-2 hover:!border-2 hover:!bg-transparent'
}>
<span>{'View all'}</span>
<IconChevron className={'size-6 -rotate-90'} />
</Button>
</div>
<button
onClick={props.onExpandClick}
className={'flex px-4 py-2 outline !outline-1 outline-white hover:!outline-[3px]'}>
<span className={'mr-1 text-white'}>{'View all'}</span>
<IconChevron className={'size-6 -rotate-90 text-white'} />
</button>
</div>
<div className={'grid grid-cols-4 grid-rows-1 gap-6'}>
{props.apps.slice(0, 4).map(app => (
Expand Down
24 changes: 18 additions & 6 deletions apps/common/components/FeaturedApp.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
import {IconShare} from '@common/icons/IconShare';

import type {TApp} from 'pages/home/[category]';
import type {ReactElement} from 'react';

export function FeaturedApp(props: {app: TApp}): ReactElement {
return (
<div
className={
'relative flex w-full flex-col justify-end bg-center px-6 py-10 outline outline-1 outline-gray-800/50 lg:h-[520px]'
}
style={{
backgroundImage: `url(${props.app.image})`
}}>
'group relative flex w-full cursor-pointer flex-col justify-end overflow-hidden px-6 py-10 outline outline-1 outline-gray-500/50 lg:h-[520px] lg:min-w-[384px]'
}>
<div
style={{
backgroundImage: `url(${props.app.image})`
}}
className={'absolute right-0 top-0 size-full bg-center transition-all group-hover:scale-105'}
/>
<div
className={
'absolute right-2 top-2 hidden size-10 items-center justify-center bg-gray-900 transition-all group-hover:flex'
}>
<IconShare className={'size-[10px]'} />
</div>
<div
style={{background: 'linear-gradient(180deg, rgba(12, 12, 12, 0) 0%, #0C0C0C 100%)'}}
className={'absolute left-0 top-0 size-full'}
className={'absolute left-0 top-0 size-full group-hover:scale-105'}
/>
<p className={'z-20 text-xl font-bold text-white'}>{props.app.title}</p>
<p className={'z-20 hidden text-gray-400 group-hover:block'}>{props.app.description}</p>
</div>
);
}
37 changes: 22 additions & 15 deletions apps/common/components/SearchBar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {cl} from '@builtbymom/web3/utils';
import {IconEnter} from '@common/icons/IconEnter';

import type {ChangeEvent, ReactElement} from 'react';

Expand Down Expand Up @@ -46,21 +47,27 @@ export function SearchBar(props: TSearchBar): ReactElement {
role={props.shouldSearchByClick ? 'button' : 'div'}
onClick={() => props.onSearchClick?.()}
className={cl(props.iconClassName, 'absolute right-0 text-neutral-400')}>
<svg
width={'20'}
height={'20'}
viewBox={'0 0 24 24'}
fill={'none'}
xmlns={'http://www.w3.org/2000/svg'}>
<path
fillRule={'evenodd'}
clipRule={'evenodd'}
d={
'M10 1C5.02972 1 1 5.02972 1 10C1 14.9703 5.02972 19 10 19C12.1249 19 14.0779 18.2635 15.6176 17.0318L21.2929 22.7071C21.6834 23.0976 22.3166 23.0976 22.7071 22.7071C23.0976 22.3166 23.0976 21.6834 22.7071 21.2929L17.0318 15.6176C18.2635 14.0779 19 12.1249 19 10C19 5.02972 14.9703 1 10 1ZM3 10C3 6.13428 6.13428 3 10 3C13.8657 3 17 6.13428 17 10C17 13.8657 13.8657 17 10 17C6.13428 17 3 13.8657 3 10Z'
}
fill={'currentcolor'}
/>
</svg>
{props.shouldSearchByClick && props.searchValue ? (
<div className={'rounded-md border border-gray-700 p-[6px]'}>
<IconEnter className={'size-3'} />
</div>
) : (
<svg
width={'20'}
height={'20'}
viewBox={'0 0 24 24'}
fill={'none'}
xmlns={'http://www.w3.org/2000/svg'}>
<path
fillRule={'evenodd'}
clipRule={'evenodd'}
d={
'M10 1C5.02972 1 1 5.02972 1 10C1 14.9703 5.02972 19 10 19C12.1249 19 14.0779 18.2635 15.6176 17.0318L21.2929 22.7071C21.6834 23.0976 22.3166 23.0976 22.7071 22.7071C23.0976 22.3166 23.0976 21.6834 22.7071 21.2929L17.0318 15.6176C18.2635 14.0779 19 12.1249 19 10C19 5.02972 14.9703 1 10 1ZM3 10C3 6.13428 6.13428 3 10 3C13.8657 3 17 6.13428 17 10C17 13.8657 13.8657 17 10 17C6.13428 17 3 13.8657 3 10Z'
}
fill={'currentcolor'}
/>
</svg>
)}
</div>
</div>
</div>
Expand Down
51 changes: 26 additions & 25 deletions apps/common/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,35 +22,36 @@ export function Sidebar(props: TSidebarProps): ReactElement {
return (
<div
className={
'flex h-full w-72 flex-col justify-between border border-gray-800/50 bg-white/5 p-4 py-6 text-white'
'flex h-full w-72 flex-col justify-between border border-gray-500/50 bg-white/5 py-6 text-white'
}>
<div>
<LogoYearn
className={'mb-10 size-10 pl-[10px]'}
back={'text-blue-500'}
front={'text-white'}
/>
<SearchBar
className={'!w-full !border-x-0 !border-b-2 !border-t-0 !border-white !bg-gray-800 '}
searchPlaceholder={'Search Apps'}
searchValue={configuration.searchValue}
onSearch={(value: string) => {
dispatch({type: 'SET_SEARCH', payload: value});
}}
shouldSearchByClick
onSearchClick={() => {
if (!configuration.searchValue) {
return;
}
router.push(`/home/search?query=${configuration.searchValue}`);
}}
/>

<div className={'ml-2 mt-8 flex flex-col'}>
<div className={'px-4'}>
<LogoYearn
className={'mb-10 size-10 pl-[10px]'}
back={'text-blue-500'}
front={'text-white'}
/>
<SearchBar
className={'!w-full !border-x-0 !border-b-2 !border-t-0 !border-white !bg-gray-500 '}
searchPlaceholder={'Search Apps'}
searchValue={configuration.searchValue}
onSearch={(value: string) => {
dispatch({type: 'SET_SEARCH', payload: value});
}}
shouldSearchByClick
onSearchClick={() => {
if (!configuration.searchValue) {
return;
}
router.push(`/home/search?query=${configuration.searchValue}`);
}}
/>
</div>
<div className={'mt-8 flex flex-col'}>
{props.tabs.map(tab => (
<Link
className={cl(
'py-2 text-base',
'py-2 px-6 text-base hover:bg-gray-600/40',
currentTab === tab.route ? 'text-white font-bold' : 'text-gray-400'
)}
href={tab.route === '/' ? tab.route : `/home/${tab.route}`}
Expand All @@ -61,7 +62,7 @@ export function Sidebar(props: TSidebarProps): ReactElement {
</div>
</div>

<div className={'flex flex-wrap gap-x-3 gap-y-4 px-2'}>
<div className={'flex flex-wrap gap-x-3 gap-y-4 px-6'}>
{LANDING_SIDEBAR_LINKS.map(link => (
<Link
className={'text-xs text-gray-400'}
Expand Down
39 changes: 39 additions & 0 deletions apps/common/icons/IconEnter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type {ReactElement} from 'react';

export function IconEnter(props: React.SVGProps<SVGSVGElement>): ReactElement {
return (
<svg
{...props}
width={'12'}
height={'12'}
viewBox={'0 0 12 12'}
fill={'none'}
xmlns={'http://www.w3.org/2000/svg'}>
<g clip-path={'url(#clip0_2013_717)'}>
<path
d={'M4 5L1 8L4 11'}
stroke={'#9D9D9D'}
strokeWidth={'1.5'}
strokeLinecap={'round'}
strokeLinejoin={'round'}
/>
<path
d={'M6 1H9C10.1046 1 11 1.89543 11 3V6C11 7.10457 10.1046 8 9 8H2'}
stroke={'#9D9D9D'}
strokeWidth={'1.5'}
strokeLinecap={'round'}
strokeLinejoin={'round'}
/>
</g>
<defs>
<clipPath id={'clip0_2013_717'}>
<rect
width={'12'}
height={'12'}
fill={'white'}
/>
</clipPath>
</defs>
</svg>
);
}
2 changes: 1 addition & 1 deletion apps/common/icons/IconShare.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function IconShare(props: React.SVGProps<SVGSVGElement>): ReactElement {
/>
<path
d={'M11 1L1 11'}
stroke={'currentcolor'}
stroke={'white'}
strokeWidth={'2'}
strokeLinecap={'round'}
strokeLinejoin={'round'}
Expand Down
6 changes: 6 additions & 0 deletions apps/common/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ export const YEARN_X_APPS = [
];

export const FEATURED_APPS = [
{
title: 'Juiced',
description: 'Product description example text product description example text',
image: '/juiced-bg.png'
},

{
title: 'Juiced',
description: 'Product description example text product description example text',
Expand Down
4 changes: 2 additions & 2 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const WithLayout = memo(function WithLayout(props: {supportedNetworks: Chain[]}
id={'app'}
className={cl('mb-0 bg-gray-900 justify-center min-h-screen flex font-aeonik')}>
<div className={'flex w-full max-w-[1480px] justify-start'}>
<motion.nav className={'sticky py-4 pl-4'}>
<motion.nav className={'fixed top-0 z-20 h-screen py-4 pl-4'}>
<Sidebar
tabs={[
{title: 'Home', route: '/'},
Expand All @@ -72,7 +72,7 @@ const WithLayout = memo(function WithLayout(props: {supportedNetworks: Chain[]}
animate={'enter'}
exit={'exit'}
variants={variants}
className={'ml-[100px] w-full'}>
className={'ml-[388px] w-full overflow-x-hidden'}>
<Component
router={props.router}
{...pageProps}
Expand Down
8 changes: 2 additions & 6 deletions pages/home/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {type ReactElement} from 'react';
import {useRouter} from 'next/navigation';
import {useMountEffect} from '@react-hookz/web';
import {AppsCarousel} from '@common/components/AppsCarousel';
import {CategorySection} from '@common/components/CategorySection';
import {FeaturedApp} from '@common/components/FeaturedApp';
import {useSearch} from '@common/contexts/useSearch';
import {COMMUNITY_APPS, FEATURED_APPS, YEARN_X_APPS} from '@common/utils/constants';

Expand Down Expand Up @@ -36,11 +36,7 @@ export default function Home(): ReactElement {

<div>
<h1 className={'mb-6 text-lg text-white'}>{'Featured Apps'}</h1>
<div className={'flex gap-x-6'}>
{FEATURED_APPS.map(app => (
<FeaturedApp app={app} />
))}
</div>
<AppsCarousel apps={FEATURED_APPS} />
</div>

<div className={'flex flex-col gap-[64px]'}>
Expand Down
4 changes: 3 additions & 1 deletion tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ module.exports = {
primary: '#0657F9',
gray: {
400: '#9D9D9D',
800: '#282828',
500: '#282828',
600: '#292929',
700: '#424242',
900: '#0C0C0C'
},
blue: {
Expand Down

0 comments on commit 4dd2585

Please sign in to comment.