diff --git a/apps/website/public/assets/wallet/1.png b/apps/website/public/assets/wallet/1.png new file mode 100644 index 00000000..153e84b6 Binary files /dev/null and b/apps/website/public/assets/wallet/1.png differ diff --git a/apps/website/public/assets/wallet/2.png b/apps/website/public/assets/wallet/2.png new file mode 100644 index 00000000..5f9ecf0c Binary files /dev/null and b/apps/website/public/assets/wallet/2.png differ diff --git a/apps/website/public/assets/wallet/3.png b/apps/website/public/assets/wallet/3.png new file mode 100644 index 00000000..5177ebb5 Binary files /dev/null and b/apps/website/public/assets/wallet/3.png differ diff --git a/apps/website/public/assets/wallet/4.png b/apps/website/public/assets/wallet/4.png new file mode 100644 index 00000000..86232d4f Binary files /dev/null and b/apps/website/public/assets/wallet/4.png differ diff --git a/apps/website/public/assets/wallet/5.png b/apps/website/public/assets/wallet/5.png new file mode 100644 index 00000000..bcaca385 Binary files /dev/null and b/apps/website/public/assets/wallet/5.png differ diff --git a/apps/website/public/assets/wallet/6.png b/apps/website/public/assets/wallet/6.png new file mode 100644 index 00000000..2e47bbb8 Binary files /dev/null and b/apps/website/public/assets/wallet/6.png differ diff --git a/apps/website/public/assets/wallet/7.png b/apps/website/public/assets/wallet/7.png new file mode 100644 index 00000000..98580675 Binary files /dev/null and b/apps/website/public/assets/wallet/7.png differ diff --git a/apps/website/public/assets/wallet/8.png b/apps/website/public/assets/wallet/8.png new file mode 100644 index 00000000..1d2a2f45 Binary files /dev/null and b/apps/website/public/assets/wallet/8.png differ diff --git a/apps/website/public/assets/wallet/arbitrum.png b/apps/website/public/assets/wallet/arbitrum.png new file mode 100644 index 00000000..a255d7bb Binary files /dev/null and b/apps/website/public/assets/wallet/arbitrum.png differ diff --git a/apps/website/public/assets/wallet/background-pattern.png b/apps/website/public/assets/wallet/background-pattern.png new file mode 100644 index 00000000..729e7cf5 Binary files /dev/null and b/apps/website/public/assets/wallet/background-pattern.png differ diff --git a/apps/website/public/assets/wallet/border.png b/apps/website/public/assets/wallet/border.png new file mode 100644 index 00000000..160458a3 Binary files /dev/null and b/apps/website/public/assets/wallet/border.png differ diff --git a/apps/website/public/assets/wallet/cube.png b/apps/website/public/assets/wallet/cube.png new file mode 100644 index 00000000..756afbdf Binary files /dev/null and b/apps/website/public/assets/wallet/cube.png differ diff --git a/apps/website/public/assets/wallet/duck.png b/apps/website/public/assets/wallet/duck.png new file mode 100644 index 00000000..5136af82 Binary files /dev/null and b/apps/website/public/assets/wallet/duck.png differ diff --git a/apps/website/public/assets/wallet/ethereum.png b/apps/website/public/assets/wallet/ethereum.png new file mode 100644 index 00000000..8c5703dd Binary files /dev/null and b/apps/website/public/assets/wallet/ethereum.png differ diff --git a/apps/website/public/assets/wallet/gentleman.png b/apps/website/public/assets/wallet/gentleman.png new file mode 100644 index 00000000..6ea5b3fc Binary files /dev/null and b/apps/website/public/assets/wallet/gentleman.png differ diff --git a/apps/website/public/assets/wallet/hands.png b/apps/website/public/assets/wallet/hands.png new file mode 100644 index 00000000..d1da4ba6 Binary files /dev/null and b/apps/website/public/assets/wallet/hands.png differ diff --git a/apps/website/public/assets/wallet/megaphone.png b/apps/website/public/assets/wallet/megaphone.png new file mode 100644 index 00000000..68e3af90 Binary files /dev/null and b/apps/website/public/assets/wallet/megaphone.png differ diff --git a/apps/website/public/assets/wallet/nft.png b/apps/website/public/assets/wallet/nft.png new file mode 100644 index 00000000..1f2247f9 Binary files /dev/null and b/apps/website/public/assets/wallet/nft.png differ diff --git a/apps/website/public/assets/wallet/optimism.png b/apps/website/public/assets/wallet/optimism.png new file mode 100644 index 00000000..ff2ae2d8 Binary files /dev/null and b/apps/website/public/assets/wallet/optimism.png differ diff --git a/apps/website/public/assets/wallet/pizza.png b/apps/website/public/assets/wallet/pizza.png new file mode 100644 index 00000000..3fc25108 Binary files /dev/null and b/apps/website/public/assets/wallet/pizza.png differ diff --git a/apps/website/public/assets/wallet/skull.png b/apps/website/public/assets/wallet/skull.png new file mode 100644 index 00000000..7df64018 Binary files /dev/null and b/apps/website/public/assets/wallet/skull.png differ diff --git a/apps/website/public/assets/wallet/texture.png b/apps/website/public/assets/wallet/texture.png new file mode 100644 index 00000000..26e70ff0 Binary files /dev/null and b/apps/website/public/assets/wallet/texture.png differ diff --git a/apps/website/public/assets/wallet/vegas.png b/apps/website/public/assets/wallet/vegas.png new file mode 100644 index 00000000..92fb9e11 Binary files /dev/null and b/apps/website/public/assets/wallet/vegas.png differ diff --git a/apps/website/public/assets/wallet/vitalik.mp4 b/apps/website/public/assets/wallet/vitalik.mp4 new file mode 100644 index 00000000..1b23224f Binary files /dev/null and b/apps/website/public/assets/wallet/vitalik.mp4 differ diff --git a/apps/website/public/assets/wallet/vitalik.webm b/apps/website/public/assets/wallet/vitalik.webm new file mode 100644 index 00000000..57100a12 Binary files /dev/null and b/apps/website/public/assets/wallet/vitalik.webm differ diff --git a/apps/website/src/components/cards/border.tsx b/apps/website/src/components/cards/border.tsx new file mode 100644 index 00000000..00fc49f4 --- /dev/null +++ b/apps/website/src/components/cards/border.tsx @@ -0,0 +1,17 @@ +export const Border = () => { + return ( + + + + ) +} diff --git a/apps/website/src/components/cards/grid-hero.tsx b/apps/website/src/components/cards/grid-hero.tsx new file mode 100644 index 00000000..2b3dda33 --- /dev/null +++ b/apps/website/src/components/cards/grid-hero.tsx @@ -0,0 +1,161 @@ +import { cva } from 'class-variance-authority' +import Image from 'next/image' + +import type { StaticImageData } from 'next/image' + +// Variants for the grid hero class names +const biggerCardClassNames = cva( + [ + 'min-w-[350px] rounded-[40px]', + 'px-[22px] py-6 sm:min-w-0 sm:px-[35px] sm:py-[48px] lg:px-5 xl:px-[34px] xl:py-[68px] 2xl:px-[73px]', + ], + { + variants: { + color: { + yellow: ['bg-customisation-yellow/10'], + turquoise: ['bg-customisation-turquoise/10'], + purple: ['bg-customisation-purple/10'], + }, + }, + } +) + +const imagesWithBorders = cva(['border-4', 'rounded-3xl'], { + variants: { + color: { + yellow: ['border-customisation-yellow/5'], + turquoise: ['border-customisation-turquoise/5'], + purple: ['border-customisation-purple/5'], + }, + }, +}) + +const imagesWithBordersTopOrBottom = cva(['border-4', 'rounded-3xl'], { + variants: { + color: { + yellow: ['border-customisation-yellow/5'], + turquoise: ['border-customisation-turquoise/5'], + purple: ['border-customisation-purple/5'], + }, + alignment: { + top: ['border-t-0'], + bottom: ['border-b-0'], + }, + }, +}) + +const thirdCardClassNames = cva( + [ + 'flex min-w-[calc(50%-10px)] rounded-[40px]', + 'px-[22px] sm:min-w-0 sm:px-[35px] lg:px-5 xl:px-[34px] 2xl:px-[73px]', + ], + { + variants: { + color: { + yellow: ['bg-customisation-yellow/10'], + turquoise: ['bg-customisation-turquoise/10'], + purple: ['bg-customisation-purple/10'], + }, + alignment: { + top: [ + 'pt-0', + 'pb-6 sm:pb-[48px] xl:pb-[68px]', + 'items-start', + 'justify-start', + ], + bottom: [ + 'pb-0', + 'pt-6 sm:pt-[48px] xl:pt-[68px]', + 'items-end', + 'justify-end', + ], + }, + }, + } +) + +const fourthCardClassNames = cva( + [ + 'flex min-w-[calc(50%-10px)] rounded-[40px]', + 'grow items-center justify-center px-0 sm:px-5 md:px-10 lg:px-5 2xl:px-10', + ], + { + variants: { + color: { + yellow: ['bg-customisation-yellow/10'], + turquoise: ['bg-customisation-turquoise/10'], + purple: ['bg-customisation-purple/10'], + }, + }, + } +) + +type Props = { + color: 'yellow' | 'turquoise' | 'purple' + cardOne: { + image: StaticImageData + alt: string + } + cardTwo: { + image: StaticImageData + alt: string + } + cardThree: { + image: StaticImageData + alt: string + alignment?: 'top' | 'bottom' + } + cardFour: { + image: StaticImageData + alt: string + } +} + +const GridHero = (props: Props) => { + const { color, cardOne, cardTwo, cardThree, cardFour } = props + + return ( +
+
+
+
+ {cardOne.alt} +
+
+ {cardTwo.alt} +
+
+
+
+ {cardThree.alt} +
+
+ {cardFour.alt} +
+
+
+
+ ) +} + +export { GridHero } diff --git a/apps/website/src/components/cards/index.ts b/apps/website/src/components/cards/index.ts new file mode 100644 index 00000000..e99e87f0 --- /dev/null +++ b/apps/website/src/components/cards/index.ts @@ -0,0 +1,2 @@ +export { GridHero } from './grid-hero' +export { Section } from './section' diff --git a/apps/website/src/components/cards/section.tsx b/apps/website/src/components/cards/section.tsx new file mode 100644 index 00000000..bad785f5 --- /dev/null +++ b/apps/website/src/components/cards/section.tsx @@ -0,0 +1,149 @@ +import { Text } from '@status-im/components' +import { PopupIcon } from '@status-im/icons' +import { cva } from 'class-variance-authority' +import Image from 'next/image' + +import { Border } from './border' + +import type { StaticImageData } from 'next/image' + +type Props = { + direction?: 'ltr' | 'rtl' + title: string + description: string + image: StaticImageData + imageAlt: string + imageSecondary: StaticImageData + imageSecondaryAlt: string + secondaryDescription: string + secondaryTitle: string + customNode?: React.ReactNode + color: 'yellow' | 'turquoise' | 'purple' + information?: string +} + +const containerClassNames = cva( + [ + 'relative flex w-full justify-center', + 'overflow-hidden', + 'max-h-[854px]', + 'max-w-[582px]', + 'rounded-[32px]', + 'py-[65px]', + ], + { + variants: { + color: { + yellow: ['bg-customisation-yellow/10'], + turquoise: ['bg-customisation-turquoise/10'], + purple: ['bg-customisation-purple/10'], + }, + }, + } +) + +const imageClassNames = cva( + ['rounded-3xl', 'border-4', 'h-auto max-h-[724px] w-auto'], + { + variants: { + color: { + yellow: ['border-customisation-yellow/5'], + turquoise: ['border-customisation-turquoise/5'], + purple: ['border-customisation-purple/5'], + }, + }, + } +) + +const borderContainerClassNames = cva( + ['absolute left-0 top-0', 'w-full', 'h-[100%]'], + { + variants: { + color: { + yellow: ['text-customisation-yellow/5'], + turquoise: ['text-customisation-turquoise/5'], + purple: ['text-customisation-purple/5'], + }, + }, + } +) + +const Section = (props: Props) => { + const { + title, + color, + description, + image, + imageAlt, + imageSecondary, + imageSecondaryAlt, + secondaryDescription, + secondaryTitle, + direction = 'ltr', + } = props + + const directionOrder = direction === 'ltr' ? 'order-0' : 'order-1' + + return ( +
+
+
+
+
+ +
+
+ {imageAlt} +
+
+
+
+ {imageSecondaryAlt} + +
+ + {title} + +
+ {description} +
+
+ +
+ + {secondaryTitle} + +
+ + {secondaryDescription} + {props.information && ( + + + + )} + +
+ + {props.customNode && ( +
{props.customNode}
+ )} +
+
+
+
+
+ ) +} + +export { Section } diff --git a/apps/website/src/components/coming-soon.tsx b/apps/website/src/components/coming-soon.tsx new file mode 100644 index 00000000..5cb13822 --- /dev/null +++ b/apps/website/src/components/coming-soon.tsx @@ -0,0 +1,12 @@ +export const ComingSoon = () => { + return ( + + + + ) +} diff --git a/apps/website/src/components/datepicker/datepicker.tsx b/apps/website/src/components/datepicker/datepicker.tsx index c2a0d54f..fe89e51c 100644 --- a/apps/website/src/components/datepicker/datepicker.tsx +++ b/apps/website/src/components/datepicker/datepicker.tsx @@ -17,8 +17,8 @@ const DatePicker = (props: Props) => { return (
- diff --git a/apps/website/src/components/error-page.tsx b/apps/website/src/components/error-page.tsx index f2ca376f..dabec07a 100644 --- a/apps/website/src/components/error-page.tsx +++ b/apps/website/src/components/error-page.tsx @@ -13,7 +13,7 @@ export const ErrorPage = (props: Props) => { // todo!: design review, not in designs case ERROR_CODES.NOT_FOUND: return ( -
+
Page not found. @@ -24,7 +24,7 @@ export const ErrorPage = (props: Props) => { case ERROR_CODES.INTERNAL_SERVER_ERROR: default: return ( -
+
diff --git a/apps/website/src/components/footer/action-card.tsx b/apps/website/src/components/footer/action-card.tsx new file mode 100644 index 00000000..2d1c939a --- /dev/null +++ b/apps/website/src/components/footer/action-card.tsx @@ -0,0 +1,29 @@ +import { Button, Text } from '@status-im/components' + +type Props = { + title: string + description: string + action: string +} + +const ActionCard = (props: Props) => { + const { title, description, action } = props + + return ( +
+
+ + {title} + + + {description} + +
+ +
+ ) +} + +export { ActionCard } diff --git a/apps/website/src/components/footer/components/dot.tsx b/apps/website/src/components/footer/components/dot.tsx new file mode 100644 index 00000000..99da4e63 --- /dev/null +++ b/apps/website/src/components/footer/components/dot.tsx @@ -0,0 +1,13 @@ +export const Dot = () => ( + + + + + +) diff --git a/apps/website/src/components/footer/components/messari-icon.tsx b/apps/website/src/components/footer/components/messari-icon.tsx new file mode 100644 index 00000000..10d768ce --- /dev/null +++ b/apps/website/src/components/footer/components/messari-icon.tsx @@ -0,0 +1,31 @@ +export const MessariIcon = () => { + return ( + + + + + + + + + + + + + ) +} diff --git a/apps/website/src/components/footer/footer-mobile.tsx b/apps/website/src/components/footer/footer-mobile.tsx new file mode 100644 index 00000000..4619758c --- /dev/null +++ b/apps/website/src/components/footer/footer-mobile.tsx @@ -0,0 +1,77 @@ +import { Text } from '@status-im/components' + +import { SOCIALS } from '@/config/links' + +import { Logo } from '../logo' +import { AccordionMenu } from '../navigation/accordion-menu' +import { Dot } from './components/dot' +import { MessariIcon } from './components/messari-icon' + +type Props = { + hasBorderTop?: boolean +} + +export const FooterMobile = (props: Props) => { + const { hasBorderTop } = props + + return ( +
+
+
+
+ +
+
+ +
+
+ +
+
+ + © Status Research & Development GmbH + + +
+ + Terms of use + + + + Privacy policy + + + + Cookies + +
+
+
+
+ + + Messari Transparency Verified + +
+
+ {Object.values(SOCIALS).map(social => { + const IconComponent = social.icon + return ( + + ) + })} +
+
+
+
+
+ ) +} diff --git a/apps/website/src/components/footer/footer.tsx b/apps/website/src/components/footer/footer.tsx new file mode 100644 index 00000000..e71bce08 --- /dev/null +++ b/apps/website/src/components/footer/footer.tsx @@ -0,0 +1,94 @@ +import { Text } from '@status-im/components' +import { cva } from 'class-variance-authority' + +import { LINKS, SOCIALS } from '@/config/links' + +import { Logo } from '../logo' +import { Dot } from './components/dot' +import { MessariIcon } from './components/messari-icon' +import { Section } from './section' + +type Props = { + hasBorderTop?: boolean +} + +const section = cva( + [ + 'border-neutral-80', + 'mb-6', + 'flex', + 'items-start', + 'border-dashed', + 'pl-6', + 'pt-6', + ], + { + variants: { + hasBorderTop: { + true: ['border-t'], + false: ['border-t-0'], + }, + }, + } +) + +export const Footer = (props: Props) => { + const { hasBorderTop } = props + + return ( +
+
+
+ +
+ {Object.entries(LINKS).map(([title, links], index) => ( +
+ ))} +
+
+
+ + © Status Research & Development GmbH + + +
+ + Terms of use + + + Privacy policy + + + Cookies + +
+
+
+
+ + + Messari Transparency Verified + + +
+ {Object.values(SOCIALS).map(social => { + const IconComponent = social.icon + return ( + + ) + })} +
+
+
+ ) +} diff --git a/apps/website/src/components/footer/section.tsx b/apps/website/src/components/footer/section.tsx new file mode 100644 index 00000000..403aa38f --- /dev/null +++ b/apps/website/src/components/footer/section.tsx @@ -0,0 +1,79 @@ +import { Text } from '@status-im/components' +import { cva } from 'class-variance-authority' + +import { Link } from '../link' + +import type { Links } from '@/config/links' + +type Props = { + title: string + links: Links + hasBorderLeft?: boolean + hasBorderTop?: boolean +} + +const section = cva( + [ + 'border-neutral-80', + 'relative', + 'grid', + 'gap-3', + 'border-dashed', + 'px-5', + 'pb-6', + 'pt-6', + 'lg:border-l', + 'lg:pb-0', + ], + { + variants: { + hasBorderTop: { + true: ['border-t'], + false: ['border-t-0'], + }, + hasBorderLeft: { + true: ['border-l'], + false: ['border-l-0'], + }, + }, + } +) + +const Section = (props: Props) => { + const { title, links, hasBorderLeft, hasBorderTop } = props + + return ( +
+
+
+ + {title} + +
    + {links.map(link => ( +
  • + + + {link.name} + + +
  • + ))} +
+
+
+ ) +} + +export { Section } diff --git a/apps/website/src/components/logo.tsx b/apps/website/src/components/logo.tsx index b60c4839..10cd64af 100644 --- a/apps/website/src/components/logo.tsx +++ b/apps/website/src/components/logo.tsx @@ -8,10 +8,11 @@ import logoLearnSrc from '../../public/images/logo/learn.svg' type Props = { label?: boolean + isTopbarDesktop?: boolean } export const Logo = (props: Props) => { - const { label = true } = props + const { label = true, isTopbarDesktop } = props const { pathname } = useRouter() @@ -39,7 +40,7 @@ export const Logo = (props: Props) => { width="70" height="16" fill="none" - className="mr-[10px]" + className={`mr-[10px] ${isTopbarDesktop ? 'hidden lg:block' : ''}`} > { + const [openLink, setOpenLink] = useState('') + + const handleToggle = (value: string) => { + setOpenLink(value === openLink ? '' : value) + } + + return ( +
+ {Object.entries(LINKS).map(([name, links]) => ( + + +
+ +
+ +
+ + {name} + +
+ +
+ {links.map((link, index) => { + const external = link.href.startsWith('http') + return ( +
+ + + {link.name} + + + {external && ( + + )} + +
+ ) + })} +
+
+
+
+
+ ))} +
+ ) +} + +export { AccordionMenu } diff --git a/apps/website/src/components/nav-menu.tsx b/apps/website/src/components/navigation/floating-desktop.tsx similarity index 73% rename from apps/website/src/components/nav-menu.tsx rename to apps/website/src/components/navigation/floating-desktop.tsx index 22fdc0f8..ba3a7aa0 100644 --- a/apps/website/src/components/nav-menu.tsx +++ b/apps/website/src/components/navigation/floating-desktop.tsx @@ -1,5 +1,3 @@ -import { useEffect, useRef, useState } from 'react' - import * as NavigationMenu from '@radix-ui/react-navigation-menu' import { Button, Text } from '@status-im/components' import { DownloadIcon, ExternalIcon } from '@status-im/icons' @@ -7,39 +5,22 @@ import { cx } from 'class-variance-authority' import { LINKS } from '@/config/links' -import { Link } from './link' -import { Logo } from './logo' +import { Link } from '../link' +import { Logo } from '../logo' -export const NavMenu = () => { - const [visible, setVisible] = useState(false) +type Props = { + visible: boolean +} - // Using ref to prevent re-running of useEffect - const visibleRef = useRef(visible) - visibleRef.current = visible - useEffect(() => { - const handleScroll = () => { - if (window.scrollY > 60) { - visibleRef.current === false && setVisible(true) - } else { - visibleRef.current === true && setVisible(false) - } - } - - handleScroll() - - window.addEventListener('scroll', handleScroll, { passive: true }) - return () => { - window.removeEventListener('scroll', handleScroll) - } - }, []) +const FloatingDesktop = (props: Props) => { + const { visible } = props return ( @@ -98,3 +79,5 @@ export const NavMenu = () => { ) } + +export { FloatingDesktop } diff --git a/apps/website/src/components/navigation/floating-menu.tsx b/apps/website/src/components/navigation/floating-menu.tsx new file mode 100644 index 00000000..dea7c091 --- /dev/null +++ b/apps/website/src/components/navigation/floating-menu.tsx @@ -0,0 +1,82 @@ +import { useRef, useState } from 'react' + +import { animated, useScroll } from '@react-spring/web' +import { cx } from 'class-variance-authority' + +import { useLockScroll } from '@/hooks/use-lock-scroll' +import { useOutsideClick } from '@/hooks/use-outside-click' + +import { FloatingDesktop } from './floating-desktop' +import { FloatingMobile } from './floating-mobile' + +const FloatingMenu = (): JSX.Element => { + const [visible, setVisible] = useState(false) + const [open, setOpen] = useState(false) + const openRef = useRef(open) + openRef.current = open + + // Using ref to prevent re-running of useEffect + const visibleRef = useRef(visible) + const scrollYRef = useRef(0) + visibleRef.current = visible + + // Close menu on outside click + const ref = useOutsideClick(() => setOpen(false)) + useLockScroll(open) + + useScroll({ + onChange: ({ value: { scrollYProgress } }) => { + const isMenuOpen = openRef.current + const isScrollingUp = scrollYProgress < scrollYRef.current + const detectionPoint = scrollYProgress > 0.005 + + if (detectionPoint && isScrollingUp) { + if (!visibleRef.current) { + setVisible(true) + } + } else { + if (!isMenuOpen) { + setVisible(false) + } + } + scrollYRef.current = scrollYProgress + }, + default: { + immediate: true, + }, + }) + + return ( + <> + + + + + + + + ) +} + +export { FloatingMenu } diff --git a/apps/website/src/components/navigation/floating-mobile.tsx b/apps/website/src/components/navigation/floating-mobile.tsx new file mode 100644 index 00000000..ac861943 --- /dev/null +++ b/apps/website/src/components/navigation/floating-mobile.tsx @@ -0,0 +1,61 @@ +import { Button, IconButton } from '@status-im/components' +import { CloseIcon, DownloadIcon, MenuIcon } from '@status-im/icons' + +import { Link } from '../link' +import { Logo } from '../logo' +import { AccordionMenu } from './accordion-menu' + +type Props = { + open: boolean + setOpen: (open: boolean) => void +} + +const FloatingMobile = (props: Props) => { + const { open, setOpen } = props + return ( +
+
+
+ + + +
+ + + ) : ( + + ) + } + onPress={() => setOpen(!open)} + /> +
+
+ +
+ +
+
+
+ ) +} + +export { FloatingMobile } diff --git a/apps/website/src/components/navigation/nav-desktop.tsx b/apps/website/src/components/navigation/nav-desktop.tsx new file mode 100644 index 00000000..6773dd85 --- /dev/null +++ b/apps/website/src/components/navigation/nav-desktop.tsx @@ -0,0 +1,88 @@ +import * as NavigationMenu from '@radix-ui/react-navigation-menu' +import { Button, Text } from '@status-im/components' +import { DownloadIcon, ExternalIcon } from '@status-im/icons' +import { cx } from 'class-variance-authority' + +import { Logo } from '@/components/logo' +import { LINKS } from '@/config/links' + +import { Link } from '../link' + +const NavDesktop = () => { + return ( + <> + +
+
+ + + +
+ +
+ + {Object.entries(LINKS).map(([name, links]) => ( + + + + {name} + + + + {links.map(link => { + const external = link.href.startsWith('http') + + return ( + + + + {link.name} + + {external && ( + + )} + + + ) + })} + + + ))} + +
+ +
+ +
+
+ +
+ + ) +} + +export { NavDesktop } diff --git a/apps/website/src/components/navigation/nav-mobile.tsx b/apps/website/src/components/navigation/nav-mobile.tsx new file mode 100644 index 00000000..69729319 --- /dev/null +++ b/apps/website/src/components/navigation/nav-mobile.tsx @@ -0,0 +1,67 @@ +import { useState } from 'react' + +import { Button, IconButton } from '@status-im/components' +import { CloseIcon, DownloadIcon, MenuIcon } from '@status-im/icons' + +import { Logo } from '@/components/logo' +import { useLockScroll } from '@/hooks/use-lock-scroll' + +import { Link } from '../link' +import { AccordionMenu } from './accordion-menu' + +const NavMobile = () => { + const [open, setOpen] = useState(false) + const screenHeight = typeof window !== 'undefined' ? window.innerHeight : 0 + + useLockScroll(open) + const handleToggle = () => { + setOpen(prevOpen => !prevOpen) + } + + return ( +
+
+
+ + + +
+ + + ) : ( + + ) + } + onPress={handleToggle} + /> +
+
+ +
+ +
+
+
+ ) +} + +export { NavMobile } diff --git a/apps/website/src/components/page-footer.tsx b/apps/website/src/components/page-footer.tsx deleted file mode 100644 index 630465b4..00000000 --- a/apps/website/src/components/page-footer.tsx +++ /dev/null @@ -1,135 +0,0 @@ -import { Button, Text } from '@status-im/components' -import Link from 'next/link' - -import { LINKS, SOCIALS } from '@/config/links' - -import { Logo } from './logo' - -import type { Links } from '@/config/links' - -export const PageFooter = () => { - return ( -
-
- -
-
- {Object.entries(LINKS).map(([title, links]) => ( -
- ))} - -
- - {"Let's connect"} - -
- {Object.values(SOCIALS).map(social => ( - - {social.name} - - ))} -
-
-
- -
- - -
- -
- - © Status Research & Development GmbH - - - - - - - - -
- - Terms of use - - - Privacy policy - - - Cookies - -
-
-
- ) -} - -type SectionProps = { - title: string - links: Links -} - -const Section = (props: SectionProps) => { - const { title, links } = props - - return ( -
-
- - {title} - -
    - {links.map(link => ( -
  • - - - {link.name} - - -
  • - ))} -
-
-
- ) -} - -type ActionCardProps = { - title: string - description: string - action: string -} - -const ActionCard = (props: ActionCardProps) => { - const { title, description, action } = props - - return ( -
-
- - {title} - - - {description} - -
- -
- ) -} diff --git a/apps/website/src/components/pre-footer.tsx b/apps/website/src/components/pre-footer.tsx new file mode 100644 index 00000000..9b132407 --- /dev/null +++ b/apps/website/src/components/pre-footer.tsx @@ -0,0 +1,48 @@ +import { Button, Text } from '@status-im/components' +import { DownloadIcon } from '@status-im/icons' +import Image from 'next/image' + +import logoSrc from '../../public/images/logo/default.svg' +import { ComingSoon } from './coming-soon' + +const Prefooter = () => { + return ( +
+
+
+ Status logo +

+ Be unstoppable +

+ + + Use the open source, decentralized crypto communication super app. + + +
+
+ +
+
+ + Betas for Mac, Windows, Linux
+ Alphas for iOS & Android +
+
+ +
+
+
+
+
+
+ ) +} + +export { Prefooter } diff --git a/apps/website/src/components/preview-page.tsx b/apps/website/src/components/preview-page.tsx index 61aac8c3..63893dc8 100644 --- a/apps/website/src/components/preview-page.tsx +++ b/apps/website/src/components/preview-page.tsx @@ -334,8 +334,8 @@ export function PreviewPage(props: PreviewPageProps) { style={!bannerURL ? getGradientStyles(data) : undefined} className="relative h-full bg-gradient-to-b from-[var(--gradient-color)] to-[#fff] to-20% xl:grid xl:grid-cols-[560px,auto]" > -
-
+
+
{bannerURL && ( -
+

{INSTRUCTIONS_HEADING[type]}

@@ -475,7 +475,7 @@ export function PreviewPage(props: PreviewPageProps) {
-
+
Have Status already? diff --git a/apps/website/src/components/qr-dialog.tsx b/apps/website/src/components/qr-dialog.tsx index 4f16e77c..4a205ca1 100644 --- a/apps/website/src/components/qr-dialog.tsx +++ b/apps/website/src/components/qr-dialog.tsx @@ -26,8 +26,8 @@ export const QrDialog = (props: Props) => {
-
-
+
+
diff --git a/apps/website/src/components/wallet/comparision-section.tsx b/apps/website/src/components/wallet/comparision-section.tsx new file mode 100644 index 00000000..11663be3 --- /dev/null +++ b/apps/website/src/components/wallet/comparision-section.tsx @@ -0,0 +1,178 @@ +import { Button, Counter, Tag, Text } from '@status-im/components' + +import { useParalax } from '@/hooks/use-parallax' + +import { ParalaxCircle } from './parallax-circle' + +const ComparisionSection = () => { + const { top, bottom } = useParalax({ + initialTop: -690, + }) + + return ( +
+
+
+
+
+
+ +
+

+ Alice has 50 DAI on both Ethereum Mainnet and Optimism and wants + to send 100 DAI to Bob on Arbitrum. +

+
+ +
+ + Finally! Multi-chain done right! + +
+ + Interested in how Status’s send with auto routing and bridging + works and helps users?{' '} + +
+
+ +
+
+
+
+
+ + Other wallets + +
+ {listOneData.map(item => ( + + ))} +
+
+
+ + Status Wallet + +
+ {listTwoData.map(item => ( + + ))} +
+
+ +
+

+ eth:opt:arb:0xAgafhja +

+
+ ) +} + +export { ComparisionSection } + +const listOneData = [ + { + count: 1, + label: 'Open dApp Browser', + }, + { + count: 2, + label: 'Visit Bridge dApp', + }, + { + count: 3, + label: 'Bridge DAI from Mainnet to Arbitrum', + }, + { + count: 4, + label: 'Send DAI on Arbitrum', + }, + { + count: 5, + label: 'Open dApp Browser', + }, + { + count: 6, + label: 'Visit Bridge dApp', + }, + { + count: 7, + label: 'Bridge DAI from Optimism to Arbitrum', + }, + { + count: 8, + label: 'Send DAI on Arbitrum', + noBorder: true, + }, + { + count: '😮‍💨', + label: 'Is that it?', + secondaryLabel: 'Did I use cheapest route and bridges?', + noBorder: true, + }, +] + +const listTwoData = [ + { + count: 1, + label: 'Select the token', + }, + { + count: 2, + label: 'Select the amount', + }, + { + count: 3, + label: 'Send', + noBorder: true, + }, + { + count: '🎉', + label: 'That’s it!', + secondaryLabel: 'Lowest possible cost!', + noBorder: true, + }, +] + +const Item = (props: { + count: string | number + label: string + secondaryLabel?: string + noBorder?: boolean +}) => { + const { count, label, secondaryLabel, noBorder } = props + const isNumber = typeof count === 'number' + return ( +
+ {isNumber ? ( + + ) : ( + {count} + )} +
+ + {label} + + {!isNumber && ( + + {secondaryLabel} + + )} +
+
+ ) +} diff --git a/apps/website/src/components/wallet/hands-section.tsx b/apps/website/src/components/wallet/hands-section.tsx new file mode 100644 index 00000000..59fffa8e --- /dev/null +++ b/apps/website/src/components/wallet/hands-section.tsx @@ -0,0 +1,62 @@ +import { Text } from '@status-im/components' + +const HandsSection = () => { + return ( +
+
+
+

+ Take control +
+ of your crypto +

+ + + No one (including Status!) has the power to freeze, lock-out or + stop a Status user from accessing and transacting their tokens. + + +
+
+
+
+ skull +
+ + Ethereum based assets + + + We support all assets in the Uniswap Labs default tokenlist and + those minted by communities using Status. + +
+
+
+ nft +
+ + NFTs and collectibles + + + We will display any NFTs or collectibles listed on OpenSea plus + those minted by communities using Status. + +
+
+
+ hands + gentleman +
+ ) +} + +export { HandsSection } diff --git a/apps/website/src/components/wallet/hero-section.tsx b/apps/website/src/components/wallet/hero-section.tsx new file mode 100644 index 00000000..2111c23c --- /dev/null +++ b/apps/website/src/components/wallet/hero-section.tsx @@ -0,0 +1,73 @@ +import { Button, Tag, Text } from '@status-im/components' +import { DownloadIcon, WalletIcon } from '@status-im/icons' +import image1 from 'public/assets/wallet/1.png' +import image2 from 'public/assets/wallet/2.png' +import image3 from 'public/assets/wallet/3.png' +import image4 from 'public/assets/wallet/vegas.png' + +import { GridHero } from '../cards/grid-hero' +import { ParalaxCircle } from './parallax-circle' + +const HeroSection = () => { + return ( +
+
+ +
+
+ +
+

+ The future +
+ is multi-chain +

+ + + L2s made simple - send and manage your crypto easily and safely + across multiple networks. + + +
+ +
+
+ +
+
+
+ +
+ ) +} + +export { HeroSection } diff --git a/apps/website/src/components/wallet/index.tsx b/apps/website/src/components/wallet/index.tsx new file mode 100644 index 00000000..149c6e29 --- /dev/null +++ b/apps/website/src/components/wallet/index.tsx @@ -0,0 +1,5 @@ +export { ComparisionSection } from './comparision-section' +export { HandsSection } from './hands-section' +export { HeroSection } from './hero-section' +export { ParalaxCircle } from './parallax-circle' +export { VideoSection } from './video-section' diff --git a/apps/website/src/components/wallet/parallax-circle.tsx b/apps/website/src/components/wallet/parallax-circle.tsx new file mode 100644 index 00000000..dc620dd2 --- /dev/null +++ b/apps/website/src/components/wallet/parallax-circle.tsx @@ -0,0 +1,28 @@ +import { useParalax } from '@/hooks/use-parallax' + +type ParalaxProps = { + initialLeft?: number + initialTop?: number + initialRight?: number + initialBottom?: number +} + +const ParalaxCircle = (props: ParalaxProps) => { + const { top, bottom } = useParalax(props) + + return ( +
+ ) +} + +export { ParalaxCircle } diff --git a/apps/website/src/components/wallet/video-section.tsx b/apps/website/src/components/wallet/video-section.tsx new file mode 100644 index 00000000..258acd99 --- /dev/null +++ b/apps/website/src/components/wallet/video-section.tsx @@ -0,0 +1,76 @@ +import { ContextTag, Text } from '@status-im/components' + +import { ParalaxCircle } from './parallax-circle' + +const VideoSection = () => { + return ( +
+ + +
+

+ Fully +
+ Decentralized +
+ Networks +

+ +
+ + Status supports blockchain networks that are fully committed to + decentralization. + +
+ + Currently supported networks + +
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+ +
+
+ ) +} + +export { VideoSection } diff --git a/apps/website/src/config/links.ts b/apps/website/src/config/links.ts index 10b16bee..55e3c40f 100644 --- a/apps/website/src/config/links.ts +++ b/apps/website/src/config/links.ts @@ -1,3 +1,10 @@ +import { + AdvancedIcon, + AirdropIcon, + CommunitiesIcon, + TokenIcon, +} from '@status-im/icons' + export const LINKS = { Features: [ { name: 'Communities', href: '/features/communities' }, @@ -45,22 +52,27 @@ export const LINKS = { ], } as const +// TODO Update icons when available export const SOCIALS = { status: { name: 'Status', href: '', + icon: CommunitiesIcon, }, twitter: { name: 'Twitter', href: 'https://twitter.com/ethstatus', + icon: TokenIcon, }, github: { name: 'GitHub', href: 'https://github.com/status-im', + icon: AirdropIcon, }, youtube: { name: 'YouTube', href: 'https://youtube.com/', + icon: AdvancedIcon, }, } diff --git a/apps/website/src/hooks/use-lock-scroll.ts b/apps/website/src/hooks/use-lock-scroll.ts new file mode 100644 index 00000000..9ff78a4d --- /dev/null +++ b/apps/website/src/hooks/use-lock-scroll.ts @@ -0,0 +1,12 @@ +export const useLockScroll = (open = false) => { + if (typeof document === 'undefined') { + return + } + // Adds the following code to disable scrolling when the menu is open + const rootElement = document.documentElement + if (open) { + rootElement.style.overflowY = 'hidden' + } else { + rootElement.style.overflowY = 'auto' + } +} diff --git a/apps/website/src/hooks/use-outside-click.ts b/apps/website/src/hooks/use-outside-click.ts new file mode 100644 index 00000000..c6cee2bd --- /dev/null +++ b/apps/website/src/hooks/use-outside-click.ts @@ -0,0 +1,21 @@ +import { useEffect, useRef } from 'react' + +export const useOutsideClick = (callback: () => void) => { + const ref = useRef(null) + + useEffect(() => { + const handleClick = (event: MouseEvent) => { + if (ref.current && !ref.current.contains(event.target as Node)) { + callback() + } + } + + document.addEventListener('click', handleClick, true) + + return () => { + document.removeEventListener('click', handleClick, true) + } + }, [callback]) + + return ref +} diff --git a/apps/website/src/hooks/use-parallax.ts b/apps/website/src/hooks/use-parallax.ts new file mode 100644 index 00000000..a12b976b --- /dev/null +++ b/apps/website/src/hooks/use-parallax.ts @@ -0,0 +1,34 @@ +import { useEffect, useState } from 'react' + +type ParalaxProps = { + initialLeft?: number + initialTop?: number + initialRight?: number + initialBottom?: number +} + +const PARALLAX_SPEED = 4 + +function useParalax(props?: ParalaxProps) { + const initialTop = props?.initialTop || 0 + const initialBottom = props?.initialBottom || 0 + + const [top, setTop] = useState(initialTop) + + const [bottom, setBottom] = useState(initialBottom) + + useEffect(() => { + const handleScroll = () => { + const scrollY = window.scrollY + + setTop(scrollY / PARALLAX_SPEED + initialTop) + setBottom(scrollY / PARALLAX_SPEED + initialBottom) + } + window.addEventListener('scroll', handleScroll, { passive: true }) + return () => window.removeEventListener('scroll', handleScroll) + }, [initialBottom, initialTop]) + + return { top, bottom } +} + +export { useParalax } diff --git a/apps/website/src/layouts/app-layout.tsx b/apps/website/src/layouts/app-layout.tsx index a97b3ba5..befd5964 100644 --- a/apps/website/src/layouts/app-layout.tsx +++ b/apps/website/src/layouts/app-layout.tsx @@ -1,100 +1,38 @@ -import * as NavigationMenu from '@radix-ui/react-navigation-menu' -import { Button, Text } from '@status-im/components' -import { DownloadIcon, ExternalIcon } from '@status-im/icons' -import { cx } from 'class-variance-authority' +import { Footer } from '@/components/footer/footer' +import { FooterMobile } from '@/components/footer/footer-mobile' +import { FloatingMenu } from '@/components/navigation/floating-menu' +import { NavDesktop } from '@/components/navigation/nav-desktop' +import { NavMobile } from '@/components/navigation/nav-mobile' +import { Prefooter } from '@/components/pre-footer' -import { Logo } from '@/components/logo' -import { NavMenu } from '@/components/nav-menu' -import { PageFooter } from '@/components/page-footer' -import { LINKS } from '@/config/links' +import type { ReactElement } from 'react' -import { Link } from '../components/link' +type AppLayoutProps = { + hasPreFooter?: boolean + children: ReactElement +} -import type { PageLayout } from 'next' - -export const AppLayout: PageLayout = page => { +export const AppLayout: React.FC = ({ + hasPreFooter = true, + children, +}) => { return ( <> -
- -
-
- -
-
- - - -
- -
- - {Object.entries(LINKS).map(([name, links]) => ( - - - - {name} - - - - {links.map(link => { - const external = link.href.startsWith('http') - - return ( - - - - {link.name} - - {external && ( - - )} - - - ) - })} - - - ))} - -
- -
- -
-
- -
+ +
+ + {/* ROUNDED WHITE BG */} - {/*
{page}
*/} - {page} - - +
+ {/* TODO Check max-width to use */} +
+ {children} +
+
+ {hasPreFooter && } +
+
) diff --git a/apps/website/src/layouts/insights-layout.tsx b/apps/website/src/layouts/insights-layout.tsx index 3fba19f9..be9193d6 100644 --- a/apps/website/src/layouts/insights-layout.tsx +++ b/apps/website/src/layouts/insights-layout.tsx @@ -1,7 +1,7 @@ import { SideBar } from '../components' import { AppLayout } from './app-layout' -import type { PageLayout } from 'next' +import type { ReactNode } from 'react' // Eventually this will be fetched from the API, at least the nested links const MENU_LINKS = [ @@ -81,11 +81,17 @@ const MENU_LINKS = [ }, ] -export const InsightsLayout: PageLayout = page => { - return AppLayout( -
- -
{page}
-
+interface InsightsLayoutProps { + children: ReactNode +} + +export const InsightsLayout: React.FC = ({ children }) => { + return ( + +
+ +
{children}
+
+
) } diff --git a/apps/website/src/pages/blog/[slug].tsx b/apps/website/src/pages/blog/[slug].tsx index 20c99d3f..5732b894 100644 --- a/apps/website/src/pages/blog/[slug].tsx +++ b/apps/website/src/pages/blog/[slug].tsx @@ -248,6 +248,8 @@ const BlogDetailPage: Page = ({ post, relatedPosts }) => { ) } -BlogDetailPage.getLayout = AppLayout +BlogDetailPage.getLayout = function getLayout(page) { + return {page} +} export default BlogDetailPage diff --git a/apps/website/src/pages/blog/index.tsx b/apps/website/src/pages/blog/index.tsx index 1db8a2cd..aa3ce4c9 100644 --- a/apps/website/src/pages/blog/index.tsx +++ b/apps/website/src/pages/blog/index.tsx @@ -222,6 +222,8 @@ export const PostCard = (props: PostCardProps) => { ) } -BlogPage.getLayout = AppLayout +BlogPage.getLayout = function getLayout(page) { + return {page} +} export default BlogPage diff --git a/apps/website/src/pages/features/wallet.tsx b/apps/website/src/pages/features/wallet.tsx new file mode 100644 index 00000000..7ece4b26 --- /dev/null +++ b/apps/website/src/pages/features/wallet.tsx @@ -0,0 +1,124 @@ +import { Text } from '@status-im/components' +import imageSection1 from 'public/assets/wallet/4.png' +import imageSection2 from 'public/assets/wallet/5.png' +import imageSection3 from 'public/assets/wallet/6.png' +import imageSection4 from 'public/assets/wallet/7.png' +import imageSection5 from 'public/assets/wallet/8.png' +import cubeImage from 'public/assets/wallet/cube.png' +import duckImage from 'public/assets/wallet/duck.png' +import megaphone from 'public/assets/wallet/megaphone.png' +import pizzaImage from 'public/assets/wallet/pizza.png' +import skullImage from 'public/assets/wallet/skull.png' + +import { Section } from '@/components/cards' +import { + ComparisionSection, + HandsSection, + HeroSection, + ParalaxCircle, + VideoSection, +} from '@/components/wallet' +import { AppLayout } from '@/layouts/app-layout' + +import type { Page } from 'next' + +const WalletPage: Page = () => { + return ( +
+ + +
+ +
+
+
+
+ + EIP-3770 format: + +

+ eth: + opt: + artb: + 0xAbc123...xyz789 +

+
+ } + /> +
+
+
+ +
+ + +
+
+
+
+
+
+ +
+ ) +} + +WalletPage.getLayout = function getLayout(page) { + return {page} +} + +export default WalletPage diff --git a/apps/website/src/pages/index.tsx b/apps/website/src/pages/index.tsx index b26ce378..7a630533 100644 --- a/apps/website/src/pages/index.tsx +++ b/apps/website/src/pages/index.tsx @@ -8,8 +8,8 @@ import type { Page } from 'next' const HomePage: Page = () => { return ( <> -
-
+
+

Make the @@ -23,7 +23,7 @@ const HomePage: Page = () => {

-
+
@@ -80,7 +80,7 @@ type FeatureSectionProps = { const FeatureSection = ({ title, description }: FeatureSectionProps) => { return (
-
+

{title}

@@ -125,6 +125,8 @@ const FeatureGrid = () => { ) } -HomePage.getLayout = AppLayout +HomePage.getLayout = function getLayout(page) { + return {page} +} export default HomePage diff --git a/apps/website/src/pages/insights/epics/[epic].tsx b/apps/website/src/pages/insights/epics/[epic].tsx index f17567a2..4642e461 100644 --- a/apps/website/src/pages/insights/epics/[epic].tsx +++ b/apps/website/src/pages/insights/epics/[epic].tsx @@ -26,6 +26,8 @@ const EpicsDetailPage: Page = () => { ) } -EpicsDetailPage.getLayout = InsightsLayout +EpicsDetailPage.getLayout = function getLayout(page) { + return {page} +} export default EpicsDetailPage diff --git a/apps/website/src/pages/insights/epics/index.tsx b/apps/website/src/pages/insights/epics/index.tsx index c6aab954..7ddec7d5 100644 --- a/apps/website/src/pages/insights/epics/index.tsx +++ b/apps/website/src/pages/insights/epics/index.tsx @@ -59,12 +59,13 @@ const EpicsPage: Page = () => { ))}
-
) } -EpicsPage.getLayout = InsightsLayout +EpicsPage.getLayout = function getLayout(page) { + return {page} +} export default EpicsPage diff --git a/apps/website/src/pages/insights/orphans.tsx b/apps/website/src/pages/insights/orphans.tsx index 3a92a530..191bb06f 100644 --- a/apps/website/src/pages/insights/orphans.tsx +++ b/apps/website/src/pages/insights/orphans.tsx @@ -17,6 +17,8 @@ const OrphansPage: Page = () => { ) } -OrphansPage.getLayout = InsightsLayout +OrphansPage.getLayout = function getLayout(page) { + return {page} +} export default OrphansPage diff --git a/apps/website/src/pages/insights/repos.tsx b/apps/website/src/pages/insights/repos.tsx index 5e63ce48..35e2ff91 100644 --- a/apps/website/src/pages/insights/repos.tsx +++ b/apps/website/src/pages/insights/repos.tsx @@ -85,6 +85,8 @@ const ReposPage: Page = () => { ) } -ReposPage.getLayout = InsightsLayout +ReposPage.getLayout = function getLayout(page) { + return {page} +} export default ReposPage diff --git a/apps/website/src/pages/insights/workstreams/[workstream].tsx b/apps/website/src/pages/insights/workstreams/[workstream].tsx index efbcadaf..da983be3 100644 --- a/apps/website/src/pages/insights/workstreams/[workstream].tsx +++ b/apps/website/src/pages/insights/workstreams/[workstream].tsx @@ -26,6 +26,8 @@ const WorkstreamDetailPage: Page = () => { ) } -WorkstreamDetailPage.getLayout = InsightsLayout +WorkstreamDetailPage.getLayout = function getLayout(page) { + return {page} +} export default WorkstreamDetailPage diff --git a/apps/website/src/pages/insights/workstreams/index.tsx b/apps/website/src/pages/insights/workstreams/index.tsx index 063ad4a4..3b6afdfc 100644 --- a/apps/website/src/pages/insights/workstreams/index.tsx +++ b/apps/website/src/pages/insights/workstreams/index.tsx @@ -64,6 +64,8 @@ const WorkstreamsPage: Page = () => { ) } -WorkstreamsPage.getLayout = InsightsLayout +WorkstreamsPage.getLayout = function getLayout(page) { + return {page} +} export default WorkstreamsPage diff --git a/apps/website/tailwind.config.cjs b/apps/website/tailwind.config.cjs index d46c3838..02c7685e 100644 --- a/apps/website/tailwind.config.cjs +++ b/apps/website/tailwind.config.cjs @@ -30,6 +30,10 @@ module.exports = { height: 'height', }, + screens: { + 'md-lg': { raw: '(min-width: 868px)' }, + }, + keyframes: { heightIn: { from: { height: 0 }, diff --git a/packages/components/src/button/button.tsx b/packages/components/src/button/button.tsx index 2864137d..ac502b08 100644 --- a/packages/components/src/button/button.tsx +++ b/packages/components/src/button/button.tsx @@ -19,6 +19,7 @@ type Props = PressableProps & { icon?: React.ReactElement iconAfter?: React.ReactElement disabled?: boolean + fullWidth?: boolean } const textColors: MapVariant = { @@ -29,6 +30,19 @@ const textColors: MapVariant = { outline: '$neutral-100', ghost: '$neutral-100', danger: '$white-100', + blue: '$white-100', + purple: '$white-100', + orange: '$white-100', + army: '$white-100', + turquoise: '$white-100', + sky: '$white-100', + yellow: '$white-100', + pink: '$white-100', + cooper: '$white-100', + camel: '$white-100', + magenta: '$white-100', + yin: '$white-100', + yang: '$neutral-100', } const textSizes: Record, TextProps['size']> = { @@ -45,6 +59,7 @@ const Button = (props: Props, ref: Ref) => { children, icon, iconAfter, + fullWidth, ...buttonProps } = props @@ -62,8 +77,9 @@ const Button = (props: Props, ref: Ref) => { radius={shape === 'circle' ? 'full' : size} size={size} iconOnly={iconOnly} + width={fullWidth ? '100%' : 'auto'} > - {icon ? cloneElement(icon, { color: '$neutral-40' }) : null} + {icon ? cloneElement(icon, { color: textColor || '$neutral-40' }) : null} {children} @@ -133,6 +149,72 @@ const Base = styled(Stack, { // TODO: update background color pressStyle: { backgroundColor: '$danger' }, }, + // TODO sync colors with the design foundation colors + blue: { + backgroundColor: '$blue-50', + hoverStyle: { backgroundColor: '$blue-60' }, + pressStyle: { backgroundColor: '$blue-50' }, + }, + purple: { + backgroundColor: '$purple-50', + hoverStyle: { backgroundColor: '$purple-60' }, + pressStyle: { backgroundColor: '$purple-50' }, + }, + orange: { + backgroundColor: '$orange-50', + hoverStyle: { backgroundColor: '$orange-60' }, + pressStyle: { backgroundColor: '$orange-50' }, + }, + army: { + backgroundColor: '$indigo-50', + hoverStyle: { backgroundColor: '$indigo-60' }, + pressStyle: { backgroundColor: '$indigo-50' }, + }, + turquoise: { + backgroundColor: '$turquoise-50', + hoverStyle: { backgroundColor: '$turquoise-60' }, + pressStyle: { backgroundColor: '$turquoise-50' }, + }, + sky: { + backgroundColor: '$sky-50', + hoverStyle: { backgroundColor: '$sky-60' }, + pressStyle: { backgroundColor: '$sky-50' }, + }, + yellow: { + backgroundColor: '$yellow-50', + hoverStyle: { backgroundColor: '$yellow-60' }, + pressStyle: { backgroundColor: '$yellow-50' }, + }, + pink: { + backgroundColor: '$pink-50', + hoverStyle: { backgroundColor: '$pink-60' }, + pressStyle: { backgroundColor: '$pink-50' }, + }, + cooper: { + backgroundColor: '$cooper-50', + hoverStyle: { backgroundColor: '$cooper-60' }, + pressStyle: { backgroundColor: '$cooper-50' }, + }, + camel: { + backgroundColor: '$camel-50', + hoverStyle: { backgroundColor: '$camel-60' }, + pressStyle: { backgroundColor: '$camel-50' }, + }, + magenta: { + backgroundColor: '$magenta', + hoverStyle: { backgroundColor: '$magenta-60' }, + pressStyle: { backgroundColor: '$magenta-50' }, + }, + yin: { + backgroundColor: '$yin-50', + hoverStyle: { backgroundColor: '$yin-60' }, + pressStyle: { backgroundColor: '$yin-50' }, + }, + yang: { + backgroundColor: '$yang-50', + hoverStyle: { backgroundColor: '$yang-60' }, + pressStyle: { backgroundColor: '$yang-50' }, + }, }, disabled: { diff --git a/packages/components/src/tag/tag.tsx b/packages/components/src/tag/tag.tsx index dbca591e..bc9d4b09 100644 --- a/packages/components/src/tag/tag.tsx +++ b/packages/components/src/tag/tag.tsx @@ -42,7 +42,10 @@ const Tag = (props: Props) => { return {icon} } - return createElement(icon, { size: iconSizes[size] }) + return createElement(icon, { + size: iconSizes[size], + color, + }) } return ( diff --git a/packages/icons/lib/create-icon.tsx b/packages/icons/lib/create-icon.tsx index f2f24c82..ba79e32e 100644 --- a/packages/icons/lib/create-icon.tsx +++ b/packages/icons/lib/create-icon.tsx @@ -14,9 +14,15 @@ import type { ComponentType, SVGProps } from 'react' // } // } +function isColorTokens( + value: `#${string}` | ColorTokens +): value is ColorTokens { + return typeof value === 'string' && value.startsWith('$') +} + export interface IconProps extends SVGProps { size: 12 | 16 | 20 - color?: ColorTokens + color?: ColorTokens | `#${string}` } export function createIcon

>( @@ -25,7 +31,7 @@ export function createIcon

>( const Icon = forwardRef((props, ref) => { const { size, color = '$neutral-100', ...rest } = props const theme = useTheme() - const token = theme[color]?.val + const token = isColorTokens(color) ? theme[color]?.val : color return createElement(Component, { ref,