Skip to content

Commit

Permalink
feat: cutaways + scrollbar dismiss + search layout + mobile layout
Browse files Browse the repository at this point in the history
  • Loading branch information
Karlen9 committed Aug 5, 2024
1 parent 4dd2585 commit 2976e61
Show file tree
Hide file tree
Showing 33 changed files with 844 additions and 140 deletions.
80 changes: 54 additions & 26 deletions apps/common/components/AppCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,60 @@ type TAppCardProps = {

export function AppCard(props: TAppCardProps): ReactElement {
return (
<Link
href={props.app.link ?? ''}
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]'} />
<>
<Link
href={props.app.appURI ?? ''}
target={'_blank'}
className={
'bg-grey-900 group relative hidden border border-gray-500/50 p-6 hover:bg-gray-600/40 md:block'
}>
<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.logoURI ? (
<Image
src={props.app.logoURI}
alt={props.app.name}
width={240}
height={240}
className={'size-[120px] rounded-[32px] object-cover'}
/>
) : (
<div className={'size-[120px] rounded-[32px] bg-fallback'} />
)}
</div>
{props.app.image ? (
<Image
src={props.app.image}
alt={props.app.title}
width={100}
height={100}
className={'object-contain'}
/>
) : (
<div className={'size-[120px] rounded-[32px] bg-fallback'} />
)}
</div>
<div className={'mb-2 text-2xl font-bold text-white'}>{props.app.title}</div>
<div className={''}>
<p className={' text-base text-gray-400'}>{props.app.description}</p>
</div>
</Link>
<div className={'mb-2 text-2xl font-bold text-white'}>{props.app.name}</div>

<p className={'text-base text-gray-400'}>{props.app.description}</p>
</Link>
<Link
href={props.app.appURI}
className={'flex items-center md:hidden'}>
<div className={''}>
{props.app.logoURI ? (
<div className={'size-16 rounded-2xl md:rounded-[32px]'}>
<Image
src={props.app.logoURI}
alt={props.app.name}
width={300}
height={300}
className={'size-full rounded-2xl bg-center object-cover md:rounded-[32px]'}
/>
</div>
) : (
<div className={'size-16 rounded-2xl bg-fallback md:rounded-[32px]'} />
)}
</div>

<div className={'ml-4'}>
<div className={'mb-1 text-base font-bold text-gray-300'}>{props.app.name}</div>
<p className={'text-base text-gray-400'}>{props.app.description}</p>
</div>
</Link>
</>
);
}
17 changes: 15 additions & 2 deletions apps/common/components/AppsCarousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,28 @@ export function AppsCarousel(props: {apps: TApp[]}): ReactElement {
<section
ref={targetRef}
className={'relative'}>
<div
className={
'pointer-events-none absolute -left-36 top-0 z-10 h-full w-1/6 bg-gradient-to-r from-gray-900 to-transparent'
}
/>
<div
className={
'pointer-events-none absolute right-0 top-0 z-10 h-full w-1/5 bg-gradient-to-l from-gray-900 to-transparent'
}
/>
<motion.div
drag={'x'}
dragConstraints={{
right: 0,
left: -width
}}
className={'flex gap-x-6'}>
{props.apps.map(app => (
<FeaturedApp app={app} />
{props.apps.map((app, i) => (
<FeaturedApp
key={app.name + i}
app={app}
/>
))}
</motion.div>
</section>
Expand Down
9 changes: 6 additions & 3 deletions apps/common/components/CategorySection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@ export function CategorySection(props: TAppSectionProps): ReactElement {
<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 => (
<AppCard app={app} />
<div className={'flex grid-rows-1 flex-col gap-6 md:grid md:grid-cols-2 lg:grid-cols-4'}>
{props.apps.slice(0, 4).map((app, i) => (
<AppCard
key={app.name + i}
app={app}
/>
))}
</div>
</div>
Expand Down
31 changes: 31 additions & 0 deletions apps/common/components/Cutaway.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Link from 'next/link';
import {IconShare} from '@common/icons/IconShare';

import type {ReactElement} from 'react';

type TCutawayProps = {
title: string;
description: string;
link: string;
icon: ReactElement;
};

export function Cutaway(props: TCutawayProps): ReactElement {
return (
<Link
href={props.link}
target={'_blank'}
className={'relative flex items-center justify-between bg-gray-600/20 p-6 hover:bg-gray-600/40'}>
<div className={'flex flex-col md:flex-row'}>
<div className={'flex size-20 items-center justify-center'}>{props.icon}</div>
<div className={'md:ml-6'}>
<p className={'mb-2 text-2xl font-bold text-gray-300'}>{props.title}</p>
<p className={'text-base text-gray-400'}>{props.description}</p>
</div>
</div>
<div className={'absolute right-7 top-7 md:static'}>
<IconShare />
</div>
</Link>
);
}
30 changes: 16 additions & 14 deletions apps/common/components/FeaturedApp.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import Image from 'next/image';
import {cl} from '@builtbymom/web3/utils';
import {IconShare} from '@common/icons/IconShare';

import type {TApp} from 'pages/home/[category]';
Expand All @@ -6,26 +8,26 @@ import type {ReactElement} from 'react';
export function FeaturedApp(props: {app: TApp}): ReactElement {
return (
<div
className={
'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'}
className={cl(
'group relative flex h-[376px] w-full min-w-[280px] cursor-pointer flex-col justify-end overflow-hidden px-6 py-10 outline outline-1 outline-gray-500/50 md:h-[520px] md:min-w-[384px]'
)}>
<Image
src={props.app.logoURI}
alt={props.app.name}
width={1400}
height={2000}
className={
'absolute right-0 top-0 size-full bg-center object-cover 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'
'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 group-hover:scale-105'}
/>
<p className={'z-20 text-xl font-bold text-white'}>{props.app.title}</p>
<div className={'absolute left-0 top-0 size-full bg-gradient-to-b from-transparent to-gray-900'} />
<p className={'z-20 text-xl font-bold text-white'}>{props.app.name}</p>
<p className={'z-20 hidden text-gray-400 group-hover:block'}>{props.app.description}</p>
</div>
);
Expand Down
87 changes: 87 additions & 0 deletions apps/common/components/MobileNavbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import Link from 'next/link';
import {usePathname} from 'next/navigation';
import {cl} from '@builtbymom/web3/utils';
import {IconCommunity} from '@common/icons/IconCommunity';
import {IconYearn} from '@common/icons/IconYearn';
import {IconYearnXApps} from '@common/icons/IconYearnXApps';
import {LogoDiscordRound} from '@common/icons/LogoDiscordRound';
import {LogoParagraphRound} from '@common/icons/LogoParagraphRound';
import {LogoTwitterRound} from '@common/icons/LogoTwitterRound';
import {LANDING_SIDEBAR_LINKS, MENU_TABS} from '@common/utils/constants';

import type {ReactElement} from 'react';

const iconsDict = {
'/': <IconYearn />,
community: <IconCommunity />,
'yearn-x': <IconYearnXApps />
};

export function MobileNavbar({
set_isNavbarOpen,
set_isSearchOpen
}: {
set_isNavbarOpen: (value: boolean) => void;
set_isSearchOpen: (value: boolean) => void;
}): ReactElement {
const pathName = usePathname();

const currentTab = pathName?.startsWith('/home/') ? pathName?.split('/')[2] : '/';
return (
<div
className={
'flex h-full w-screen flex-col justify-end border-t border-gray-600/50 bg-gradient-to-b from-gray-900 to-[#1A1A1A] '
}>
<div className={'flex flex-col items-start gap-y-2 bg-transparent p-6 pb-4'}>
{MENU_TABS.map(tab => (
<Link
className={cl(
'text-base flex items-center gap-x-2 py-2 text-gray-400',
currentTab === tab.route ? 'text-white' : 'text-gray-400'
)}
onClick={() => {
set_isSearchOpen(false);
set_isNavbarOpen(false);
}}
href={tab.route === '/' ? tab.route : `/home/${tab.route}`}>
<div className={'flex size-6 items-center justify-center'}>
{iconsDict[tab.route as '/' | 'community' | 'yearn-x']}
</div>
<p>{tab.title}</p>
</Link>
))}
</div>

<div className={'w-full border-t border-gray-500 p-6'}>
<div className={'flex w-full justify-between'}>
{LANDING_SIDEBAR_LINKS.slice(0, 5).map(link => (
<Link
href={link.href}
className={'text-sm text-gray-400'}
target={'_blank'}>
{link.title}
</Link>
))}
</div>

<div className={'mt-6 flex gap-x-6'}>
<Link
target={'_blank'}
href={'https://discord.com/invite/yearn'}>
<LogoDiscordRound />
</Link>
<Link
target={'_blank'}
href={''}>
<LogoParagraphRound />
</Link>
<Link
target={'_blank'}
href={'https://twitter.com/yearnfi'}>
<LogoTwitterRound />
</Link>
</div>
</div>
</div>
);
}
75 changes: 75 additions & 0 deletions apps/common/components/MobileTopNav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {type ReactElement, useCallback} from 'react';
import {useRouter} from 'next/navigation';
import {useSearch} from '@common/contexts/useSearch';
import {IconBurger} from '@common/icons/IconBurger';
import {IconSearch} from '@common/icons/IconSearch';
import {LogoYearn} from '@common/icons/LogoYearn';

import {SearchBar} from './SearchBar';

export function MobileTopNav({
isSearchOpen,
set_isSearchOpen,
set_isNavbarOpen
}: {
isSearchOpen: boolean;
set_isSearchOpen: React.Dispatch<React.SetStateAction<boolean>>;
set_isNavbarOpen: React.Dispatch<React.SetStateAction<boolean>>;
}): ReactElement {
const {configuration, dispatch} = useSearch();
const router = useRouter();

const onSearchClick = useCallback(() => {
if (!configuration.searchValue) {
return;
}
router.push(`/home/search?query=${configuration.searchValue}`);
}, [configuration.searchValue, router]);

return (
<div className={'z-50 bg-gray-900'}>
<div className={'flex w-full justify-between bg-gray-900 p-6'}>
<div className={'flex items-center'}>
<button
className={'mr-4'}
onClick={() => set_isNavbarOpen(prev => !prev)}>
<IconBurger />
</button>
<button
onClick={() => {
router.push('/');
set_isSearchOpen(false);
}}>
<LogoYearn
className={'size-8'}
back={'text-blue-500'}
front={'text-white'}
/>
</button>
</div>
<div>
<button
onClick={() => {
set_isNavbarOpen(false);
set_isSearchOpen(prev => !prev);
}}>
<IconSearch />
</button>
</div>
</div>

{isSearchOpen && (
<div className={'!w-full bg-gray-900 px-6 pb-6'}>
<SearchBar
className={'!max-w-none !border-0 !border-white !bg-gray-500 text-white '}
searchValue={configuration.searchValue}
onSearch={(value: string) => dispatch({type: 'SET_SEARCH', payload: value})}
searchPlaceholder={'Search Apps'}
onSearchClick={onSearchClick}
shouldSearchByClick
/>
</div>
)}
</div>
);
}
Loading

0 comments on commit 2976e61

Please sign in to comment.