diff --git a/public/images/icon-decent.png b/public/images/icon-decent.png new file mode 100644 index 0000000000..dd2e9e4b33 Binary files /dev/null and b/public/images/icon-decent.png differ diff --git a/public/images/icon-decent.svg b/public/images/icon-decent.svg deleted file mode 100644 index 7893d24e4b..0000000000 --- a/public/images/icon-decent.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/public/images/icon-govern.svg b/public/images/icon-govern.svg deleted file mode 100644 index 2e4fb85a64..0000000000 --- a/public/images/icon-govern.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/public/images/icon-operate.svg b/public/images/icon-operate.svg deleted file mode 100644 index af25b4ae7d..0000000000 --- a/public/images/icon-operate.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/public/images/icon-structure.svg b/public/images/icon-structure.svg deleted file mode 100644 index beeada2d73..0000000000 --- a/public/images/icon-structure.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/public/images/shutter-icon-only-logo.svg b/public/images/shutter-icon-only-logo.svg index 23e44bf15e..f83b579948 100644 --- a/public/images/shutter-icon-only-logo.svg +++ b/public/images/shutter-icon-only-logo.svg @@ -1,8 +1,15 @@ - - - - - - - - + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/components/pages/AppHome/AppFooter.tsx b/src/components/pages/AppHome/AppFooter.tsx index f5fbbfeee4..e4550e56f9 100644 --- a/src/components/pages/AppHome/AppFooter.tsx +++ b/src/components/pages/AppHome/AppFooter.tsx @@ -1,18 +1,22 @@ -import { Box, BoxProps, Flex, Link, Spacer, Text } from '@chakra-ui/react'; +import { Flex, Link, Spacer, Text } from '@chakra-ui/react'; import { Trans, useTranslation } from 'react-i18next'; import { URL_DECENT } from '../../../constants/url'; import ExternalLink from '../../ui/links/ExternalLink'; import Divider from '../../ui/utils/Divider'; -export function AppFooter({ ...rest }: BoxProps) { +export function AppFooter() { const { t } = useTranslation('home'); return ( - - + - + ); } diff --git a/src/components/pages/AppHome/CTABox.tsx b/src/components/pages/AppHome/CTABox.tsx index ffc98f5849..9602b13495 100644 --- a/src/components/pages/AppHome/CTABox.tsx +++ b/src/components/pages/AppHome/CTABox.tsx @@ -1,29 +1,61 @@ -import { BoxProps, Center, Flex } from '@chakra-ui/react'; +import { Box, Flex, Text } from '@chakra-ui/react'; import { ReactNode } from 'react'; -import { StyledBox } from '../../ui/containers/StyledBox'; +import { useTranslation } from 'react-i18next'; +import { Link } from 'react-router-dom'; -interface Props extends BoxProps { - leftSlot: ReactNode; - rightSlot: ReactNode; -} - -export function CTABox({ leftSlot, rightSlot, ...rest }: Props) { +export default function CTABox({ + Icon, + titleKey, + descKey, + titleColor = 'white-0', + descColor = 'neutral-7', + bg = 'neutral-3', + to, + target, + pr, + iconContainerJustify, +}: { + Icon: ReactNode; + titleKey: string; + descKey: string; + titleColor?: string; + descColor?: string; + bg?: string; + to: string; + target?: string; + pr?: string | number; + iconContainerJustify?: string; +}) { + const { t } = useTranslation('home'); return ( - -
- + - {leftSlot} - {rightSlot} - -
-
+ {t(titleKey)} + + {t(descKey)} + + + {Icon} + + ); } diff --git a/src/components/pages/AppHome/FeaturedDAOCard.tsx b/src/components/pages/AppHome/FeaturedDAOCard.tsx index 88fb5ca3ed..1562d573e5 100644 --- a/src/components/pages/AppHome/FeaturedDAOCard.tsx +++ b/src/components/pages/AppHome/FeaturedDAOCard.tsx @@ -1,59 +1,77 @@ -import { Text, BoxProps, Image, HStack, Spacer, Flex, Box, Link } from '@chakra-ui/react'; +import { Text, VStack, Flex, Image } from '@chakra-ui/react'; import { useTranslation } from 'react-i18next'; -import { Link as RouterLink } from 'react-router-dom'; import { DAO_ROUTES } from '../../../constants/routes'; +import { Badge } from '../../ui/badges/Badge'; import { StyledBox } from '../../ui/containers/StyledBox'; -interface DAOFeatureProps extends BoxProps { + +export interface FeaturedDAO { iconSrc: string; - title: string; - desc: string; + iconBg?: string; + iconRounded?: boolean; + titleKey: string; network: string; + networkName: string; + votingStrategy: string; address: string; } +interface FeaturedDAOCardProps extends FeaturedDAO {} + export default function FeaturedDAOCard({ iconSrc, - title, - desc, + iconBg = 'lilac-0', + iconRounded = false, + titleKey, network, address, - ...rest -}: DAOFeatureProps) { + networkName, + votingStrategy, +}: FeaturedDAOCardProps) { const { t } = useTranslation('home'); return ( - - + - - - {title} - {title} - - {desc} - - - - + {t(titleKey)} + + {t(titleKey)} + + + {networkName} + + - {t('featureLink')} - + {votingStrategy} + - - + + ); } diff --git a/src/components/pages/AppHome/ValueProposition.tsx b/src/components/pages/AppHome/ValueProposition.tsx deleted file mode 100644 index 49573a6c86..0000000000 --- a/src/components/pages/AppHome/ValueProposition.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { Text, Image, Flex, FlexProps, VStack } from '@chakra-ui/react'; - -interface DAOActionProps extends FlexProps { - iconSrc: string; - title: string; - desc: string; -} - -export default function ValueProposition({ iconSrc, title, desc, ...rest }: DAOActionProps) { - return ( - - {title} - - - {title} - - {desc} - - - ); -} diff --git a/src/components/pages/DaoDashboard/Info/ParentLink.tsx b/src/components/pages/DaoDashboard/Info/ParentLink.tsx index 860195c7d3..085b0ba0c9 100644 --- a/src/components/pages/DaoDashboard/Info/ParentLink.tsx +++ b/src/components/pages/DaoDashboard/Info/ParentLink.tsx @@ -1,4 +1,4 @@ -import { Link, HStack, Image, Text, Icon } from '@chakra-ui/react'; +import { Link, HStack, Text, Icon } from '@chakra-ui/react'; import { ArrowBendLeftUp } from '@phosphor-icons/react'; import { useTranslation } from 'react-i18next'; import { Link as RouterLink } from 'react-router-dom'; diff --git a/src/components/pages/DaoSettings/components/SettingsSection.tsx b/src/components/pages/DaoSettings/components/SettingsSection.tsx index 49be59d630..9c4fbb8109 100644 --- a/src/components/pages/DaoSettings/components/SettingsSection.tsx +++ b/src/components/pages/DaoSettings/components/SettingsSection.tsx @@ -29,7 +29,6 @@ export function SettingsSection({ {/* SETTINGS SECTION CONTENT */} = { [FractalProposalState.ACTIVE]: { tooltipKey: 'stateActiveTip', bg: 'lilac-0', @@ -99,19 +98,21 @@ const BADGE_MAPPING: BadgeType = { }, }; -type BadgeSize = { [key: string]: { minWidth: string; height: string } }; -const BADGE_SIZES: BadgeSize = { +type Size = 'sm' | 'base'; +type BadgeSize = { minWidth: string; height: string }; +const BADGE_SIZES: Record = { sm: { minWidth: '5rem', height: '1.375rem' }, base: { minWidth: '5.4375rem', height: '1.375rem' }, }; interface IBadge { - size: 'sm' | 'base'; - labelKey: FractalProposalState | DAOState | string; + size: Size; + labelKey: keyof typeof BADGE_MAPPING; + children?: ReactNode; proposal?: FractalProposal; } -export function Badge({ labelKey, size, proposal }: IBadge) { +export function Badge({ labelKey, children, size, proposal }: IBadge) { const { tooltipKey, ...colors } = BADGE_MAPPING[labelKey]; const sizes = BADGE_SIZES[size]; @@ -144,7 +145,7 @@ export function Badge({ labelKey, size, proposal }: IBadge) { textStyle="label-base" lineHeight="1" > - {t(labelKey)} + {children || t(labelKey)} {proposal && ( - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export function DocsIllustration() { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/src/i18n/locales/en/home.json b/src/i18n/locales/en/home.json index 3f2cd52995..f1e8c25834 100644 --- a/src/i18n/locales/en/home.json +++ b/src/i18n/locales/en/home.json @@ -1,29 +1,16 @@ { - "homeTitle": "Welcome to Decent", - "homeDesc": "Are you outgrowing your Multisig? Decent extends Safe treasuries into on-chain hierarchies of permissions, token flows, and governance.", - "govern": "Govern", - "governDesc": "Choose a governance per sub-Safe. Create and authorize proposals. Decentralize on any timeline.", - "structure": "Structure", - "structureDesc": "Start with any Safe Multisig. Connect teams in flexible sub-Safe hierarchies for agile delivery.", - "operate": "Operate", - "operateDesc": "Unleash on-chain efficiency with reuseable, streamed, and permissioned transactions.", - "featuredTitle": "Featured Organizations", - "featuredDesc": "Here are some projects using Decent to convert their Safe Multisig into DAOs as they decentralize:", + "homeTitle": "Get Started", + "createCTA": "Create DAO", + "createDesc": "Govern your Safe.", + "docsCTA": "Learn More", + "docsDesc": "Read our docs to get started.", + "featuredTitle": "Explore DAOs", "decentTitle": "Decent DAO", - "decentDesc": "We are an open-source collective that unites builders toward global decentralization.", "awakeTitle": "AwakeVC", - "awakeDesc": "Awake Internet Protocols combine AI and FinTech to empower Decentralized Private Equity for the multiverse. Welcome to Awakened Value Co-creation aka AwakeVC.", "ethlizardsTitle": "Lizard DAO", - "ethlizardsDesc": "Ethlizards brings together an exceptional mix of avid gamers, visionary builders, and savvy investors, establishing itself as a highly esteemed partner in the GameFi ecosystem.", "shutterTitle": "Shutter DAO 0x36", - "shutterDesc": "Shutter is an anti-frontrunning/malicious MEV protocol using threshold encryption. Shutter DAO 0x36 is a pragmatic, step-by-step approach towards decentralization, prioritizing community involvement and learning from each phase while maintaining operational reliability and security.", "myosinTitle": "Myosin", - "myosinDesc": "The Ultimate Marketing Network. Supercharging growth for web3 companies & onboarding brands into the future of the internet.", - "featureLink": "Explore >", - "readyCTA": "Ready to start?", - "createButton": "+ Start from Scratch", + "textMoreDAOs": "Load More", "homeAttribution": "Made with 💜 by <1>Decent DAO", - "audit": "Audit", - "learnCTA": "Explore the Docs to see how Decent works", - "getStartedButton": "Get Started" + "audit": "Audit" } diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx index 210ec21e38..b838510604 100644 --- a/src/pages/HomePage.tsx +++ b/src/pages/HomePage.tsx @@ -1,69 +1,46 @@ -import { Center, VStack, Text, Button, Flex, Box } from '@chakra-ui/react'; - -import { useEffect } from 'react'; +import { VStack, Text, Flex, Button } from '@chakra-ui/react'; +import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useNavigate } from 'react-router-dom'; import { mainnet, sepolia } from 'wagmi/chains'; import { AppFooter } from '../components/pages/AppHome/AppFooter'; -import { CTABox } from '../components/pages/AppHome/CTABox'; -import FeaturedDAOCard from '../components/pages/AppHome/FeaturedDAOCard'; -import ValueProposition from '../components/pages/AppHome/ValueProposition'; -import ExternalLink from '../components/ui/links/ExternalLink'; +import CTABox from '../components/pages/AppHome/CTABox'; +import FeaturedDAOCard, { FeaturedDAO } from '../components/pages/AppHome/FeaturedDAOCard'; +import { CreateDAOIllustration, DocsIllustration } from '../components/ui/proposal/Icons'; import { BASE_ROUTES } from '../constants/routes'; import { URL_DOCS } from '../constants/url'; import { useFractal } from '../providers/App/AppProvider'; import { useNetworkConfig } from '../providers/NetworkConfig/NetworkConfigProvider'; -const VALUE_PROPS = [ - { - iconSrc: '/images/icon-structure.svg', - titleKey: 'structure', - descKey: 'structureDesc', - }, - { - iconSrc: '/images/icon-operate.svg', - titleKey: 'operate', - descKey: 'operateDesc', - }, - { - iconSrc: '/images/icon-govern.svg', - titleKey: 'govern', - descKey: 'governDesc', - }, -]; - -interface Feature { - iconSrc: string; - titleKey: string; - descKey: string; - network: string; - address: string; -} - // featured DAOs are dependent on the connected chain -const FEATURED_DAOS = new Map([ +const FEATURED_DAOS = new Map([ [ mainnet.id, [ { - iconSrc: '/images/shutter-icon-only-logo.svg', - titleKey: 'shutterTitle', - descKey: 'shutterDesc', + iconSrc: '/images/icon-decent.png', + iconRounded: true, + titleKey: 'decentTitle', network: 'eth', - address: '0x36bD3044ab68f600f6d3e081056F34f2a58432c4', + networkName: 'Ethereum', + votingStrategy: 'Multisig', + address: '0xD26c85D435F02DaB8B220cd4D2d398f6f646e235', }, { - iconSrc: '/images/icon-decent.svg', - titleKey: 'decentTitle', - descKey: 'decentDesc', + iconSrc: '/images/shutter-icon-only-logo.svg', + iconBg: 'neutral-3', + titleKey: 'shutterTitle', network: 'eth', - address: '0xD26c85D435F02DaB8B220cd4D2d398f6f646e235', + networkName: 'Ethereum', + votingStrategy: 'ERC-20', + address: '0x36bD3044ab68f600f6d3e081056F34f2a58432c4', }, { iconSrc: '/images/icon-awakevc.svg', titleKey: 'awakeTitle', - descKey: 'awakeDesc', + iconBg: 'neutral-3', network: 'eth', + networkName: 'Ethereum', + votingStrategy: 'Multisig', address: '0xdD6CeFA62239272f1eDf755ba6471eacb7DF2Fa5', }, ], @@ -74,8 +51,9 @@ const FEATURED_DAOS = new Map([ { iconSrc: '/images/icon-myosin.svg', titleKey: 'myosinTitle', - descKey: 'myosinDesc', network: 'sep', + networkName: 'Sepolia', + votingStrategy: 'ERC-20', address: '0xdef90A94273a1A1A72B33D39129fa41E6C08Be3a', }, ], @@ -83,11 +61,8 @@ const FEATURED_DAOS = new Map([ ]); export default function HomePage() { + const [shownItemsCount, setShownItemsCount] = useState(4); const { t } = useTranslation('home'); - const navigate = useNavigate(); - const createDAO = () => { - navigate(BASE_ROUTES.create); - }; const { node: { daoAddress }, action, @@ -100,147 +75,84 @@ export default function HomePage() { }, [daoAddress, action]); const { chain } = useNetworkConfig(); - const features = FEATURED_DAOS.get(chain.id); - + const featuredDaos = FEATURED_DAOS.get(chain.id); return ( -
+ - - {t('homeTitle')} - -
- - - {t('homeDesc')} - - - -
+ {t('homeTitle')} - {VALUE_PROPS.map((daoAction, index) => { - return ( - - ); - })} + } + titleColor="cosmic-nebula-0" + descColor="cosmic-nebula-0" + bg="lilac-0" + /> + } + pr={0} + iconContainerJustify="flex-end" + /> - - - - } - rightSlot={{t('learnCTA')}} - /> - {features && features.length > 0 ? ( - <> - - {t('featuredTitle')} - - - {t('featuredDesc')} - + {featuredDaos && featuredDaos.length > 0 ? ( + + {t('featuredTitle')} - {features.map((feature, index) => { - if ( - typeof location !== 'undefined' && - location.pathname === 'app.fractalframework.xyz' - ) { - return null; - } - return ( - - ); - })} + {featuredDaos.slice(0, shownItemsCount).map(dao => ( + + ))} - - ) : ( - // if there are no features just show padding - - )} - {t('readyCTA')}} - rightSlot={ - - } - /> - + {featuredDaos.length > shownItemsCount && ( + + {/* @todo This is supposed to be themed button but it seems like this is only instance of it in the app. Either keep it as is or style properly through Chakra theming */} + + + )} + + ) : null}
-
+ +
); }