diff --git a/index.html b/index.html index 619e09137..0a8cef947 100644 --- a/index.html +++ b/index.html @@ -27,6 +27,10 @@ + \ No newline at end of file diff --git a/src/assets/locales/en/common.json b/src/assets/locales/en/common.json index bbead2169..bfbae35d0 100644 --- a/src/assets/locales/en/common.json +++ b/src/assets/locales/en/common.json @@ -32,7 +32,7 @@ "subtitle": "Go back to explorer page" }, "navButtons": { - "connectWallet": "Connect wallet", + "connectWallet": "Connect", "giveFeedback": "Give feedback" }, "labels": { @@ -1010,17 +1010,15 @@ }, "explore": { "hero": { - "title": "Explore the DAO World", - "subtitle1": "Build your DAO, explore communities, and find inspiration for your project all in one place." + "title": "Governed on Aragon", + "subtitle1": "Explore the organizations using our modular governance stack to secure their onchain governance." }, "explorer": { "title": "Explore DAOs", "myDaos": "My DAOs", "popular": "Popular", "newest": "Newest", - "walletBased": "Wallet-based", - "showMore": "Show more", - "tokenBased": "Token-based" + "showMore": "Show more" }, "activeProposals": "Active proposals", "showMore": "Show more", @@ -1038,8 +1036,13 @@ "linkLabel": "Learn about DAOs", "linkURL": "https://aragon.org/education-portal" }, + "build": { + "linkLabel": "Build faster", + "linkURL": "https://docs.aragon.org" + }, "toggleFilter": { - "Favourites": "Following", + "favourites": "Following", + "featuredDAOs": "Featured", "allDAOs": "All DAOs ", "member": "Member" }, @@ -1128,19 +1131,19 @@ }, "cta": { "create": { - "title": "Create your DAO", - "description": "Mint tokens, set governance parameters, and deploy your DAO on-chain in minutes with our no-code setup process.", + "title": "Create", + "description": "Easily deploy a new DAO on Aragon OSx in minutes with our simple, no-code deployment wizard.", "actionLabel": "Create a DAO" }, "learn": { - "title": "Learn about DAOs", - "description": "Find inspiration and learn about DAOs in our education portal designed for builders at every stage of the journey.", + "title": "Learn", + "description": "Master onchain governance with our Resource Library's case studies, guides, and expert insights into Aragon OSx.", "actionLabel": "Learn about DAOs" }, "build": { - "title": "Build faster", - "description": "Use our governance plugins to build a DAO, dApp, or anything you can imagine on the Aragon OSx protocol.", - "actionLabel": "Coming soon" + "title": "Build", + "description": "Take the DIY approach: build Aragon OSx plugins or your own application using our Governance UI Kit and App Template.", + "actionLabel": "Build a custom DAO" }, "404": { "titleLine1": "Oh no,", diff --git a/src/components/ctaCard/data.ts b/src/components/ctaCard/data.ts index 4596c829e..83b2bd791 100644 --- a/src/components/ctaCard/data.ts +++ b/src/components/ctaCard/data.ts @@ -14,6 +14,7 @@ const CTACards = [ imgSrc: createDaoImg, subtitle: i18n.t('cta.create.description'), title: i18n.t('cta.create.title'), + isPrimary: true, }, { actionAvailable: true, @@ -22,14 +23,16 @@ const CTACards = [ imgSrc: learnImg, subtitle: i18n.t('cta.learn.description'), title: i18n.t('cta.learn.title'), + isPrimary: false, }, { - actionAvailable: false, + actionAvailable: true, actionLabel: i18n.t('cta.build.actionLabel'), - path: '', + path: i18n.t('explore.build.linkURL'), imgSrc: buildFaster, subtitle: i18n.t('cta.build.description'), title: i18n.t('cta.build.title'), + isPrimary: false, }, ]; diff --git a/src/components/ctaCard/index.tsx b/src/components/ctaCard/index.tsx index 0724c4899..ba7559ffa 100644 --- a/src/components/ctaCard/index.tsx +++ b/src/components/ctaCard/index.tsx @@ -13,6 +13,7 @@ type Props = { onClick: (path: string) => void; subtitle: string; title: string; + isPrimary: boolean; }; const CTACard: React.FC = props => { @@ -27,10 +28,11 @@ const CTACard: React.FC = props => { + {filters.quickFilter !== 'following' && ( + { + setActiveDropdown(e); + }} + customTrigger={ + - {filters.quickFilter !== 'following' && ( - { - setActiveDropdown(e); - }} - customTrigger={ - - )} - - {t('explore.pagination.label.amountOf DAOs', { - amount: totalDaosShown, - total: totalDaos, - })} - - - )} + {totalDaos != null && + totalDaos > 0 && + totalDaosShown > 0 && + filters.quickFilter !== 'featuredDaos' && ( +
+ {hasNextPage && ( + + )} + + {t('explore.pagination.label.amountOf DAOs', { + amount: totalDaosShown, + total: totalDaos, + })} + +
+ )} = ({onClose}) => { iconLeft={IconType.CLOSE} variant="tertiary" size="sm" - responsiveSize={{lg: 'lg'}} + responsiveSize={{lg: 'md'}} onClick={onClose} /> @@ -92,11 +87,10 @@ const Header: React.FC = ({onClose}) => { type ContentProps = Pick; const ModalContent: React.FC = ({ - filters: {networks, quickFilter, pluginNames, showTestnets}, + filters: {networks, pluginNames, showTestnets}, onFilterChange, }) => { const {t} = useTranslation(); - const {isConnected} = useWallet(); const testnetsFilters = networkFilters.flatMap(f => f.testnet ? f.value : [] @@ -109,14 +103,6 @@ const ModalContent: React.FC = ({ /************************************************* * Callbacks and Handlers * *************************************************/ - const toggleQuickFilters = (value?: string | string[]) => { - if (value && !Array.isArray(value)) { - onFilterChange({ - type: FilterActionTypes.SET_QUICK_FILTER, - payload: value as QuickFilterValue, - }); - } - }; const toggleNetworks = (value?: string[]) => { onFilterChange({ @@ -152,29 +138,6 @@ const ModalContent: React.FC = ({ *************************************************/ return (
- {/* Quick Filters */} - - - {quickFilters.map(f => { - return ( - - ); - })} - - - {/* Blockchain Filters */} diff --git a/src/containers/daoOverview/index.tsx b/src/containers/daoOverview/index.tsx index b90ca528d..6326c75cc 100644 --- a/src/containers/daoOverview/index.tsx +++ b/src/containers/daoOverview/index.tsx @@ -2,7 +2,6 @@ import {Breadcrumb} from '@aragon/ods-old'; import React from 'react'; import {useTranslation} from 'react-i18next'; import styled from 'styled-components'; - import CardWithImage from 'components/cardWithImage'; import {useFormStep} from 'components/fullScreenStepper'; import {ActiveIndicator, Indicator, StyledCarousel} from 'containers/carousel'; diff --git a/src/containers/explorerCta/index.tsx b/src/containers/explorerCta/index.tsx new file mode 100644 index 000000000..c6a2c47db --- /dev/null +++ b/src/containers/explorerCta/index.tsx @@ -0,0 +1,75 @@ +import React, {useMemo, useCallback} from 'react'; +import styled from 'styled-components'; +import {useNavigate} from 'react-router-dom'; +import CTACard from 'components/ctaCard'; +import {CTACards} from 'components/ctaCard/data'; +import {useWallet} from 'hooks/useWallet'; +import {trackEvent} from 'services/analytics'; + +const ExplorerCTA: React.FC = () => { + const navigate = useNavigate(); + const {methods, isConnected} = useWallet(); + + // TODO + // this prevents the user from entering the creation + // flow without a wallet, but this should be updated + // when the rest of CTAs are enabled + const handleCTAClick = useCallback( + (path: string) => { + if (path === '/create') { + trackEvent('landing_createDaoBtn_clicked'); + } + + if (path.startsWith('http')) { + window.open(path, '_blank'); + return; + } + + if (isConnected) { + navigate(path); + return; + } + + methods + .selectWallet() + .then(() => { + navigate(path); + }) + .catch((err: Error) => { + // To be implemented: maybe add an error message when + // the error is different from closing the window + console.error(err); + }); + }, + [isConnected, methods, navigate] + ); + + const ctaList = useMemo( + () => + CTACards.map(card => ( + + )), + [handleCTAClick] + ); + + return {ctaList}; +}; + +const CTAContainer = styled.div.attrs({ + className: 'relative flex lg:flex-row flex-col lg:space-x-6 max-w-fit', +})``; + +export const ActiveIndicator = styled.li.attrs({ + className: 'inline-block bg-primary-500 h-1.5 w-12 ml-2 rounded-xl', +})``; + +export const Indicator = styled.li.attrs({ + className: 'inline-block bg-neutral-200 h-1.5 w-4 ml-2 rounded-xl', +})``; + +export default ExplorerCTA; diff --git a/src/containers/hero/index.tsx b/src/containers/hero/index.tsx index 488690119..bb2935fa7 100644 --- a/src/containers/hero/index.tsx +++ b/src/containers/hero/index.tsx @@ -1,90 +1,54 @@ import React from 'react'; import styled from 'styled-components'; -import Logo from 'assets/images/coloredLogo.svg'; -import Green from 'assets/images/circleGreenGradient.svg'; -import Purple from 'assets/images/purpleGradient.svg'; +import Blueprint from 'assets/images/blueprintTexture.svg'; import {useTranslation} from 'react-i18next'; import {GridLayout} from 'components/layout'; function Hero() { const {t} = useTranslation(); + return ( + {t('explore.hero.title')} {t('explore.hero.subtitle1')} - - - - - - - - - ); } -// NOTE: "h-[448px] -mt-20 pt-20" is the "simplest" way to achieve a sticky header -// with a gradient AND a primary 400 background. What it does it is extends the -// hero by a height of 12, moves it up using the negative margin and compensates -// by lowering the content using the padding-top. Same with factor 12 on -// desktop. const Container = styled.div.attrs({ className: - 'bg-primary-400 h-[448px] -mt-20 pt-20 xl:h-[536px] xl:pt-24 xl:-mt-24 overflow-hidden', + 'relative bg-primary-400 -mt-20 pt-20 xl:pt-24 xl:-mt-24 overflow-hidden', })``; const Wrapper = styled.div.attrs({ - className: - 'flex justify-center xl:justify-between col-span-full xl:col-start-2 xl:col-end-12 relative', + className: 'flex relative w-full col-start-1 xl:col-start-2 col-end-12', })``; const ContentWrapper = styled.div.attrs({ - className: 'xl:space-y-1.5 space-y-2 max-w-lg pt-9 xl:pt-20', + className: 'flex flex-col space-y-4 py-16 max-w-[720px]', })``; const Title = styled.h1.attrs({ - className: - 'text-neutral-0 font-semibold ft-text-5xl xl:text-left text-center xl:leading-[60px] leading-[38px]', + className: 'text-neutral-0 ft-text-5xl', })` - font-family: Syne; - letter-spacing: -0.03em; + font-family: Sora; + letter-spacing: -2.4%; `; const Subtitle = styled.h3.attrs({ className: - 'text-neutral-0 ft-text-lg font-normal text-center xl:text-left leading-[24px] xl:leading-[30px]', -})``; - -const ImageWrapper = styled.div.attrs({ - className: 'h-full', + 'text-neutral-0 ft-text-lg font-normal leading-[24px] xl:leading-[30px]', })``; const StyledImage = styled.img.attrs({ - className: 'w-[568px] hidden xl:block', -})``; - -const GradientContainer = styled.div.attrs({ - className: 'absolute top-64 xl:top-40 right-0 w-[568px]', -})``; - -const GradientWrapper = styled.div.attrs({ - className: 'relative w-full h-full', -})``; - -const GradientGreen = styled.img.attrs({ - className: 'h-80 absolute xl:-left-28 xl:-top-40 -top-[152px] left-28', -})``; - -const GradientPurple = styled.img.attrs({ - className: 'xl:h-80 h-60 absolute xl:-right-40 xl:top-10 -right-10 -top-12', + className: 'absolute top-0 left-0 w-full h-full object-cover', })``; export default Hero; diff --git a/src/containers/navbar/exploreNav.tsx b/src/containers/navbar/exploreNav.tsx index e0072125d..3eb0f67cf 100644 --- a/src/containers/navbar/exploreNav.tsx +++ b/src/containers/navbar/exploreNav.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useEffect, useState} from 'react'; import styled from 'styled-components'; import {ButtonWallet, useScreen} from '@aragon/ods-old'; import {Button, IconType} from '@aragon/ods'; @@ -9,8 +9,10 @@ import Logo from 'assets/images/logo.svg'; import {useGlobalModalContext} from 'context/globalModals'; import {Container, GridLayout} from 'components/layout'; import {FEEDBACK_FORM} from 'utils/constants'; +import classNames from 'classnames'; const ExploreNav: React.FC = () => { + const [isScrolled, setIsScrolled] = useState(false); const {t} = useTranslation(); const {address, ensName, ensAvatarUrl, isConnected, methods} = useWallet(); const {open} = useGlobalModalContext(); @@ -29,15 +31,37 @@ const ExploreNav: React.FC = () => { } methods.selectWallet().catch((err: Error) => { - // To be implemented: maybe add an error message when - // the error is different from closing the window console.error(err); }); }; + useEffect(() => { + const handleScroll = () => { + const threshold = 250; + if (window.scrollY > threshold) { + setIsScrolled(true); + } else { + setIsScrolled(false); + } + }; + + window.addEventListener('scroll', handleScroll); + + handleScroll(); + + return () => { + window.removeEventListener('scroll', handleScroll); + }; + }, []); + + const menuClassNames = classNames('py-4 xl:py-6', { + 'bg-gradient-to-b from-primary-400 to-transparent': !isScrolled, + 'bg-primary-400': isScrolled, + }); + return ( - + + ); }; -const Menu = styled.nav.attrs({ - className: 'py-4 xl:py-6', -})` - background: linear-gradient(180deg, #3164fa 0%, rgba(49, 100, 250, 0) 100%); -`; - const LeftContent = styled.div.attrs({ className: 'col-span-3 md:col-span-2 flex items-center', })``; diff --git a/src/hooks/useFeaturedDaos.ts b/src/hooks/useFeaturedDaos.ts new file mode 100644 index 000000000..51f0d6cc9 --- /dev/null +++ b/src/hooks/useFeaturedDaos.ts @@ -0,0 +1,20 @@ +import {useQuery} from '@tanstack/react-query'; +import {IDao} from 'services/aragon-backend/domain/dao'; + +const FEATURED_DAOS_URL = + 'https://raw.githubusercontent.com/aragon/app/refs/heads/develop/src/assets/data/featured-daos.json'; + +const fetchFeaturedDaos = async (): Promise => { + const response = await fetch(FEATURED_DAOS_URL); + + if (!response.ok) { + throw new Error('Failed to fetch featured DAOs'); + } + + const data: IDao[] = await response.json(); + return data; +}; + +export const useFeaturedDaos = () => { + return useQuery({queryKey: ['featuredDaos'], queryFn: fetchFeaturedDaos}); +}; diff --git a/src/pages/explore.tsx b/src/pages/explore.tsx index ca1a807fa..6017e99b9 100644 --- a/src/pages/explore.tsx +++ b/src/pages/explore.tsx @@ -1,9 +1,7 @@ import React, {useEffect} from 'react'; -import 'react-responsive-carousel/lib/styles/carousel.min.css'; import styled from 'styled-components'; - import {GridLayout} from 'components/layout'; -import Carousel from 'containers/carousel'; +import ExplorerCTA from 'containers/explorerCta'; import {DaoExplorer} from 'containers/daoExplorer'; import Hero from 'containers/hero'; import {useNetwork} from 'context/network'; @@ -31,8 +29,8 @@ export const Explore: React.FC = () => { - + diff --git a/src/utils/paths.ts b/src/utils/paths.ts index 97c050e6e..acb21bd92 100644 --- a/src/utils/paths.ts +++ b/src/utils/paths.ts @@ -1,6 +1,6 @@ /* TOP LEVEL PAGES ========================================================== */ export const Landing = '/'; -export const CreateDAO = '/create'; +export const CreateDAO = '/#/create'; export const NotFound = '/not-found'; /* DAO-SPECIFIC PAGES ======================================================= */