From 030c7bc702a97bc6e9851f095ba4dcae15623105 Mon Sep 17 00:00:00 2001 From: Sohee Lim Date: Thu, 14 Nov 2024 20:49:37 -0500 Subject: [PATCH 1/4] feat: add home UI --- src/components/Icons/index.tsx | 217 ++++++++++ src/components/NewsletterForm/index.tsx | 88 ++++ src/css/custom.css | 8 + src/pages/index.tsx | 479 ++++++++++++---------- src/theme/Layout.tsx | 20 + src/theme/Navbar.tsx | 60 +-- static/img/Union.svg | 2 +- static/img/logo.svg | 2 +- static/img/undraw_docusaurus_mountain.svg | 42 +- static/img/undraw_docusaurus_react.svg | 42 +- static/img/undraw_docusaurus_tree.svg | 2 +- static/img/uni_dark_icon.svg | 4 +- tailwind.config.js | 7 + 13 files changed, 677 insertions(+), 296 deletions(-) create mode 100644 src/components/NewsletterForm/index.tsx create mode 100644 src/theme/Layout.tsx diff --git a/src/components/Icons/index.tsx b/src/components/Icons/index.tsx index a41b8eb107..7d96b813b2 100644 --- a/src/components/Icons/index.tsx +++ b/src/components/Icons/index.tsx @@ -2,6 +2,103 @@ import React, { FC } from 'react' import cn from 'classnames' +export const ThickX: FC<{ className?: string }> = ({ className }) => { + return ( + + + + ) +} + +export const Globe: FC<{ + className?: string + color: 'orange-vibrant' | 'brown-vibrant' | 'pink-vibrant' | 'neutral-1' +}> = ({ className, color }) => { + return ( + + + + ) +} + +export const Hexagon: FC<{ className?: string; color?: 'green' }> = ({ className, color = 'green' }) => { + return ( + + + + ) +} + +export const BookOpen: FC<{ className?: string; color?: 'accent-1' }> = ({ className, color = 'accent-1' }) => { + return ( + + + + ) +} + +export const ArrowRight: FC<{ + className?: string + color?: 'accent-1' +}> = ({ className, color = 'accent-1' }) => { + return ( + + + + ) +} + export const MiniUnicon: FC<{ className?: string color?: 'accent-1' | 'neutral-1' @@ -79,6 +176,54 @@ export const MiniUnicon: FC<{ ) } +export const Emblem1: FC<{ + className?: string + color?: 'accent-1' +}> = ({ className, color = 'accent-1' }) => { + return ( + + + + ) +} + +export const Emblem2: FC<{ + className?: string + color?: 'accent-1' +}> = ({ className, color = 'accent-1' }) => { + return ( + + + + ) +} + export const Github: FC<{ className?: string color?: 'neutral-2' @@ -170,6 +315,7 @@ export const Menu: FC<{ ) } + export const Moon: FC<{ className?: string color?: 'neutral-2' @@ -186,6 +332,77 @@ export const Moon: FC<{ ) } +export const Npm: FC<{ className?: string }> = ({ className }) => { + return ( + + + + + + + ) +} + +export const HelpCircle: FC<{ + className?: string + color?: 'orange-vibrant' | 'blue-vibrant' | 'green-base' | 'pink-vibrant' +}> = ({ className, color = 'orange-vibrant' }) => { + return ( + + + + ) +} + +export const Chat: FC<{ + className?: string + color?: 'brown-vibrant' +}> = ({ className, color = 'brown-vibrant' }) => { + return ( + + + + ) +} + +export const Envlope: FC<{ + className?: string + color?: 'pink-vibrant' | 'neutral-2' +}> = ({ className, color = 'pink-vibrant' }) => { + return ( + + + + ) +} + export type Icon = 'sun' | 'moon' export const IconMap: FC<{ diff --git a/src/components/NewsletterForm/index.tsx b/src/components/NewsletterForm/index.tsx new file mode 100644 index 0000000000..bd3c37e925 --- /dev/null +++ b/src/components/NewsletterForm/index.tsx @@ -0,0 +1,88 @@ +import React, { useState } from 'react' +import { Envlope } from '../../components/Icons' +import cn from 'classnames' + +interface NewsletterFormProps { + headerText: string + headerTextClass?: string + globeColorClass: 'pink-vibrant' | 'neutral-2' + inputClass?: string +} + +const NewsletterForm: React.FC = ({ + headerText, + headerTextClass, + inputClass, + globeColorClass, +}) => { + const [emailInputValue, setEmailInputValue] = useState('') + const [isSubscribed, setIsSubscribed] = useState(false) + const [error, setError] = useState('') + + const handleSubscribe = async (e: React.FormEvent) => { + e.preventDefault() + + if (!emailInputValue) { + setError('Please provide a valid email address.') + return + } + + try { + const response = await fetch('/api/subscribeEmail', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ emailInputValue }), + }) + + if (response.ok) { + setIsSubscribed(true) + setError('') + } else { + const data = await response.json() + setError(data.message || 'Subscription failed. Please try again.') + } + } catch (err) { + setError('An error occurred. Please try again.') + } + } + + return ( + <> +

{headerText}

+
+
+
+ setEmailInputValue(e.target.value)} + /> + +
+ +
+
+ {!isSubscribed && error && ( +

{error}

+ )} + {isSubscribed && ( +

+ Successfully subscribed +

+ )} +
+
+ + ) +} + +export default NewsletterForm diff --git a/src/css/custom.css b/src/css/custom.css index 07c844b12a..abff705148 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -22,3 +22,11 @@ .default-grid { @apply grid grid-cols-4 gap-gap-large sm:grid-cols-8; } + +.content-page-padding { + @apply p-6 pb-10 sm:p-12 sm:pt-6 md:px-10 md:pb-12; +} + +.divider { + @apply border-t border-light-surface-3 dark:border-dark-surface-3; +} diff --git a/src/pages/index.tsx b/src/pages/index.tsx index d4ef7ddc0c..f105f62e8c 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,41 +1,47 @@ +import React, { FC } from 'react' + import Link from '@docusaurus/Link' -import useBaseUrl from '@docusaurus/useBaseUrl' -import Discord from '@site/static/img/discord.svg' -import GitHub from '@site/static/img/github.svg' -import Npm from '@site/static/img/npm.svg' -// import UGP from '@site/static/img/UGP.png' import Layout from '@theme/Layout' -import ThemedImage from '@theme/ThemedImage' -import { TraceEvent } from '@uniswap/analytics' -import { - BrowserEvent, - DocsHomepageElementName as ElementName, - DocsSectionName as SectionName, - SharedEventName, -} from '@uniswap/analytics-events' -import React from 'react' -import { ArrowUpRight as LinkIcon, BookOpen, HelpCircle, Info, MessageCircle } from 'react-feather' +import cn from 'classnames' +// eslint-disable-next-line +const UPG = require('../../static/img/UGP.png').default -import SearchBarWithAnalytics from '../theme/SearchBar' +import { + Emblem1, + Emblem2, + ThickX, + Hexagon, + BookOpen, + ArrowRight, + Github, + Npm, + HelpCircle, + Chat, + Globe, +} from '../components/Icons' +import NewsletterForm from '../components/NewsletterForm' export const actions = [ { - title: 'What is Uniswap', - icon: Info, + title: 'What is Uniswap?', + icon: 'book-open', to: '/concepts/overview', - text: `Learn about the core concepts of the Uniswap Protocol, Swaps, Pools, Concentrated Liquidity and more.`, + text: 'Learn about the core concepts of the Uniswap Protocol, Swaps, Pools, Liquidity, and more.', + color: 'pink', }, { - title: 'Integrate with Uniswap', - icon: HelpCircle, + title: 'Troubleshoot an issue', + icon: 'x', to: '/sdk/v3/overview', - text: `Learn how to integrate with Uniswap by building a dApp through guided examples.`, + text: 'Learn how to troubleshoot an issue.', + color: 'blue', }, { - title: 'The Uniswap smart contracts', - icon: BookOpen, + title: 'How to use Uniswap', + icon: 'hexagon', to: '/contracts/v3/overview', - text: `Learn about the architecture of the Uniswap Protocol smart contracts through guided examples.`, + text: 'Learn how to integrate with Uniswap by building a dApp.', + color: 'green', }, ] @@ -43,27 +49,27 @@ export const developerLinks = [ { title: 'uniswap-v3-core', href: 'https://github.com/Uniswap/uniswap-v3-core', - icon: GitHub, + icon: 'github', }, { title: 'uniswap-v3-sdk', href: 'https://github.com/Uniswap/uniswap-v3-sdk', - icon: GitHub, + icon: 'github', }, { title: 'uniswap-v3-periphery', href: 'https://github.com/Uniswap/uniswap-v3-periphery', - icon: GitHub, + icon: 'github', }, { title: 'Deployment addresses', href: 'https://github.com/Uniswap/uniswap-v3-periphery/blob/main/deploys.md', - icon: GitHub, + icon: 'github', }, { title: 'widgets', href: 'https://www.npmjs.com/package/@uniswap/widgets', - icon: Npm, + icon: 'npm', }, ] @@ -122,216 +128,247 @@ export const smartContractGuides = [ }, ] -export default function Home() { +const connectBlock = { + title: 'Connect with us', + supportTitle: 'Get Support', + supportButton: { + url: 'https://help.uniswap.org/', + name: 'Help center', + }, + socialTitle: 'Insights and news from the team', + socialButton: { + url: 'https://blog.uniswap.org/', + name: 'Help center', + }, + newsletterTitle: 'Sign up for research and updates from the Uniswap Labs team', +} + +const Home = () => { return ( - -
-
-
-

Welcome to Uniswap Docs

-
- -
-
- {/* */} -
- {actions.map((action) => ( - +
+
+

+ Build + + with + + Uniswap +

+

+ Dive into the world of DeFi apps, integrations, and developer tooling built on top of the Uniswap Protocol. +

+
+ +
+ {actions.map((action, i) => { + return ( + 0, + 'bg-light-accent-2 dark:bg-dark-accent-2': action.color === 'pink', + 'bg-light-blue dark:bg-dark-blue': action.color === 'blue', + 'bg-light-green dark:bg-dark-green': action.color === 'green', + })} > - -
-
-
- -
-
- +
+
+ {action.icon === 'book-open' ? ( +
+ + + Getting started +
-
-

{action.title}

-

{action.text}

+ ) : null} + {action.icon === 'x' ? : null} + {action.icon === 'hexagon' ? : null}
- - +
+

+ {action.title} +

+

{action.text}

+
+
+ + ) + })} +
+ +
+ +
+

Integrate your Smart Contracts

+
+ {dAppGuides.map((card) => ( + ))}
-
-
-

Integrate your dApp

-

Explore these guided tutorials to get started integrating with Uniswap in your dApp.

-
- {dAppGuides.map((action) => ( - - -
-
-
-

{action.title}

-
-
- -
-
-

{action.text}

-
- -
- ))} -
+ +
+ +
+

Integrate your dApp

+
+ {smartContractGuides.map((card) => ( + + ))}
-
-

Integrate your smart contracts

-

Explore these guided tutorials to get started integrating with Uniswap in your smart contracts.

-
- {smartContractGuides.map((action) => ( - + +
+ +
+

Quick Links

+
+ {developerLinks.map((devLink) => { + return ( + - -
-
-
-

{action.title}

-
-
- -
-
-

{action.text}

-
- - - ))} -
+ <> + {devLink.icon === 'github' ? : null} + {devLink.icon === 'npm' ? : null} +

+ {devLink.title} +

+ + + ) + })}
-
-
- {/* */} -
-

Developer Links

- {developerLinks.map((action) => ( - - -
-
-
-
-
- -
-
- {action.title} -
-
- -
-
-
- -
- ))} + +
+ +
+

{connectBlock.title}

+
+
+

+ {connectBlock.supportTitle} +

+ +
+
+

+ {connectBlock.socialTitle} +

+ +
+
+ +
-
-
- - -
- -
-

Discord

-

Join our Developer Community.

-
-
- -
- - + +
+
+
- -
-

Forum

-

Discuss governance and more.

-
+

Uniswap Grants Program

+

+ Uniswap Governance offers grant funding for people who are building apps, tools, and activities for + Uniswap Protocol users, builders, and community members. +

- - - - -
-
- -
-
-

GitHub

-

View all Uniswap repositories.

-
+
+ + + + Learn more + +
- - -
- -
- {/* */} -
-

Uniswap Grants Program

-

- Uniswap Governance offers grant funding for people who are building apps, tools, and activities for - Uniswap Protocol users, builders, and community members.{' '} -

+
+
+
- +
) } + +export default Home + +const IconButton: FC<{ + href: string + ariaLabel?: string + label: string + color: 'orange-vibrant' | 'brown-vibrant' +}> = ({ href, label, color }) => { + return ( +
+ + {color === 'orange-vibrant' && } + {color === 'brown-vibrant' && } + + {label} + + +
+ ) +} + +const ArticleLinkCard: FC<{ + title: string + description: string + url: string +}> = ({ title, description, url }) => { + return ( + +
+

+ {title} +

+

{description}

+
+
+ +
+ + ) +} diff --git a/src/theme/Layout.tsx b/src/theme/Layout.tsx new file mode 100644 index 0000000000..3845ef8f8d --- /dev/null +++ b/src/theme/Layout.tsx @@ -0,0 +1,20 @@ +import React, { FC } from 'react' + +import LayoutProvider from '@theme/Layout/Provider' +import { PageMetadata } from '@docusaurus/theme-common' +import Navbar from '@theme/Navbar' +import Footer from '@theme/Footer' +import type { Props } from '@theme/Layout' + +const Layout: FC = ({ title, description, children }) => { + return ( + + + +
{children}
+
+ + ) +} + +export default Layout diff --git a/src/theme/Navbar.tsx b/src/theme/Navbar.tsx index 9c0ae4a89d..30840ab6f6 100644 --- a/src/theme/Navbar.tsx +++ b/src/theme/Navbar.tsx @@ -6,36 +6,40 @@ import ThemeSwitch from '../components/ThemeSwitch' const Navbar: FC = () => { return ( - + + ) } diff --git a/static/img/Union.svg b/static/img/Union.svg index 1d4ffbb9f9..fc7f28765e 100644 --- a/static/img/Union.svg +++ b/static/img/Union.svg @@ -1,3 +1,3 @@ - + diff --git a/static/img/logo.svg b/static/img/logo.svg index 9db6d0d066..02753e9eac 100644 --- a/static/img/logo.svg +++ b/static/img/logo.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/static/img/undraw_docusaurus_mountain.svg b/static/img/undraw_docusaurus_mountain.svg index 431cef2f7f..d7b5368b97 100644 --- a/static/img/undraw_docusaurus_mountain.svg +++ b/static/img/undraw_docusaurus_mountain.svg @@ -45,17 +45,17 @@ - - - - - - - - - - - + + + + + + + + + + + @@ -68,10 +68,10 @@ - + - + @@ -87,7 +87,7 @@ - + @@ -116,7 +116,7 @@ - + @@ -130,14 +130,14 @@ - + - + @@ -161,10 +161,10 @@ - - - - + + + + diff --git a/static/img/undraw_docusaurus_react.svg b/static/img/undraw_docusaurus_react.svg index e417050433..250ce76666 100644 --- a/static/img/undraw_docusaurus_react.svg +++ b/static/img/undraw_docusaurus_react.svg @@ -38,17 +38,17 @@ - - - - - - - - - - - + + + + + + + + + + + @@ -61,10 +61,10 @@ - + - + @@ -80,7 +80,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -123,14 +123,14 @@ - + - + @@ -154,10 +154,10 @@ - - - - + + + + diff --git a/static/img/undraw_docusaurus_tree.svg b/static/img/undraw_docusaurus_tree.svg index a05cc03dda..cd4c2cb037 100644 --- a/static/img/undraw_docusaurus_tree.svg +++ b/static/img/undraw_docusaurus_tree.svg @@ -1 +1 @@ -docu_tree \ No newline at end of file +docu_tree \ No newline at end of file diff --git a/static/img/uni_dark_icon.svg b/static/img/uni_dark_icon.svg index 3a974624c8..28ae7416bf 100644 --- a/static/img/uni_dark_icon.svg +++ b/static/img/uni_dark_icon.svg @@ -7,7 +7,7 @@ - - + + diff --git a/tailwind.config.js b/tailwind.config.js index c02a64054d..8b449cb0d2 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -159,6 +159,13 @@ module.exports = { 'dark-pink-vibrant': '#FC74FE', 'dark-pink-fade': '#361A37', 'dark-pink-fade-80': 'rgba(54,26,55,0.80)', + 'blue-base': '#4981FF', + 'green-base': '#0C8911', + 'green-vibrant': '#21C95E', + 'light-blue': '#EFF4FF', + 'dark-blue': '#10143D', + 'light-green': '#EEFBF1', + 'dark-green': '#0F2C1A', }, }, }, From 3073ffc148e5efb046c1ecb5ca7ae43baebd4b48 Mon Sep 17 00:00:00 2001 From: Sohee Lim Date: Fri, 15 Nov 2024 09:35:46 -0500 Subject: [PATCH 2/4] feat: add 404 --- src/theme/Navbar.tsx | 11 +- src/theme/NotFound.tsx | 2297 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2303 insertions(+), 5 deletions(-) create mode 100644 src/theme/NotFound.tsx diff --git a/src/theme/Navbar.tsx b/src/theme/Navbar.tsx index 30840ab6f6..baa3aac280 100644 --- a/src/theme/Navbar.tsx +++ b/src/theme/Navbar.tsx @@ -1,5 +1,6 @@ import React, { FC } from 'react' +import Link from '@docusaurus/Link' import OriginalSearchbar from '@theme-original/SearchBar' import { MiniUnicon, Menu } from '../components/Icons' import ThemeSwitch from '../components/ThemeSwitch' @@ -11,10 +12,10 @@ const Navbar: FC = () => {
diff --git a/src/theme/NotFound.tsx b/src/theme/NotFound.tsx new file mode 100644 index 0000000000..9ba86cb9e4 --- /dev/null +++ b/src/theme/NotFound.tsx @@ -0,0 +1,2297 @@ +import React, { FC, useEffect } from 'react' +import Link from '@docusaurus/Link' + +import { ThemeManager } from '../utils/storage' + +const NotFound: FC = () => { + useEffect(() => { + const currentTheme = ThemeManager.get() + + document.documentElement.setAttribute('data-theme', currentTheme) + document.documentElement.setAttribute('class', currentTheme) + }, []) + + return ( +
+

Error - 404

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

+ That page can’t be found. +

+ +
+ View all posts +
+ +
+
+
+ ) +} + +export default NotFound From d0c0d3b270c724381bd836571d5edd8120dcdea4 Mon Sep 17 00:00:00 2001 From: Sohee Lim Date: Fri, 15 Nov 2024 09:56:33 -0500 Subject: [PATCH 3/4] fix: style --- src/components/NewsletterForm/index.tsx | 5 +++-- src/pages/index.tsx | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/NewsletterForm/index.tsx b/src/components/NewsletterForm/index.tsx index bd3c37e925..b8abb64fdf 100644 --- a/src/components/NewsletterForm/index.tsx +++ b/src/components/NewsletterForm/index.tsx @@ -28,7 +28,8 @@ const NewsletterForm: React.FC = ({ } try { - const response = await fetch('/api/subscribeEmail', { + // Replace '/some-api' with the actual API endpoint + const response = await fetch('/some-api', { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -64,7 +65,7 @@ const NewsletterForm: React.FC = ({ />
-
{ to="https://unigrants.org/" > - + Learn more From 96befd41de522eff882182ffcf28e8d8ad08d2e9 Mon Sep 17 00:00:00 2001 From: Sohee Lim Date: Fri, 15 Nov 2024 14:22:07 -0500 Subject: [PATCH 4/4] fix: typo --- src/components/Icons/index.tsx | 2 +- src/components/NewsletterForm/index.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Icons/index.tsx b/src/components/Icons/index.tsx index 7d96b813b2..e6c3612383 100644 --- a/src/components/Icons/index.tsx +++ b/src/components/Icons/index.tsx @@ -386,7 +386,7 @@ export const Chat: FC<{ ) } -export const Envlope: FC<{ +export const Envelope: FC<{ className?: string color?: 'pink-vibrant' | 'neutral-2' }> = ({ className, color = 'pink-vibrant' }) => { diff --git a/src/components/NewsletterForm/index.tsx b/src/components/NewsletterForm/index.tsx index b8abb64fdf..fedf404abf 100644 --- a/src/components/NewsletterForm/index.tsx +++ b/src/components/NewsletterForm/index.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react' -import { Envlope } from '../../components/Icons' +import { Envelope } from '../../components/Icons' import cn from 'classnames' interface NewsletterFormProps { @@ -63,7 +63,7 @@ const NewsletterForm: React.FC = ({ value={emailInputValue} onChange={(e) => setEmailInputValue(e.target.value)} /> - +