From 3026e87606bf8b640b3cc0edd3a5761de1eb1d20 Mon Sep 17 00:00:00 2001 From: nhestrompia Date: Mon, 28 Aug 2023 11:51:30 +0300 Subject: [PATCH 01/38] fix(web): vote-stake-data --- web/src/pages/Courts/CourtDetails/Stats.tsx | 4 ++-- web/src/utils/index.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/web/src/pages/Courts/CourtDetails/Stats.tsx b/web/src/pages/Courts/CourtDetails/Stats.tsx index 72e73ac54..d6798c079 100644 --- a/web/src/pages/Courts/CourtDetails/Stats.tsx +++ b/web/src/pages/Courts/CourtDetails/Stats.tsx @@ -44,8 +44,8 @@ const stats: IStat[] = [ { title: "Vote Stake", coinId: 0, - getText: (data) => formatPNK(data?.minStake), - getSubtext: (data, coinPrice) => formatUSD(Number(formatUnitsWei(data?.minStake)) * (coinPrice ?? 0)), + getText: (data) => formatPNK(data?.alpha), + getSubtext: (data, coinPrice) => formatUSD(Number(formatUnitsWei(data?.alpha)) * (coinPrice ?? 0)), color: "purple", icon: VoteStake, }, diff --git a/web/src/utils/index.ts b/web/src/utils/index.ts index 0d37380be..938f2de46 100644 --- a/web/src/utils/index.ts +++ b/web/src/utils/index.ts @@ -5,7 +5,7 @@ export const isUndefined = (maybeObject: any): maybeObject is undefined => typeo export const formatUnitsWei = (value: bigint) => formatUnits(value, 18); -export const formatPNK = (value: bigint, fractionDigits = 0) => +export const formatPNK = (value: bigint, fractionDigits = 4) => commify(Number(formatUnitsWei(value)).toFixed(fractionDigits)); export const formatETH = (value: bigint, fractionDigits = 4) => From 4bbf2587d076261f7395b65e068b25ffcd0ebd27 Mon Sep 17 00:00:00 2001 From: nhestrompia Date: Mon, 28 Aug 2023 13:05:42 +0300 Subject: [PATCH 02/38] fix: fraction digits --- web/src/utils/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/utils/index.ts b/web/src/utils/index.ts index 938f2de46..0d37380be 100644 --- a/web/src/utils/index.ts +++ b/web/src/utils/index.ts @@ -5,7 +5,7 @@ export const isUndefined = (maybeObject: any): maybeObject is undefined => typeo export const formatUnitsWei = (value: bigint) => formatUnits(value, 18); -export const formatPNK = (value: bigint, fractionDigits = 4) => +export const formatPNK = (value: bigint, fractionDigits = 0) => commify(Number(formatUnitsWei(value)).toFixed(fractionDigits)); export const formatETH = (value: bigint, fractionDigits = 4) => From 72d64dd20fe08f24954a8ceb054ab9765ac2dd7f Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Sat, 2 Sep 2023 04:54:16 +0200 Subject: [PATCH 03/38] feat(web): navbar and footer for desktop --- web/src/assets/svgs/socialmedia/twitter.svg | 10 -- web/src/assets/svgs/socialmedia/x.svg | 3 + .../ConnectWallet/AccountDisplay.tsx | 27 +++- web/src/consts/socialmedia.tsx | 6 +- web/src/hooks/useWindowWidth.tsx | 19 +++ web/src/layout/Footer/index.tsx | 18 ++- web/src/layout/Header/index.tsx | 132 ++++++++++++++++-- web/src/layout/Header/navbar/DappList.tsx | 13 +- web/src/layout/Header/navbar/Explore.tsx | 54 +++++-- web/src/layout/Header/navbar/Menu/Help.tsx | 13 +- .../Header/navbar/Menu/Settings/index.tsx | 13 +- web/src/layout/Header/navbar/Menu/index.tsx | 54 +++++-- web/src/layout/Header/navbar/index.tsx | 44 +++--- web/src/pages/Home/Header.tsx | 12 +- web/src/styles/smallScreenStyle.ts | 8 +- web/src/styles/themes.ts | 2 + 16 files changed, 335 insertions(+), 93 deletions(-) delete mode 100644 web/src/assets/svgs/socialmedia/twitter.svg create mode 100644 web/src/assets/svgs/socialmedia/x.svg create mode 100644 web/src/hooks/useWindowWidth.tsx diff --git a/web/src/assets/svgs/socialmedia/twitter.svg b/web/src/assets/svgs/socialmedia/twitter.svg deleted file mode 100644 index 458fd4f9b..000000000 --- a/web/src/assets/svgs/socialmedia/twitter.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/web/src/assets/svgs/socialmedia/x.svg b/web/src/assets/svgs/socialmedia/x.svg new file mode 100644 index 000000000..e9faf4183 --- /dev/null +++ b/web/src/assets/svgs/socialmedia/x.svg @@ -0,0 +1,3 @@ + + + diff --git a/web/src/components/ConnectWallet/AccountDisplay.tsx b/web/src/components/ConnectWallet/AccountDisplay.tsx index 0fb33516d..ead4acc1d 100644 --- a/web/src/components/ConnectWallet/AccountDisplay.tsx +++ b/web/src/components/ConnectWallet/AccountDisplay.tsx @@ -1,5 +1,6 @@ import React from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; +import { smallScreenStyle } from "styles/smallScreenStyle"; import { useAccount, useNetwork, useEnsAvatar, useEnsName } from "wagmi"; import Identicon from "react-identicons"; import { shortenAddress } from "utils/shortenAddress"; @@ -10,6 +11,16 @@ const Container = styled.div` justify-content: space-between; align-content: center; align-items: center; + height: 32px; + border-radius: 300px; + background-color: ${({ theme }) => theme.whiteLowOpacity}; + padding: 0 12px; + + ${smallScreenStyle( + () => css` + background-color: ${({ theme }) => theme.whiteBackground}; + ` + )} `; const AccountContainer = styled.div` @@ -17,11 +28,12 @@ const AccountContainer = styled.div` display: flex; align-items: center; width: fit-content; - gap: 8px; + gap: 12px; + > label { color: ${({ theme }) => theme.primaryText}; - font-size: 16px; - font-weight: 600; + font-size: 14px; + font-weight: 500; } `; const ChainConnectionContainer = styled.div` @@ -29,16 +41,17 @@ const ChainConnectionContainer = styled.div` min-height: 32px; display: flex; align-items: center; + padding-left: 12px; > label { color: ${({ theme }) => theme.success}; - font-size: 16px; - margin-right: 4px; + font-size: 14px; + font-weight: 500; } :before { content: ""; width: 8px; height: 8px; - margin: 0px 13px 0px 3px; + margin: 0px 8px 0px 3px; border-radius: 50%; background-color: ${({ theme }) => theme.success}; } diff --git a/web/src/consts/socialmedia.tsx b/web/src/consts/socialmedia.tsx index bd6ffebb7..62d82b57e 100644 --- a/web/src/consts/socialmedia.tsx +++ b/web/src/consts/socialmedia.tsx @@ -3,7 +3,7 @@ import EtherscanLogo from "svgs/socialmedia/etherscan.svg"; import GithubLogo from "svgs/socialmedia/github.svg"; import SnapshotLogo from "svgs/socialmedia/snapshot.svg"; import DiscordLogo from "svgs/socialmedia/discord.svg"; -import TwitterLogo from "svgs/socialmedia/twitter.svg"; +import XLogo from "svgs/socialmedia/x.svg"; import RedditLogo from "svgs/socialmedia/reddit.svg"; import TelegramLogo from "svgs/socialmedia/telegram.svg"; import GhostBlogLogo from "svgs/socialmedia/ghost-blog.svg"; @@ -27,8 +27,8 @@ export const socialmedia = { url: "https://discord.com/invite/MhXQGCyHd9", }, twitter: { - icon: , - url: "https://twitter.com/kleros_io", + icon: , + url: "https://x.com/kleros_io", }, reddit: { icon: , diff --git a/web/src/hooks/useWindowWidth.tsx b/web/src/hooks/useWindowWidth.tsx new file mode 100644 index 000000000..ff74a14ba --- /dev/null +++ b/web/src/hooks/useWindowWidth.tsx @@ -0,0 +1,19 @@ +import { useState, useEffect } from "react"; + +export const useWindowWidth = () => { + const [windowWidth, setWindowWidth] = useState(window.innerWidth); + + useEffect(() => { + const handleResize = () => { + setWindowWidth(window.innerWidth); + }; + + window.addEventListener("resize", handleResize); + + return () => { + window.removeEventListener("resize", handleResize); + }; + }, []); + + return windowWidth; +}; diff --git a/web/src/layout/Footer/index.tsx b/web/src/layout/Footer/index.tsx index fe5bc92d8..c51376b9c 100644 --- a/web/src/layout/Footer/index.tsx +++ b/web/src/layout/Footer/index.tsx @@ -1,18 +1,28 @@ import React from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; +import { smallScreenStyle } from "styles/smallScreenStyle"; import SecuredByKlerosLogo from "svgs/footer/secured-by-kleros.svg"; import { socialmedia } from "consts/socialmedia"; const Container = styled.div` - height: 80px; + height: 64px; width: 100%; background-color: ${({ theme }) => theme.primaryPurple}; display: flex; - flex-direction: column; + flex-direction: row; + justify-content: space-between; align-items: center; - justify-content: center; + padding: 0 32px; gap: 16px; + ${smallScreenStyle( + () => css` + height: 80px; + flex-direction: column; + justify-content: center; + ` + )} + .secured-by-kleros { min-height: 24px; } diff --git a/web/src/layout/Header/index.tsx b/web/src/layout/Header/index.tsx index e4c0b61d0..4c0d163b4 100644 --- a/web/src/layout/Header/index.tsx +++ b/web/src/layout/Header/index.tsx @@ -1,10 +1,17 @@ import React, { useState, useRef, useContext } from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; +import { useToggle } from "react-use"; +import { smallScreenStyle } from "styles/smallScreenStyle"; import { Link } from "react-router-dom"; import HamburgerIcon from "svgs/header/hamburger.svg"; +import KlerosSolutionsIcon from "svgs/menu-icons/kleros-solutions.svg"; import KlerosCourtLogo from "svgs/header/kleros-court.svg"; import LightButton from "components/LightButton"; +import ConnectWallet from "components/ConnectWallet"; import NavBar from "./navbar"; +import DappList from "./navbar/DappList"; +import Explore from "./navbar/Explore"; +import Menu from "./navbar/Menu"; import { useFocusOutside } from "hooks/useFocusOutside"; const Container = styled.div` @@ -17,23 +24,88 @@ const Container = styled.div` padding: 0 24px; display: flex; - align-items: center; - justify-content: space-between; .kleros-court-link { min-height: 48px; } `; -const StyledLightButton = styled(LightButton)` - padding: 0; +const MobileNavBar = styled.div` + display: none; + ${smallScreenStyle( + () => css` + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + ` + )} +`; + +const DesktopNavBar = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + position: relative; + + ${smallScreenStyle( + () => css` + display: none; + ` + )}; +`; + +const LeftSide = styled.div` + display: flex; +`; + +const MiddleSide = styled.div` + display: flex; + transform: translateX(50%); + color: ${({ theme }) => theme.white} !important; +`; - .button-svg { - margin-right: 0px; - fill: white; +const RightSide = styled.div` + display: flex; + gap: 16px; + + canvas { + width: 20px; } - .button-text { - display: none; +`; + +const StyledLightButton = styled(LightButton)` + ${smallScreenStyle( + () => css` + padding: 0; + + .button-svg { + margin-right: 0px; + fill: white; + } + .button-text { + display: none; + } + ` + )} +`; + +const LightButtonContainer = styled.div` + display: flex; + align-items: center; + width: 16px; + margin-left: calc(4px + (8 - 4) * ((100vw - 375px) / (1250 - 375))); + margin-right: calc(12px + (16 - 12) * ((100vw - 375px) / (1250 - 375))); +`; + +const StyledKlerosSolutionsIcon = styled(KlerosSolutionsIcon)` + fill: ${({ theme }) => theme.white} !important; +`; + +const ConnectWalletContainer = styled.div` + label { + color: ${({ theme }) => theme.white}; } `; @@ -50,19 +122,49 @@ export function useOpenContext() { const Header: React.FC = () => { const [isOpen, setIsOpen] = useState(false); + const [isSolutionsOpen, toggleSolution] = useToggle(false); const toggleIsOpen = () => setIsOpen(!isOpen); const containerRef = useRef(null); useFocusOutside(containerRef, () => setIsOpen(false)); return ( - - - -
+ + + + { + toggleSolution(); + }} + Icon={StyledKlerosSolutionsIcon} + /> + + {isSolutionsOpen && } + + + + + + + + + + + + + + + + + + + + + -
+
); diff --git a/web/src/layout/Header/navbar/DappList.tsx b/web/src/layout/Header/navbar/DappList.tsx index 81c69a38b..c5c9bb733 100644 --- a/web/src/layout/Header/navbar/DappList.tsx +++ b/web/src/layout/Header/navbar/DappList.tsx @@ -1,5 +1,7 @@ import React, { useRef } from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; +import { useLockBodyScroll } from "react-use"; +import { smallScreenStyle } from "styles/smallScreenStyle"; import { useFocusOutside } from "hooks/useFocusOutside"; import Curate from "svgs/icons/curate-image.png"; import Resolver from "svgs/icons/dispute-resolver.svg"; @@ -25,7 +27,7 @@ const Container = styled.div` display: flex; position: absolute; max-height: 60vh; - top: 5%; + top: 140%; left: 50%; transform: translate(-50%); z-index: 10; @@ -43,6 +45,12 @@ const Container = styled.div` svg { visibility: visible; } + + ${smallScreenStyle( + () => css` + top: 5%; + ` + )} `; const ItemsDiv = styled.div` @@ -110,6 +118,7 @@ const DappList: React.FC = ({ toggleSolution }) => { useFocusOutside(containerRef, () => { toggleSolution(); }); + useLockBodyScroll(true); return ( <> diff --git a/web/src/layout/Header/navbar/Explore.tsx b/web/src/layout/Header/navbar/Explore.tsx index 87cf63d12..742bf623d 100644 --- a/web/src/layout/Header/navbar/Explore.tsx +++ b/web/src/layout/Header/navbar/Explore.tsx @@ -1,20 +1,50 @@ import React from "react"; -import styled from "styled-components"; -import { Link } from "react-router-dom"; +import styled, { css } from "styled-components"; +import { smallScreenStyle } from "styles/smallScreenStyle"; +import { Link, useLocation } from "react-router-dom"; import { useOpenContext } from "../index"; -const Container = styled.div``; +const Container = styled.div` + display: flex; + flex-direction: row; + gap: calc(4px + (16 - 4) * ((100vw - 375px) / (1250 - 375))); + ${smallScreenStyle( + () => css` + flex-direction: column; + gap: 0px; + ` + )}; +`; const LinkContainer = styled.div` - min-height: 32px; display: flex; - align-items: center; - .sm-link { - color: ${({ theme }) => theme.primaryText}; + color: ${({ theme }) => theme.white}; text-decoration: none; font-size: 16px; + &.active-link { + font-weight: 600; + } } + ${smallScreenStyle( + () => css` + min-height: 32px; + display: flex; + align-items: center; + .sm-link { + color: ${({ theme }) => theme.primaryText}; + } + ` + )}; +`; + +const Title = styled.h1` + display: none; + ${smallScreenStyle( + () => css` + display: block; + ` + )}; `; const links = [ @@ -24,13 +54,19 @@ const links = [ ]; const Explore: React.FC = () => { + const location = useLocation(); const { toggleIsOpen } = useOpenContext(); + return ( -

Explore

+ Explore {links.map(({ to, text }) => ( - + {text} diff --git a/web/src/layout/Header/navbar/Menu/Help.tsx b/web/src/layout/Header/navbar/Menu/Help.tsx index 1559d6b68..4777babc4 100644 --- a/web/src/layout/Header/navbar/Menu/Help.tsx +++ b/web/src/layout/Header/navbar/Menu/Help.tsx @@ -1,5 +1,7 @@ import React, { useRef } from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; +import { useLockBodyScroll } from "react-use"; +import { smallScreenStyle } from "styles/smallScreenStyle"; import { useFocusOutside } from "hooks/useFocusOutside"; import Book from "svgs/icons/book-open.svg"; import Guide from "svgs/icons/book.svg"; @@ -13,7 +15,7 @@ const Container = styled.div` display: flex; flex-direction: column; position: absolute; - top: 5%; + top: 140%; left: 50%; transform: translate(-50%); z-index: 10; @@ -23,6 +25,12 @@ const Container = styled.div` background-color: ${({ theme }) => theme.whiteBackground}; border-radius: 3px; box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.06); + + ${smallScreenStyle( + () => css` + top: 5%; + ` + )} `; const ListItem = styled.a` @@ -91,6 +99,7 @@ const Help: React.FC = ({ toggle }) => { useFocusOutside(containerRef, () => { toggle(); }); + useLockBodyScroll(true); return ( <> diff --git a/web/src/layout/Header/navbar/Menu/Settings/index.tsx b/web/src/layout/Header/navbar/Menu/Settings/index.tsx index a6bf761d0..3c4ea3957 100644 --- a/web/src/layout/Header/navbar/Menu/Settings/index.tsx +++ b/web/src/layout/Header/navbar/Menu/Settings/index.tsx @@ -1,5 +1,7 @@ import React, { Dispatch, SetStateAction, useRef, useState } from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; +import { useLockBodyScroll } from "react-use"; +import { smallScreenStyle } from "styles/smallScreenStyle"; import { Tabs } from "@kleros/ui-components-library"; import General from "./General"; import SendMeNotifications from "./SendMeNotifications"; @@ -15,9 +17,15 @@ const Container = styled.div` border: 1px solid ${({ theme }) => theme.stroke}; border-radius: 3px; overflow-y: auto; - top: 5%; + top: 140%; left: 50%; transform: translateX(-50%); + + ${smallScreenStyle( + () => css` + top: 5%; + ` + )} `; const StyledSettingsText = styled.div` @@ -52,6 +60,7 @@ const Settings: React.FC = ({ setIsSettingsOpen }) => { const [currentTab, setCurrentTab] = useState(0); const containerRef = useRef(null); useFocusOutside(containerRef, () => setIsSettingsOpen(false)); + useLockBodyScroll(true); return ( <> diff --git a/web/src/layout/Header/navbar/Menu/index.tsx b/web/src/layout/Header/navbar/Menu/index.tsx index 2886c7c66..a204ac6a6 100644 --- a/web/src/layout/Header/navbar/Menu/index.tsx +++ b/web/src/layout/Header/navbar/Menu/index.tsx @@ -1,5 +1,6 @@ import React, { useState } from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; +import { BREAKPOINT_SMALL_SCREEN, smallScreenStyle } from "styles/smallScreenStyle"; import { useToggle } from "react-use"; import LightButton from "components/LightButton"; import Help from "./Help"; @@ -10,37 +11,74 @@ import NotificationsIcon from "svgs/menu-icons/notifications.svg"; import SettingsIcon from "svgs/menu-icons/settings.svg"; import Settings from "./Settings"; import { useToggleTheme } from "hooks/useToggleThemeContext"; +import { useWindowWidth } from "hooks/useWindowWidth"; -const Container = styled.div``; +const Container = styled.div` + display: flex; + flex-direction: row; + gap: 8px; + ${smallScreenStyle( + () => css` + flex-direction: column; + gap: 0px; + ` + )} +`; const ButtonContainer = styled.div` min-height: 32px; display: flex; align-items: center; + + button { + padding: 0px; + } + + .button-svg { + fill: ${({ theme }) => theme.white}; + } + + ${smallScreenStyle( + () => css` + .button-svg { + fill: ${({ theme }) => theme.secondaryPurple}; + } + ` + )} `; +const getThemeButtonText = (isScreenBig: boolean, isLightTheme: boolean): string => { + if (isScreenBig) { + return ""; + } + return isLightTheme ? "Dark Mode" : "Light Mode"; +}; + const Menu: React.FC = () => { const [theme, toggleTheme] = useToggleTheme(); - const [isHelpOpen, toggleIsHelpOpen] = useToggle(true); + const [isHelpOpen, toggleIsHelpOpen] = useToggle(false); const [isSettingsOpen, setIsSettingsOpen] = useState(false); + const windowWidth = useWindowWidth(); const isLightTheme = theme === "light"; + const isScreenBig = windowWidth > BREAKPOINT_SMALL_SCREEN; + const buttons = [ - { text: "Notifications", Icon: NotificationsIcon }, + { text: isScreenBig ? "" : "Notifications", Icon: NotificationsIcon }, { - text: "Settings", + text: isScreenBig ? "" : "Settings", Icon: SettingsIcon, onClick: () => setIsSettingsOpen(true), }, { - text: "Help", + text: isScreenBig ? "" : "Help", Icon: HelpIcon, onClick: () => { toggleIsHelpOpen(); }, }, { - text: `${isLightTheme ? "Dark" : "Light"} Mode`, + text: getThemeButtonText(isScreenBig, isLightTheme), Icon: isLightTheme ? DarkModeIcon : LightModeIcon, onClick: () => toggleTheme(), }, @@ -49,7 +87,7 @@ const Menu: React.FC = () => { return ( {buttons.map(({ text, Icon, onClick }) => ( - + ))} diff --git a/web/src/layout/Header/navbar/index.tsx b/web/src/layout/Header/navbar/index.tsx index 684a36ebf..fbd82f302 100644 --- a/web/src/layout/Header/navbar/index.tsx +++ b/web/src/layout/Header/navbar/index.tsx @@ -1,5 +1,6 @@ import React from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; +import { smallScreenStyle } from "styles/smallScreenStyle"; import { useLockBodyScroll, useToggle } from "react-use"; import ConnectWallet from "components/ConnectWallet"; import LightButton from "components/LightButton"; @@ -11,27 +12,32 @@ import Menu from "./Menu"; import Debug from "./Debug"; const Container = styled.div<{ isOpen: boolean }>` - position: absolute; - top: 64px; - left: 0; - right: 0; - z-index: 1; - background-color: ${({ theme }) => theme.whiteBackground}; - border: 1px solid ${({ theme }) => theme.stroke}; - box-shadow: 0px 2px 3px ${({ theme }) => theme.defaultShadow}; + ${({ isOpen }) => + smallScreenStyle( + () => css` + position: absolute; + top: 64px; + left: 0; + right: 0; + z-index: 1; + background-color: ${({ theme }) => theme.whiteBackground}; + border: 1px solid ${({ theme }) => theme.stroke}; + box-shadow: 0px 2px 3px ${({ theme }) => theme.defaultShadow}; - transform-origin: top; - transform: scaleY(${({ isOpen }) => (isOpen ? "1" : "0")}); - visibility: ${({ isOpen }) => (isOpen ? "visible" : "hidden")}; - transition-property: transform, visibility; - transition-duration: ${({ theme }) => theme.transitionSpeed}; - transition-timing-function: ease; + transform-origin: top; + transform: scaleY(${isOpen ? "1" : "0"}); + visibility: ${isOpen ? "visible" : "hidden"}; + transition-property: transform, visibility; + transition-duration: ${({ theme }) => theme.transitionSpeed}; + transition-timing-function: ease; - padding: 24px; + padding: 24px; - hr { - margin: 24px 0; - } + hr { + margin: 24px 0; + } + ` + )} `; const NavBar: React.FC = () => { diff --git a/web/src/pages/Home/Header.tsx b/web/src/pages/Home/Header.tsx index 05c825635..bd0f44e92 100644 --- a/web/src/pages/Home/Header.tsx +++ b/web/src/pages/Home/Header.tsx @@ -1,22 +1,18 @@ import React from "react"; import { useTheme } from "styled-components"; -import { useMeasure } from "react-use"; import { BREAKPOINT_SMALL_SCREEN } from "styles/smallScreenStyle"; import HeaderLightMobile from "tsx:svgs/header/header-lightmode-mobile.svg"; import HeaderDarkMobile from "tsx:svgs/header/header-darkmode-mobile.svg"; import HeaderLightDesktop from "tsx:svgs/header/header-lightmode-desktop.svg"; import HeaderDarkDesktop from "tsx:svgs/header/header-darkmode-desktop.svg"; +import { useWindowWidth } from "hooks/useWindowWidth"; const Header = () => { - const [ref, { width }] = useMeasure(); + const windowWidth = useWindowWidth(); const theme = useTheme(); const themeIsLight = theme.name === "light"; - const screenIsBig = width > BREAKPOINT_SMALL_SCREEN; - return ( -
- {screenIsBig ? : } -
- ); + const screenIsBig = windowWidth > BREAKPOINT_SMALL_SCREEN; + return
{screenIsBig ? : }
; }; const HeaderDesktop: React.FC<{ themeIsLight: boolean }> = ({ themeIsLight }) => { diff --git a/web/src/styles/smallScreenStyle.ts b/web/src/styles/smallScreenStyle.ts index 10ee1e008..a45819f2e 100644 --- a/web/src/styles/smallScreenStyle.ts +++ b/web/src/styles/smallScreenStyle.ts @@ -1,9 +1,9 @@ -import { css, FlattenSimpleInterpolation } from "styled-components"; +import { css, DefaultTheme, FlattenInterpolation, ThemeProps } from "styled-components"; -export const BREAKPOINT_SMALL_SCREEN = 768; +export const BREAKPOINT_SMALL_SCREEN = 1000; -export const smallScreenStyle = (style: FlattenSimpleInterpolation) => css` +export const smallScreenStyle = (styleFn: () => FlattenInterpolation>) => css` @media (max-width: ${BREAKPOINT_SMALL_SCREEN}px) { - ${style} + ${() => styleFn()} } `; diff --git a/web/src/styles/themes.ts b/web/src/styles/themes.ts index 75a073ffe..df8027c4b 100644 --- a/web/src/styles/themes.ts +++ b/web/src/styles/themes.ts @@ -3,6 +3,7 @@ import { lightTheme as componentsLightTheme, darkTheme as componentsDarkTheme } export const lightTheme = { ...componentsLightTheme, name: "light", + white: "#FFFFFF", primaryPurple: "#4D00B4", secondaryPurple: "#9013FE", mediumPurple: "#F8F1FF", @@ -43,6 +44,7 @@ export const lightTheme = { export const darkTheme = { ...componentsDarkTheme, name: "dark", + white: "#FFFFFF", primaryPurple: "#7E1BD4", secondaryPurple: "#B45FFF", mediumPurple: "#390F6C", From 9db8b0f3c104673774f8f6aafb07c1e53d366b3b Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Sat, 2 Sep 2023 23:22:45 +0200 Subject: [PATCH 04/38] fix(web): better code structure, optimizations, community section, popups below buttons in desktop --- web/src/consts/socialmedia.tsx | 2 +- web/src/layout/Header/DesktopHeader.tsx | 100 +++++++++++ web/src/layout/Header/MobileHeader.tsx | 66 ++++++++ web/src/layout/Header/index.tsx | 156 +----------------- web/src/layout/Header/navbar/DappList.tsx | 6 +- web/src/layout/Header/navbar/Explore.tsx | 2 +- web/src/layout/Header/navbar/Menu/Help.tsx | 11 +- .../Header/navbar/Menu/Settings/index.tsx | 9 +- web/src/layout/Header/navbar/Menu/index.tsx | 28 ++-- web/src/layout/Header/navbar/index.tsx | 2 +- web/src/pages/Home/Community/index.tsx | 46 +++++- 11 files changed, 239 insertions(+), 189 deletions(-) create mode 100644 web/src/layout/Header/DesktopHeader.tsx create mode 100644 web/src/layout/Header/MobileHeader.tsx diff --git a/web/src/consts/socialmedia.tsx b/web/src/consts/socialmedia.tsx index 62d82b57e..749e11396 100644 --- a/web/src/consts/socialmedia.tsx +++ b/web/src/consts/socialmedia.tsx @@ -26,7 +26,7 @@ export const socialmedia = { icon: , url: "https://discord.com/invite/MhXQGCyHd9", }, - twitter: { + x: { icon: , url: "https://x.com/kleros_io", }, diff --git a/web/src/layout/Header/DesktopHeader.tsx b/web/src/layout/Header/DesktopHeader.tsx new file mode 100644 index 000000000..e1d013616 --- /dev/null +++ b/web/src/layout/Header/DesktopHeader.tsx @@ -0,0 +1,100 @@ +import React from "react"; +import styled, { css } from "styled-components"; +import { useToggle } from "react-use"; +import { Link } from "react-router-dom"; +import { smallScreenStyle } from "styles/smallScreenStyle"; +import KlerosSolutionsIcon from "svgs/menu-icons/kleros-solutions.svg"; +import KlerosCourtLogo from "svgs/header/kleros-court.svg"; +import ConnectWallet from "components/ConnectWallet"; +import LightButton from "components/LightButton"; +import DappList from "./navbar/DappList"; +import Explore from "./navbar/Explore"; +import Menu from "./navbar/Menu"; + +const Container = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + position: relative; + + ${smallScreenStyle( + () => css` + display: none; + ` + )}; +`; + +const LeftSide = styled.div` + display: flex; +`; + +const MiddleSide = styled.div` + position: absolute; + left: 50%; + transform: translateX(-50%); + display: flex; + color: ${({ theme }) => theme.white} !important; +`; + +const RightSide = styled.div` + display: flex; + gap: 16px; + + canvas { + width: 20px; + } +`; + +const LightButtonContainer = styled.div` + display: flex; + align-items: center; + width: 16px; + margin-left: calc(4px + (8 - 4) * ((100vw - 375px) / (1250 - 375))); + margin-right: calc(12px + (16 - 12) * ((100vw - 375px) / (1250 - 375))); +`; + +const StyledKlerosSolutionsIcon = styled(KlerosSolutionsIcon)` + fill: ${({ theme }) => theme.white} !important; +`; + +const ConnectWalletContainer = styled.div` + label { + color: ${({ theme }) => theme.white}; + } +`; + +const DesktopHeader = () => { + const [isSolutionsOpen, toggleSolution] = useToggle(false); + return ( + + + + { + toggleSolution(); + }} + Icon={StyledKlerosSolutionsIcon} + /> + + {isSolutionsOpen && } + + + + + + + + + + + + + + + + + ); +}; +export default DesktopHeader; diff --git a/web/src/layout/Header/MobileHeader.tsx b/web/src/layout/Header/MobileHeader.tsx new file mode 100644 index 000000000..eae620d51 --- /dev/null +++ b/web/src/layout/Header/MobileHeader.tsx @@ -0,0 +1,66 @@ +import React, { useContext, useRef, useState } from "react"; +import styled, { css } from "styled-components"; +import { smallScreenStyle } from "styles/smallScreenStyle"; +import { Link } from "react-router-dom"; +import KlerosCourtLogo from "svgs/header/kleros-court.svg"; +import HamburgerIcon from "svgs/header/hamburger.svg"; +import LightButton from "components/LightButton"; +import NavBar from "./navbar"; +import { useFocusOutside } from "hooks/useFocusOutside"; + +const Container = styled.div` + display: none; + ${smallScreenStyle( + () => css` + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + ` + )} +`; + +const StyledLightButton = styled(LightButton)` + ${smallScreenStyle( + () => css` + padding: 0; + + .button-svg { + margin-right: 0px; + fill: white; + } + .button-text { + display: none; + } + ` + )} +`; + +const OpenContext = React.createContext({ + isOpen: false, + toggleIsOpen: () => { + // Placeholder + }, +}); +export function useOpenContext() { + return useContext(OpenContext); +} + +const MobileHeader = () => { + const [isOpen, setIsOpen] = useState(false); + const toggleIsOpen = () => setIsOpen(!isOpen); + const containerRef = useRef(null); + useFocusOutside(containerRef, () => setIsOpen(false)); + return ( + + + + + + + + + + ); +}; +export default MobileHeader; diff --git a/web/src/layout/Header/index.tsx b/web/src/layout/Header/index.tsx index 29a484495..498920263 100644 --- a/web/src/layout/Header/index.tsx +++ b/web/src/layout/Header/index.tsx @@ -1,18 +1,7 @@ -import React, { useState, useRef, useContext } from "react"; -import styled, { css } from "styled-components"; -import { useToggle } from "react-use"; -import { smallScreenStyle } from "styles/smallScreenStyle"; -import { Link } from "react-router-dom"; -import HamburgerIcon from "svgs/header/hamburger.svg"; -import KlerosSolutionsIcon from "svgs/menu-icons/kleros-solutions.svg"; -import KlerosCourtLogo from "svgs/header/kleros-court.svg"; -import LightButton from "components/LightButton"; -import ConnectWallet from "components/ConnectWallet"; -import NavBar from "./navbar"; -import DappList from "./navbar/DappList"; -import Explore from "./navbar/Explore"; -import Menu from "./navbar/Menu"; -import { useFocusOutside } from "hooks/useFocusOutside"; +import React from "react"; +import styled from "styled-components"; +import MobileHeader from "./MobileHeader"; +import DesktopHeader from "./DesktopHeader"; const Container = styled.div` position: sticky; @@ -30,144 +19,11 @@ const Container = styled.div` } `; -const MobileNavBar = styled.div` - display: none; - ${smallScreenStyle( - () => css` - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - ` - )} -`; - -const DesktopNavBar = styled.div` - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - position: relative; - - ${smallScreenStyle( - () => css` - display: none; - ` - )}; -`; - -const LeftSide = styled.div` - display: flex; -`; - -const MiddleSide = styled.div` - position: absolute; - left: 50%; - transform: translateX(-50%); - display: flex; - color: ${({ theme }) => theme.white} !important; -`; - -const RightSide = styled.div` - display: flex; - gap: 16px; - - canvas { - width: 20px; - } -`; - -const StyledLightButton = styled(LightButton)` - ${smallScreenStyle( - () => css` - padding: 0; - - .button-svg { - margin-right: 0px; - fill: white; - } - .button-text { - display: none; - } - ` - )} -`; - -const LightButtonContainer = styled.div` - display: flex; - align-items: center; - width: 16px; - margin-left: calc(4px + (8 - 4) * ((100vw - 375px) / (1250 - 375))); - margin-right: calc(12px + (16 - 12) * ((100vw - 375px) / (1250 - 375))); -`; - -const StyledKlerosSolutionsIcon = styled(KlerosSolutionsIcon)` - fill: ${({ theme }) => theme.white} !important; -`; - -const ConnectWalletContainer = styled.div` - label { - color: ${({ theme }) => theme.white}; - } -`; - -const OpenContext = React.createContext({ - isOpen: false, - toggleIsOpen: () => { - // Placeholder - }, -}); - -export function useOpenContext() { - return useContext(OpenContext); -} - const Header: React.FC = () => { - const [isOpen, setIsOpen] = useState(false); - const [isSolutionsOpen, toggleSolution] = useToggle(false); - const toggleIsOpen = () => setIsOpen(!isOpen); - const containerRef = useRef(null); - useFocusOutside(containerRef, () => setIsOpen(false)); return ( - - - - - { - toggleSolution(); - }} - Icon={StyledKlerosSolutionsIcon} - /> - - {isSolutionsOpen && } - - - - - - - - - - - - - - - - - - - - - - - - - + + ); }; diff --git a/web/src/layout/Header/navbar/DappList.tsx b/web/src/layout/Header/navbar/DappList.tsx index c5c9bb733..6182e643d 100644 --- a/web/src/layout/Header/navbar/DappList.tsx +++ b/web/src/layout/Header/navbar/DappList.tsx @@ -27,9 +27,7 @@ const Container = styled.div` display: flex; position: absolute; max-height: 60vh; - top: 140%; - left: 50%; - transform: translate(-50%); + top: 50%; z-index: 10; flex-direction: column; align-items: center; @@ -49,6 +47,8 @@ const Container = styled.div` ${smallScreenStyle( () => css` top: 5%; + left: 50%; + transform: translateX(-50%); ` )} `; diff --git a/web/src/layout/Header/navbar/Explore.tsx b/web/src/layout/Header/navbar/Explore.tsx index 742bf623d..60c0959aa 100644 --- a/web/src/layout/Header/navbar/Explore.tsx +++ b/web/src/layout/Header/navbar/Explore.tsx @@ -2,7 +2,7 @@ import React from "react"; import styled, { css } from "styled-components"; import { smallScreenStyle } from "styles/smallScreenStyle"; import { Link, useLocation } from "react-router-dom"; -import { useOpenContext } from "../index"; +import { useOpenContext } from "../MobileHeader"; const Container = styled.div` display: flex; diff --git a/web/src/layout/Header/navbar/Menu/Help.tsx b/web/src/layout/Header/navbar/Menu/Help.tsx index 4777babc4..8bf0c8fa1 100644 --- a/web/src/layout/Header/navbar/Menu/Help.tsx +++ b/web/src/layout/Header/navbar/Menu/Help.tsx @@ -15,10 +15,10 @@ const Container = styled.div` display: flex; flex-direction: column; position: absolute; - top: 140%; - left: 50%; - transform: translate(-50%); - z-index: 10; + width: 240px; + top: 50%; + transform: translateX(-50%); + z-index: 1; padding: 27px 10px; gap: 23px; border: 1px solid ${({ theme }) => theme.stroke}; @@ -29,6 +29,9 @@ const Container = styled.div` ${smallScreenStyle( () => css` top: 5%; + left: 50%; + transform: translateX(-50%); + width: auto; ` )} `; diff --git a/web/src/layout/Header/navbar/Menu/Settings/index.tsx b/web/src/layout/Header/navbar/Menu/Settings/index.tsx index 3c4ea3957..a0c68e86c 100644 --- a/web/src/layout/Header/navbar/Menu/Settings/index.tsx +++ b/web/src/layout/Header/navbar/Menu/Settings/index.tsx @@ -11,19 +11,20 @@ import { Overlay } from "components/Overlay"; const Container = styled.div` display: flex; position: absolute; + flex-direction: column; + top: 50%; + transform: translateX(-75%); z-index: 1; background-color: ${({ theme }) => theme.whiteBackground}; - flex-direction: column; border: 1px solid ${({ theme }) => theme.stroke}; border-radius: 3px; overflow-y: auto; - top: 140%; - left: 50%; - transform: translateX(-50%); ${smallScreenStyle( () => css` top: 5%; + left: 50%; + transform: translateX(-50%); ` )} `; diff --git a/web/src/layout/Header/navbar/Menu/index.tsx b/web/src/layout/Header/navbar/Menu/index.tsx index a204ac6a6..517a764b8 100644 --- a/web/src/layout/Header/navbar/Menu/index.tsx +++ b/web/src/layout/Header/navbar/Menu/index.tsx @@ -1,6 +1,6 @@ import React, { useState } from "react"; import styled, { css } from "styled-components"; -import { BREAKPOINT_SMALL_SCREEN, smallScreenStyle } from "styles/smallScreenStyle"; +import { smallScreenStyle } from "styles/smallScreenStyle"; import { useToggle } from "react-use"; import LightButton from "components/LightButton"; import Help from "./Help"; @@ -11,7 +11,6 @@ import NotificationsIcon from "svgs/menu-icons/notifications.svg"; import SettingsIcon from "svgs/menu-icons/settings.svg"; import Settings from "./Settings"; import { useToggleTheme } from "hooks/useToggleThemeContext"; -import { useWindowWidth } from "hooks/useWindowWidth"; const Container = styled.div` display: flex; @@ -34,6 +33,10 @@ const ButtonContainer = styled.div` padding: 0px; } + .button-text { + display: none; + } + .button-svg { fill: ${({ theme }) => theme.white}; } @@ -43,42 +46,35 @@ const ButtonContainer = styled.div` .button-svg { fill: ${({ theme }) => theme.secondaryPurple}; } + .button-text { + display: block; + } ` )} `; -const getThemeButtonText = (isScreenBig: boolean, isLightTheme: boolean): string => { - if (isScreenBig) { - return ""; - } - return isLightTheme ? "Dark Mode" : "Light Mode"; -}; - const Menu: React.FC = () => { const [theme, toggleTheme] = useToggleTheme(); const [isHelpOpen, toggleIsHelpOpen] = useToggle(false); const [isSettingsOpen, setIsSettingsOpen] = useState(false); - const windowWidth = useWindowWidth(); - const isLightTheme = theme === "light"; - const isScreenBig = windowWidth > BREAKPOINT_SMALL_SCREEN; const buttons = [ - { text: isScreenBig ? "" : "Notifications", Icon: NotificationsIcon }, + { text: "Notifications", Icon: NotificationsIcon }, { - text: isScreenBig ? "" : "Settings", + text: "Settings", Icon: SettingsIcon, onClick: () => setIsSettingsOpen(true), }, { - text: isScreenBig ? "" : "Help", + text: "Help", Icon: HelpIcon, onClick: () => { toggleIsHelpOpen(); }, }, { - text: getThemeButtonText(isScreenBig, isLightTheme), + text: `${isLightTheme ? "Dark" : "Light"} Mode`, Icon: isLightTheme ? DarkModeIcon : LightModeIcon, onClick: () => toggleTheme(), }, diff --git a/web/src/layout/Header/navbar/index.tsx b/web/src/layout/Header/navbar/index.tsx index dc8f48d88..ff6c0f868 100644 --- a/web/src/layout/Header/navbar/index.tsx +++ b/web/src/layout/Header/navbar/index.tsx @@ -6,7 +6,7 @@ import { useAccount } from "wagmi"; import ConnectWallet from "components/ConnectWallet"; import LightButton from "components/LightButton"; import KlerosSolutionsIcon from "svgs/menu-icons/kleros-solutions.svg"; -import { useOpenContext } from "../index"; +import { useOpenContext } from "../MobileHeader"; import DappList from "./DappList"; import Explore from "./Explore"; import Menu from "./Menu"; diff --git a/web/src/pages/Home/Community/index.tsx b/web/src/pages/Home/Community/index.tsx index ccb23d2a1..4fb4cfdf0 100644 --- a/web/src/pages/Home/Community/index.tsx +++ b/web/src/pages/Home/Community/index.tsx @@ -1,5 +1,6 @@ import React from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; +import { smallScreenStyle } from "styles/smallScreenStyle"; import { Card } from "@kleros/ui-components-library"; import { Element } from "./Element"; import { firstSection, secondSection } from "consts/community-elements"; @@ -19,11 +20,35 @@ const StyledSeparator = styled.hr` const Section = styled.div` width: 100%; - padding: 12px; + height: 64px; + padding: 0 32px; display: flex; - flex-direction: column; + flex-direction: row; align-items: center; - gap: 8px; + justify-content: space-between; + + ${smallScreenStyle( + () => css` + flex-direction: column; + justify-content: center; + gap: 8px; + padding: 12px; + height: auto; + ` + )} +`; + +const TwoElementContainer = styled.div` + display: flex; + flex-direction: row; + gap: 48px; + + ${smallScreenStyle( + () => css` + flex-direction: column; + gap: 8px; + ` + )} `; const Community = () => ( @@ -31,14 +56,17 @@ const Community = () => (

Community

- {firstSection.map((element, i) => ( - - ))} + + {firstSection.slice(0, 2).map((element) => ( + + ))} + +
- {secondSection.map((element, i) => ( - + {secondSection.map((element) => ( + ))}
From 0b69de6d2a280320a71725dc912d5997a9eae64d Mon Sep 17 00:00:00 2001 From: nhestrompia Date: Sun, 3 Sep 2023 00:53:10 +0300 Subject: [PATCH 05/38] fix: some layout adjustments --- .../components/ConnectWallet/AccountDisplay.tsx | 16 +++++++++++----- web/src/layout/Header/DesktopHeader.tsx | 6 +++--- web/src/styles/smallScreenStyle.ts | 3 ++- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/web/src/components/ConnectWallet/AccountDisplay.tsx b/web/src/components/ConnectWallet/AccountDisplay.tsx index 28817d660..e170405d6 100644 --- a/web/src/components/ConnectWallet/AccountDisplay.tsx +++ b/web/src/components/ConnectWallet/AccountDisplay.tsx @@ -1,10 +1,10 @@ import React from "react"; import styled, { css } from "styled-components"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import { BREAKPOINT_TABLET_SCREEN, smallScreenStyle } from "styles/smallScreenStyle"; import { useAccount, useNetwork, useEnsAvatar, useEnsName } from "wagmi"; import Identicon from "react-identicons"; import { shortenAddress } from "utils/shortenAddress"; - +import { useWindowWidth } from "~src/hooks/useWindowWidth"; const Container = styled.div` display: flex; flex-direction: row; @@ -133,15 +133,21 @@ export const ChainDisplay: React.FC = () => { }; const AccountDisplay: React.FC = () => { + const windowWidth = useWindowWidth(); + + const screenIsBig = windowWidth > BREAKPOINT_TABLET_SCREEN; + return ( - - - + {screenIsBig && ( + + + + )} ); }; diff --git a/web/src/layout/Header/DesktopHeader.tsx b/web/src/layout/Header/DesktopHeader.tsx index e1d013616..d3260bafa 100644 --- a/web/src/layout/Header/DesktopHeader.tsx +++ b/web/src/layout/Header/DesktopHeader.tsx @@ -30,17 +30,17 @@ const LeftSide = styled.div` `; const MiddleSide = styled.div` + display: flex; position: absolute; left: 50%; transform: translateX(-50%); - display: flex; color: ${({ theme }) => theme.white} !important; `; const RightSide = styled.div` display: flex; - gap: 16px; - + gap: calc(8px + (16 - 8) * ((100vw - 300px) / (1024 - 300))); + margin-left: 8px; canvas { width: 20px; } diff --git a/web/src/styles/smallScreenStyle.ts b/web/src/styles/smallScreenStyle.ts index a45819f2e..9bec90327 100644 --- a/web/src/styles/smallScreenStyle.ts +++ b/web/src/styles/smallScreenStyle.ts @@ -1,6 +1,7 @@ import { css, DefaultTheme, FlattenInterpolation, ThemeProps } from "styled-components"; -export const BREAKPOINT_SMALL_SCREEN = 1000; +export const BREAKPOINT_SMALL_SCREEN = 768; +export const BREAKPOINT_TABLET_SCREEN = 1024; export const smallScreenStyle = (styleFn: () => FlattenInterpolation>) => css` @media (max-width: ${BREAKPOINT_SMALL_SCREEN}px) { From 26e761bfe4dd19d36e19c090b83ef50d67a99f70 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Sun, 3 Sep 2023 02:14:56 +0200 Subject: [PATCH 06/38] fix(web): dont display chain on tablet --- .../ConnectWallet/AccountDisplay.tsx | 24 ++++++++++--------- web/src/styles/smallScreenStyle.ts | 1 - web/src/styles/tabletScreenStyle.ts | 9 +++++++ 3 files changed, 22 insertions(+), 12 deletions(-) create mode 100644 web/src/styles/tabletScreenStyle.ts diff --git a/web/src/components/ConnectWallet/AccountDisplay.tsx b/web/src/components/ConnectWallet/AccountDisplay.tsx index e170405d6..39022e922 100644 --- a/web/src/components/ConnectWallet/AccountDisplay.tsx +++ b/web/src/components/ConnectWallet/AccountDisplay.tsx @@ -1,10 +1,11 @@ import React from "react"; import styled, { css } from "styled-components"; -import { BREAKPOINT_TABLET_SCREEN, smallScreenStyle } from "styles/smallScreenStyle"; +import { smallScreenStyle } from "styles/smallScreenStyle"; +import { tabletScreenStyle } from "styles/tabletScreenStyle"; import { useAccount, useNetwork, useEnsAvatar, useEnsName } from "wagmi"; import Identicon from "react-identicons"; import { shortenAddress } from "utils/shortenAddress"; -import { useWindowWidth } from "~src/hooks/useWindowWidth"; + const Container = styled.div` display: flex; flex-direction: row; @@ -70,9 +71,16 @@ const ChainConnectionContainer = styled.div` background-color: ${({ theme }) => theme.success}; } + ${tabletScreenStyle( + () => css` + display: none; + ` + )} + ${smallScreenStyle( () => css` padding-left: 0px; + display: flex; > label { font-size: 16px; @@ -133,21 +141,15 @@ export const ChainDisplay: React.FC = () => { }; const AccountDisplay: React.FC = () => { - const windowWidth = useWindowWidth(); - - const screenIsBig = windowWidth > BREAKPOINT_TABLET_SCREEN; - return ( - {screenIsBig && ( - - - - )} + + + ); }; diff --git a/web/src/styles/smallScreenStyle.ts b/web/src/styles/smallScreenStyle.ts index 9bec90327..fc7c68e19 100644 --- a/web/src/styles/smallScreenStyle.ts +++ b/web/src/styles/smallScreenStyle.ts @@ -1,7 +1,6 @@ import { css, DefaultTheme, FlattenInterpolation, ThemeProps } from "styled-components"; export const BREAKPOINT_SMALL_SCREEN = 768; -export const BREAKPOINT_TABLET_SCREEN = 1024; export const smallScreenStyle = (styleFn: () => FlattenInterpolation>) => css` @media (max-width: ${BREAKPOINT_SMALL_SCREEN}px) { diff --git a/web/src/styles/tabletScreenStyle.ts b/web/src/styles/tabletScreenStyle.ts new file mode 100644 index 000000000..7b1fe25e7 --- /dev/null +++ b/web/src/styles/tabletScreenStyle.ts @@ -0,0 +1,9 @@ +import { css, DefaultTheme, FlattenInterpolation, ThemeProps } from "styled-components"; + +export const BREAKPOINT_TABLET_SCREEN = 1024; + +export const tabletScreenStyle = (styleFn: () => FlattenInterpolation>) => css` + @media (max-width: ${BREAKPOINT_TABLET_SCREEN}px) { + ${() => styleFn()} + } +`; From b810481fd9e15f8207eea239ae0341e00c043060 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Sun, 3 Sep 2023 04:35:40 +0200 Subject: [PATCH 07/38] fix(web): css top property adjustment on navbar popups --- web/src/layout/Header/navbar/DappList.tsx | 2 +- web/src/layout/Header/navbar/Menu/Help.tsx | 2 +- web/src/layout/Header/navbar/Menu/Settings/index.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/web/src/layout/Header/navbar/DappList.tsx b/web/src/layout/Header/navbar/DappList.tsx index 6182e643d..8648e9f08 100644 --- a/web/src/layout/Header/navbar/DappList.tsx +++ b/web/src/layout/Header/navbar/DappList.tsx @@ -27,7 +27,7 @@ const Container = styled.div` display: flex; position: absolute; max-height: 60vh; - top: 50%; + top: 100%; z-index: 10; flex-direction: column; align-items: center; diff --git a/web/src/layout/Header/navbar/Menu/Help.tsx b/web/src/layout/Header/navbar/Menu/Help.tsx index 8bf0c8fa1..c92ca04df 100644 --- a/web/src/layout/Header/navbar/Menu/Help.tsx +++ b/web/src/layout/Header/navbar/Menu/Help.tsx @@ -16,7 +16,7 @@ const Container = styled.div` flex-direction: column; position: absolute; width: 240px; - top: 50%; + top: 100%; transform: translateX(-50%); z-index: 1; padding: 27px 10px; diff --git a/web/src/layout/Header/navbar/Menu/Settings/index.tsx b/web/src/layout/Header/navbar/Menu/Settings/index.tsx index a0c68e86c..69d621f69 100644 --- a/web/src/layout/Header/navbar/Menu/Settings/index.tsx +++ b/web/src/layout/Header/navbar/Menu/Settings/index.tsx @@ -12,7 +12,7 @@ const Container = styled.div` display: flex; position: absolute; flex-direction: column; - top: 50%; + top: 100%; transform: translateX(-75%); z-index: 1; background-color: ${({ theme }) => theme.whiteBackground}; From d0612bc544bdb676f7acd13cf560243a39402fb9 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Mon, 4 Sep 2023 12:44:21 +0200 Subject: [PATCH 08/38] fix(web): dashboard juror info desktop responsive --- .../pages/Dashboard/JurorInfo/JurorRewards.tsx | 2 +- web/src/pages/Dashboard/JurorInfo/index.tsx | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/web/src/pages/Dashboard/JurorInfo/JurorRewards.tsx b/web/src/pages/Dashboard/JurorInfo/JurorRewards.tsx index 57fabfdc8..bf5baf096 100644 --- a/web/src/pages/Dashboard/JurorInfo/JurorRewards.tsx +++ b/web/src/pages/Dashboard/JurorInfo/JurorRewards.tsx @@ -19,7 +19,7 @@ const Container = styled.div` display: flex; flex-direction: column; align-items: flex-start; - width: 100%; + width: auto; `; const tooltipMsg = diff --git a/web/src/pages/Dashboard/JurorInfo/index.tsx b/web/src/pages/Dashboard/JurorInfo/index.tsx index 1628f7c40..7e0714484 100644 --- a/web/src/pages/Dashboard/JurorInfo/index.tsx +++ b/web/src/pages/Dashboard/JurorInfo/index.tsx @@ -1,5 +1,6 @@ import React from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; +import { smallScreenStyle } from "styles/smallScreenStyle"; import { Card as _Card } from "@kleros/ui-components-library"; import Coherency from "./Coherency"; import JurorRewards from "./JurorRewards"; @@ -14,11 +15,18 @@ const Card = styled(_Card)` const Layout = styled.div` display: flex; - flex-direction: column; + flex-direction: row; align-items: center; + justify-content: space-between; gap: 24px; - width: fit-content; - margin: 16px auto; + width: auto; + margin: 16px 32px; + + ${smallScreenStyle( + () => css` + flex-direction: column; + ` + )} `; const JurorInfo: React.FC = () => { From 8cc0eb0cefcbc5dc7b68382563d990a843cf2080 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Mon, 4 Sep 2023 13:38:07 +0200 Subject: [PATCH 09/38] fix(web): make dashboard look less spacew on desktop --- web/src/pages/Dashboard/JurorInfo/index.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/web/src/pages/Dashboard/JurorInfo/index.tsx b/web/src/pages/Dashboard/JurorInfo/index.tsx index 7e0714484..4f2827e9d 100644 --- a/web/src/pages/Dashboard/JurorInfo/index.tsx +++ b/web/src/pages/Dashboard/JurorInfo/index.tsx @@ -17,14 +17,15 @@ const Layout = styled.div` display: flex; flex-direction: row; align-items: center; - justify-content: space-between; - gap: 24px; + justify-content: center; + gap: 48px; width: auto; margin: 16px 32px; ${smallScreenStyle( () => css` flex-direction: column; + gap: 24px; ` )} `; From 4a4e4024ef26f4681b5aa4c80e9e3a53e90c8ec9 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Mon, 4 Sep 2023 19:58:45 +0200 Subject: [PATCH 10/38] fix(web): accurate paddings and distances between components in desktop --- web/src/pages/Cases/index.tsx | 4 +++- web/src/pages/Courts/CourtDetails/Stats.tsx | 12 ++++++++++-- web/src/pages/Courts/CourtDetails/index.tsx | 4 ++-- web/src/pages/Courts/index.tsx | 4 +++- web/src/pages/Dashboard/Courts/index.tsx | 5 ++++- web/src/pages/Dashboard/JurorInfo/JurorRewards.tsx | 13 +++++++------ web/src/pages/Dashboard/JurorInfo/index.tsx | 6 +++++- web/src/pages/Dashboard/index.tsx | 8 +++++++- web/src/pages/Home/Community/index.tsx | 4 ++++ web/src/pages/Home/CourtOverview/Chart.tsx | 2 +- web/src/pages/Home/CourtOverview/Stats.tsx | 2 +- web/src/pages/Home/LatestCases.tsx | 6 +++++- web/src/pages/Home/index.tsx | 4 +++- 13 files changed, 55 insertions(+), 19 deletions(-) diff --git a/web/src/pages/Cases/index.tsx b/web/src/pages/Cases/index.tsx index 86b623fdb..1d8b7242a 100644 --- a/web/src/pages/Cases/index.tsx +++ b/web/src/pages/Cases/index.tsx @@ -9,7 +9,9 @@ const Container = styled.div` width: 100%; min-height: calc(100vh - 144px); background-color: ${({ theme }) => theme.lightBackground}; - padding: 32px; + padding: calc(32px + (132 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-top: calc(32px + (64 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-bottom: calc(64px + (96 - 64) * (min(max(100vw, 375px), 1250px) - 375px) / 875); `; const Cases: React.FC = () => { diff --git a/web/src/pages/Courts/CourtDetails/Stats.tsx b/web/src/pages/Courts/CourtDetails/Stats.tsx index bfc8bfa49..c084b9408 100644 --- a/web/src/pages/Courts/CourtDetails/Stats.tsx +++ b/web/src/pages/Courts/CourtDetails/Stats.tsx @@ -1,5 +1,6 @@ import React from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; +import { smallScreenStyle } from "styles/smallScreenStyle"; import { useParams } from "react-router-dom"; import { useCourtDetails, CourtDetailsQuery } from "queries/useCourtDetails"; import { useCoinPrice } from "hooks/useCoinPrice"; @@ -20,8 +21,15 @@ const StyledCard = styled.div` width: auto; height: fit-content; display: grid; - gap: 32px; + gap: 16px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + padding: calc(0px + (32 - 0) * (min(max(100vw, 375px), 1250px) - 375px) / 875) 0; + + ${smallScreenStyle( + () => css` + gap: 32px; + ` + )} `; interface IStat { diff --git a/web/src/pages/Courts/CourtDetails/index.tsx b/web/src/pages/Courts/CourtDetails/index.tsx index e8a8db7db..5db6a65a8 100644 --- a/web/src/pages/Courts/CourtDetails/index.tsx +++ b/web/src/pages/Courts/CourtDetails/index.tsx @@ -25,10 +25,10 @@ const ButtonContainer = styled.div` `; const StyledCard = styled(Card)` - margin-top: 16px; + margin-top: calc(16px + (24 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); width: 100%; height: auto; - padding: 16px; + padding: calc(16px + (32 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); min-height: 100px; `; diff --git a/web/src/pages/Courts/index.tsx b/web/src/pages/Courts/index.tsx index e9803fd0c..c2f483ce3 100644 --- a/web/src/pages/Courts/index.tsx +++ b/web/src/pages/Courts/index.tsx @@ -8,7 +8,9 @@ const Container = styled.div` width: 100%; min-height: calc(100vh - 144px); background-color: ${({ theme }) => theme.lightBackground}; - padding: 32px; + padding: calc(32px + (132 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-top: calc(32px + (64 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-bottom: calc(64px + (96 - 64) * (min(max(100vw, 375px), 1250px) - 375px) / 875); `; const Courts: React.FC = () => { diff --git a/web/src/pages/Dashboard/Courts/index.tsx b/web/src/pages/Dashboard/Courts/index.tsx index aaa4ed1d0..f6f588060 100644 --- a/web/src/pages/Dashboard/Courts/index.tsx +++ b/web/src/pages/Dashboard/Courts/index.tsx @@ -7,6 +7,10 @@ import { useUserQuery } from "queries/useUser"; const Container = styled.div` margin-top: 64px; + + h1 { + margin-bottom: calc(16px + (48 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + } `; const CourtsContainer = styled.div` @@ -23,7 +27,6 @@ const Courts: React.FC = () => { <>

My Courts

-
{!isUndefined(data) && data.user?.tokens?.map(({ court: { id, name } }) => { diff --git a/web/src/pages/Dashboard/JurorInfo/JurorRewards.tsx b/web/src/pages/Dashboard/JurorInfo/JurorRewards.tsx index bf5baf096..f51c5b515 100644 --- a/web/src/pages/Dashboard/JurorInfo/JurorRewards.tsx +++ b/web/src/pages/Dashboard/JurorInfo/JurorRewards.tsx @@ -9,12 +9,6 @@ import { CoinIds } from "consts/coingecko"; import { useUserQuery, UserQuery } from "queries/useUser"; import { useCoinPrice } from "hooks/useCoinPrice"; -interface IReward { - token: "ETH" | "PNK"; - coinId: number; - getAmount: (amount: bigint) => string; - getValue: (amount: bigint, coinPrice?: number) => string; -} const Container = styled.div` display: flex; flex-direction: column; @@ -28,6 +22,13 @@ const tooltipMsg = "is coherent with the final ruling receive the Juror Rewards composed of " + "arbitration fees (ETH) + PNK redistribution between jurors."; +interface IReward { + token: "ETH" | "PNK"; + coinId: number; + getAmount: (amount: bigint) => string; + getValue: (amount: bigint, coinPrice?: number) => string; +} + const rewards: IReward[] = [ { token: "ETH", diff --git a/web/src/pages/Dashboard/JurorInfo/index.tsx b/web/src/pages/Dashboard/JurorInfo/index.tsx index 4f2827e9d..6e6b9ced8 100644 --- a/web/src/pages/Dashboard/JurorInfo/index.tsx +++ b/web/src/pages/Dashboard/JurorInfo/index.tsx @@ -8,6 +8,10 @@ import JurorRewards from "./JurorRewards"; const Container = styled.div``; +const Header = styled.h1` + margin-bottom: calc(16px + (48 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); +`; + const Card = styled(_Card)` width: 100%; height: auto; @@ -33,7 +37,7 @@ const Layout = styled.div` const JurorInfo: React.FC = () => { return ( -

Juror Dashboard

+
Juror Dashboard
diff --git a/web/src/pages/Dashboard/index.tsx b/web/src/pages/Dashboard/index.tsx index aaf615cec..db14e62e4 100644 --- a/web/src/pages/Dashboard/index.tsx +++ b/web/src/pages/Dashboard/index.tsx @@ -11,11 +11,17 @@ const Container = styled.div` width: 100%; min-height: calc(100vh - 144px); background-color: ${({ theme }) => theme.lightBackground}; - padding: 32px; + padding: calc(32px + (132 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-top: calc(32px + (64 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-bottom: calc(64px + (96 - 64) * (min(max(100vw, 375px), 1250px) - 375px) / 875); `; const StyledCasesDisplay = styled(CasesDisplay)` margin-top: 64px; + + h1 { + margin-bottom: calc(16px + (48 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + } `; const ConnectWalletContainer = styled.div` diff --git a/web/src/pages/Home/Community/index.tsx b/web/src/pages/Home/Community/index.tsx index 4fb4cfdf0..cefb9e9a9 100644 --- a/web/src/pages/Home/Community/index.tsx +++ b/web/src/pages/Home/Community/index.tsx @@ -7,6 +7,10 @@ import { firstSection, secondSection } from "consts/community-elements"; const Container = styled.div` margin-top: 64px; + + h1 { + margin-bottom: calc(16px + (48 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + } `; const StyledCard = styled(Card)` diff --git a/web/src/pages/Home/CourtOverview/Chart.tsx b/web/src/pages/Home/CourtOverview/Chart.tsx index 3e8ac0414..5e48f574c 100644 --- a/web/src/pages/Home/CourtOverview/Chart.tsx +++ b/web/src/pages/Home/CourtOverview/Chart.tsx @@ -7,7 +7,7 @@ import { formatUnits } from "viem"; import { useHomePageContext } from "hooks/useHomePageContext"; const Container = styled.div` - margin-bottom: 32px; + margin-bottom: calc(32px + (48 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); display: flex; flex-direction: column; `; diff --git a/web/src/pages/Home/CourtOverview/Stats.tsx b/web/src/pages/Home/CourtOverview/Stats.tsx index 58c665462..5f17ceeff 100644 --- a/web/src/pages/Home/CourtOverview/Stats.tsx +++ b/web/src/pages/Home/CourtOverview/Stats.tsx @@ -18,7 +18,7 @@ import { useCoinPrice } from "hooks/useCoinPrice"; const StyledCard = styled(Card)` width: auto; height: fit-content; - padding: 16px; + padding: calc(16px + (30 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); display: grid; gap: 32px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); diff --git a/web/src/pages/Home/LatestCases.tsx b/web/src/pages/Home/LatestCases.tsx index d3f9028a6..e471dbf17 100644 --- a/web/src/pages/Home/LatestCases.tsx +++ b/web/src/pages/Home/LatestCases.tsx @@ -5,13 +5,17 @@ import DisputeCard from "components/DisputeCard"; import { StyledSkeleton } from "components/StyledSkeleton"; const Container = styled.div` - margin-top: 64px; + margin-top: calc(64px + (80 - 64) * (min(max(100vw, 375px), 1250px) - 375px) / 875); .disputes-container { display: flex; gap: 24px; flex-wrap: wrap; justify-content: center; } + + h1 { + margin-bottom: calc(16px + (48 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + } `; const LatestCases: React.FC = () => { diff --git a/web/src/pages/Home/index.tsx b/web/src/pages/Home/index.tsx index f78437078..62cd3ada1 100644 --- a/web/src/pages/Home/index.tsx +++ b/web/src/pages/Home/index.tsx @@ -11,7 +11,9 @@ const Container = styled.div` width: 100%; min-height: calc(100vh - 144px); background-color: ${({ theme }) => theme.lightBackground}; - padding: 32px; + padding: calc(32px + (132 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-top: calc(32px + (64 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-bottom: calc(64px + (96 - 64) * (min(max(100vw, 375px), 1250px) - 375px) / 875); `; const Home: React.FC = () => { From 36c736b6739d72985b34c8ee98fb1fec949f317e Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Mon, 4 Sep 2023 20:06:15 +0200 Subject: [PATCH 11/38] fix(web): show some separator in case of not being staked anywhere --- web/src/pages/Dashboard/Courts/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/web/src/pages/Dashboard/Courts/index.tsx b/web/src/pages/Dashboard/Courts/index.tsx index f6f588060..8599c6d38 100644 --- a/web/src/pages/Dashboard/Courts/index.tsx +++ b/web/src/pages/Dashboard/Courts/index.tsx @@ -27,6 +27,7 @@ const Courts: React.FC = () => { <>

My Courts

+ {!isUndefined(data) &&
} {!isUndefined(data) && data.user?.tokens?.map(({ court: { id, name } }) => { From 758807df02089f1f5a1fa4db7f54c369e53af82f Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Tue, 5 Sep 2023 12:36:49 +0200 Subject: [PATCH 12/38] fix(web): community section more tablet responsive --- web/src/pages/Home/Community/Element.tsx | 10 +++++++++- web/src/pages/Home/Community/index.tsx | 4 ++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/web/src/pages/Home/Community/Element.tsx b/web/src/pages/Home/Community/Element.tsx index cc3a2481b..97fb3e637 100644 --- a/web/src/pages/Home/Community/Element.tsx +++ b/web/src/pages/Home/Community/Element.tsx @@ -1,9 +1,11 @@ import React from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; +import { smallScreenStyle } from "styles/smallScreenStyle"; const Container = styled.div` display: flex; gap: 8px; + padding: 16px 32px 16px 0px; svg { width: 16px; @@ -14,6 +16,12 @@ const Container = styled.div` display: flex; gap: 8px; } + + ${smallScreenStyle( + () => css` + padding: 0px; + ` + )} `; const StyledLabel = styled.label` diff --git a/web/src/pages/Home/Community/index.tsx b/web/src/pages/Home/Community/index.tsx index cefb9e9a9..fc5df011f 100644 --- a/web/src/pages/Home/Community/index.tsx +++ b/web/src/pages/Home/Community/index.tsx @@ -24,10 +24,10 @@ const StyledSeparator = styled.hr` const Section = styled.div` width: 100%; - height: 64px; + min-height: 64px; + flex-wrap: wrap; padding: 0 32px; display: flex; - flex-direction: row; align-items: center; justify-content: space-between; From 17009144827e5e462d14f92adb6a6d3a14d12abf Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Tue, 5 Sep 2023 12:43:20 +0200 Subject: [PATCH 13/38] fix(web): bug in desktop view community section --- web/src/pages/Home/Community/Element.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/web/src/pages/Home/Community/Element.tsx b/web/src/pages/Home/Community/Element.tsx index 97fb3e637..cc3a2481b 100644 --- a/web/src/pages/Home/Community/Element.tsx +++ b/web/src/pages/Home/Community/Element.tsx @@ -1,11 +1,9 @@ import React from "react"; -import styled, { css } from "styled-components"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import styled from "styled-components"; const Container = styled.div` display: flex; gap: 8px; - padding: 16px 32px 16px 0px; svg { width: 16px; @@ -16,12 +14,6 @@ const Container = styled.div` display: flex; gap: 8px; } - - ${smallScreenStyle( - () => css` - padding: 0px; - ` - )} `; const StyledLabel = styled.label` From 61bae81fb1be77b5fddba10a8cf65a18900bf020 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Wed, 6 Sep 2023 03:48:12 +0200 Subject: [PATCH 14/38] fix(web): stats paddings adjustments for desktop --- web/src/components/StatDisplay.tsx | 11 ++++++++++- web/src/pages/Courts/CourtDetails/Stats.tsx | 1 + web/src/pages/Home/CourtOverview/Stats.tsx | 13 +++++++++++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/web/src/components/StatDisplay.tsx b/web/src/components/StatDisplay.tsx index 43c929663..d12dc05a0 100644 --- a/web/src/components/StatDisplay.tsx +++ b/web/src/components/StatDisplay.tsx @@ -1,10 +1,19 @@ import React from "react"; -import styled, { useTheme } from "styled-components"; +import { smallScreenStyle } from "styles/smallScreenStyle"; +import styled, { useTheme, css } from "styled-components"; const Container = styled.div` display: flex; + max-width: 196px; align-items: center; gap: 8px; + margin-bottom: calc(16px + (30 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + + ${smallScreenStyle( + () => css` + margin-bottom: 0px; + ` + )} `; const SVGContainer = styled.div<{ iconColor: string; backgroundColor: string }>` diff --git a/web/src/pages/Courts/CourtDetails/Stats.tsx b/web/src/pages/Courts/CourtDetails/Stats.tsx index c084b9408..7771006b1 100644 --- a/web/src/pages/Courts/CourtDetails/Stats.tsx +++ b/web/src/pages/Courts/CourtDetails/Stats.tsx @@ -24,6 +24,7 @@ const StyledCard = styled.div` gap: 16px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); padding: calc(0px + (32 - 0) * (min(max(100vw, 375px), 1250px) - 375px) / 875) 0; + padding-bottom: 0px; ${smallScreenStyle( () => css` diff --git a/web/src/pages/Home/CourtOverview/Stats.tsx b/web/src/pages/Home/CourtOverview/Stats.tsx index 5f17ceeff..160c2b36e 100644 --- a/web/src/pages/Home/CourtOverview/Stats.tsx +++ b/web/src/pages/Home/CourtOverview/Stats.tsx @@ -1,5 +1,6 @@ import React from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; +import { smallScreenStyle } from "styles/smallScreenStyle"; import { Card } from "@kleros/ui-components-library"; import StatDisplay, { IStatDisplay } from "components/StatDisplay"; import { StyledSkeleton } from "components/StyledSkeleton"; @@ -19,9 +20,17 @@ const StyledCard = styled(Card)` width: auto; height: fit-content; padding: calc(16px + (30 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-left: calc(16px + (35 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-bottom: 0px; display: grid; - gap: 32px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + + ${smallScreenStyle( + () => css` + padding-bottom: 16px; + gap: 32px; + ` + )} `; const getLastOrZero = (src: HomePageQuery["counters"], stat: HomePageQueryDataPoints) => From caafd1db048159d219d0420ba886ac88c9531b99 Mon Sep 17 00:00:00 2001 From: nhestrompia Date: Wed, 6 Sep 2023 16:11:50 +0300 Subject: [PATCH 15/38] feat(web): cases-grid-and-list-display --- web/src/app.tsx | 23 +++--- web/src/assets/svgs/icons/grid.svg | 3 + web/src/assets/svgs/icons/list.svg | 3 + web/src/components/CasesDisplay/CasesGrid.tsx | 41 ++++++++-- .../CasesDisplay/CasesListHeader.tsx | 79 +++++++++++++++++++ web/src/components/CasesDisplay/Filters.tsx | 32 ++++++++ .../components/DisputeCard/DisputeInfo.tsx | 37 ++++++--- .../components/DisputeCard/PeriodBanner.tsx | 15 ++-- web/src/components/DisputeCard/index.tsx | 72 ++++++++++++++--- web/src/components/Field.tsx | 17 ++-- web/src/context/FilterProvider.tsx | 25 ++++++ web/src/context/Web3Provider.tsx | 2 +- web/src/hooks/queries/useCasesQuery.ts | 10 +-- web/src/hooks/useWindowWidth.ts | 19 +++++ web/src/pages/Cases/index.tsx | 20 ++++- web/src/styles/tabletScreenStyle.ts | 9 +++ 16 files changed, 345 insertions(+), 62 deletions(-) create mode 100644 web/src/assets/svgs/icons/grid.svg create mode 100644 web/src/assets/svgs/icons/list.svg create mode 100644 web/src/components/CasesDisplay/CasesListHeader.tsx create mode 100644 web/src/context/FilterProvider.tsx create mode 100644 web/src/hooks/useWindowWidth.ts create mode 100644 web/src/styles/tabletScreenStyle.ts diff --git a/web/src/app.tsx b/web/src/app.tsx index f6a705ac6..594489272 100644 --- a/web/src/app.tsx +++ b/web/src/app.tsx @@ -6,6 +6,7 @@ import "react-toastify/dist/ReactToastify.css"; import Web3Provider from "context/Web3Provider"; import QueryClientProvider from "context/QueryClientProvider"; import StyledComponentsProvider from "context/StyledComponentsProvider"; +import { FilterProvider } from "context/FilterProvider"; import RefetchOnBlock from "context/RefetchOnBlock"; import Layout from "layout/index"; import Home from "./pages/Home"; @@ -20,16 +21,18 @@ const App: React.FC = () => { - - }> - } /> - } /> - } /> - } /> - } /> - Justice not found here ¯\_( ͡° ͜ʖ ͡°)_/¯} /> - - + + + }> + } /> + } /> + } /> + } /> + } /> + Justice not found here ¯\_( ͡° ͜ʖ ͡°)_/¯} /> + + + diff --git a/web/src/assets/svgs/icons/grid.svg b/web/src/assets/svgs/icons/grid.svg new file mode 100644 index 000000000..eb3fa4e05 --- /dev/null +++ b/web/src/assets/svgs/icons/grid.svg @@ -0,0 +1,3 @@ + + + diff --git a/web/src/assets/svgs/icons/list.svg b/web/src/assets/svgs/icons/list.svg new file mode 100644 index 000000000..767198a5d --- /dev/null +++ b/web/src/assets/svgs/icons/list.svg @@ -0,0 +1,3 @@ + + + diff --git a/web/src/components/CasesDisplay/CasesGrid.tsx b/web/src/components/CasesDisplay/CasesGrid.tsx index b9e9c9415..7f465ff1e 100644 --- a/web/src/components/CasesDisplay/CasesGrid.tsx +++ b/web/src/components/CasesDisplay/CasesGrid.tsx @@ -1,12 +1,27 @@ import React from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; import { StandardPagination } from "@kleros/ui-components-library"; +import { smallScreenStyle } from "styles/smallScreenStyle"; +import { useFiltersContext } from "context/FilterProvider"; import { CasesPageQuery } from "queries/useCasesQuery"; import DisputeCard from "components/DisputeCard"; +import CasesListHeader from "./CasesListHeader"; -const Container = styled.div` +const GridContainer = styled.div` + display: grid; + gap: 16px; + grid-template-columns: repeat(3, minmax(50px, 1fr)); + justify-content: center; + align-items: center; + gap: 8px; + ${smallScreenStyle(css` + display: flex; + flex-wrap: wrap; + `)} +`; +const ListContainer = styled.div` display: flex; - flex-wrap: wrap; + flex-direction: column; justify-content: center; gap: 8px; `; @@ -26,13 +41,23 @@ export interface ICasesGrid { } const CasesGrid: React.FC = ({ disputes, currentPage, setCurrentPage, numberDisputes, casesPerPage }) => { + const { isList } = useFiltersContext(); return ( <> - - {disputes.map((dispute, i) => { - return ; - })} - + {!isList ? ( + + {disputes.map((dispute, i) => { + return ; + })} + + ) : ( + + {isList && } + {disputes.map((dispute, i) => { + return ; + })} + + )} theme.secondaryText} !important; + } + + ${smallScreenStyle(css` + display: none; + `)} +`; + +const tooltipMsg = + "Users have an economic interest in serving as jurors in Kleros: " + + "collecting the Juror Rewards in exchange for their work. Each juror who " + + "is coherent with the final ruling receive the Juror Rewards composed of " + + "arbitration fees (ETH) + PNK redistribution between jurors."; + +const CasesListHeader: React.FC = () => { + return ( + + + + + + + + Category + + + + + + + + + ); +}; + +export default CasesListHeader; diff --git a/web/src/components/CasesDisplay/Filters.tsx b/web/src/components/CasesDisplay/Filters.tsx index d74c06574..a4b596cd7 100644 --- a/web/src/components/CasesDisplay/Filters.tsx +++ b/web/src/components/CasesDisplay/Filters.tsx @@ -1,6 +1,9 @@ import React from "react"; import styled, { useTheme } from "styled-components"; import { DropdownSelect } from "@kleros/ui-components-library"; +import { useFiltersContext } from "context/FilterProvider"; +import ListIcon from "svgs/icons/list.svg"; +import GridIcon from "svgs/icons/grid.svg"; const Container = styled.div` display: flex; @@ -9,8 +12,33 @@ const Container = styled.div` width: fit-content; `; +const StyledGridIcon = styled(GridIcon)<{ isList: boolean }>` + cursor: pointer; + transition: fill 0.2s ease; + fill: ${({ theme, isList }) => (isList ? theme.secondaryText : theme.primaryBlue)}; + width: 16px; + height: 16px; +`; + +const IconsContainer = styled.div` + display: flex; + justify-content: center; + align-items: center; + gap: 4px; +`; + +const StyledListIcon = styled(ListIcon)<{ isList: boolean }>` + cursor: pointer; + transition: fill 0.2s ease; + fill: ${({ theme, isList }) => (isList ? theme.primaryBlue : theme.secondaryText)}; + width: 16px; + height: 17px; +`; + const Filters: React.FC = () => { const theme = useTheme(); + const { isList, setIsList } = useFiltersContext(); + return ( { defaultValue={0} callback={() => {}} /> + + setIsList(false)} /> + setIsList(true)} /> + ); }; diff --git a/web/src/components/DisputeCard/DisputeInfo.tsx b/web/src/components/DisputeCard/DisputeInfo.tsx index 0b3568097..6ea8f9940 100644 --- a/web/src/components/DisputeCard/DisputeInfo.tsx +++ b/web/src/components/DisputeCard/DisputeInfo.tsx @@ -7,10 +7,14 @@ import LawBalanceIcon from "svgs/icons/law-balance.svg"; import PileCoinsIcon from "svgs/icons/pile-coins.svg"; import Field from "../Field"; -const Container = styled.div` +const Container = styled.div<{ isCard: boolean }>` display: flex; - flex-direction: column; - gap: 8px; + flex-direction: ${({ isCard }) => (isCard ? "column" : "row")}; + gap: ${({ isCard }) => (isCard ? "8px" : "48px")}; + justify-content: ${({ isCard }) => (isCard ? "center" : "space-between")}; + align-items: center; + width: 100%; + height: 100%; `; const getPeriodPhrase = (period: Periods): string => { @@ -33,16 +37,31 @@ export interface IDisputeInfo { rewards?: string; period?: Periods; date?: number; + isCard?: boolean; } -const DisputeInfo: React.FC = ({ courtId, court, category, rewards, period, date }) => { +const formatDate = (date: number) => { + const options: Intl.DateTimeFormatOptions = { year: "numeric", month: "long", day: "numeric" }; + const startingDate = new Date(date * 1000); + const formattedDate = startingDate.toLocaleDateString("en-US", options); + return formattedDate; +}; + +const DisputeInfo: React.FC = ({ courtId, court, category, rewards, period, date, isCard = true }) => { return ( - - {category && } - {court && courtId && } - {rewards && } + + {court && courtId && ( + + )} + {category && } + {rewards && } {typeof period !== "undefined" && date && ( - + )} ); diff --git a/web/src/components/DisputeCard/PeriodBanner.tsx b/web/src/components/DisputeCard/PeriodBanner.tsx index fb8dd3e0a..0ad1ac647 100644 --- a/web/src/components/DisputeCard/PeriodBanner.tsx +++ b/web/src/components/DisputeCard/PeriodBanner.tsx @@ -3,7 +3,7 @@ import styled, { Theme } from "styled-components"; import { Periods } from "consts/periods"; const Container = styled.div>` - height: 45px; + height: ${({ isCard }) => (isCard ? "45px" : "100%")}; width: auto; border-top-right-radius: 3px; border-top-left-radius: 3px; @@ -21,11 +21,11 @@ const Container = styled.div>` margin-right: 8px; } } - ${({ theme, period }) => { + ${({ theme, period, isCard }) => { const [frontColor, backgroundColor] = getPeriodColors(period, theme); return ` - border-top: 5px solid ${frontColor}; - background-color: ${backgroundColor}; + ${isCard ? `border-top: 5px solid ${frontColor}` : `border-left: 5px solid ${frontColor}`}; + ${isCard && `background-color: ${backgroundColor}`}; .front-color { color: ${frontColor}; } @@ -41,6 +41,7 @@ const Container = styled.div>` export interface IPeriodBanner { id: number; period: Periods; + isCard?: boolean; } const getPeriodColors = (period: Periods, theme: Theme): [string, string] => { @@ -65,9 +66,9 @@ const getPeriodLabel = (period: Periods): string => { } }; -const PeriodBanner: React.FC = ({ id, period }) => ( - - +const PeriodBanner: React.FC = ({ id, period, isCard = true }) => ( + + {isCard && } ); diff --git a/web/src/components/DisputeCard/index.tsx b/web/src/components/DisputeCard/index.tsx index 2579d0130..8ecc73562 100644 --- a/web/src/components/DisputeCard/index.tsx +++ b/web/src/components/DisputeCard/index.tsx @@ -5,6 +5,7 @@ import { formatEther } from "viem"; import { StyledSkeleton } from "components/StyledSkeleton"; import { Card } from "@kleros/ui-components-library"; import { Periods } from "consts/periods"; +import { useFiltersContext } from "context/FilterProvider"; import { CasesPageQuery } from "queries/useCasesQuery"; import { useCourtPolicy } from "queries/useCourtPolicy"; import { useDisputeTemplate } from "queries/useDisputeTemplate"; @@ -18,8 +19,13 @@ const StyledCard = styled(Card)` width: auto; height: 260px; `; +const StyledListItem = styled(Card)` + display: flex; + width: 100%; + height: 64px; +`; -const Container = styled.div` +const CardContainer = styled.div` height: 215px; padding: 24px; display: flex; @@ -29,6 +35,25 @@ const Container = styled.div` margin: 0; } `; +const ListContainer = styled.div` + display: flex; + justify-content: space-between; + align-items: flex-start; + gap: 32px; + width: 100%; + margin-right: 2%; + h3 { + margin: 0; + } +`; + +const ListTitle = styled.div` + display: flex; + height: 100%; + justify-content: start; + align-items: center; + min-width: 40vw; +`; export const getPeriodEndTimestamp = ( lastPeriodChange: string, @@ -46,6 +71,7 @@ const DisputeCard: React.FC = ({ lastPeriodChange, court, }) => { + const { isList } = useFiltersContext(); const currentPeriodIndex = Periods[period]; const rewards = `≥ ${formatEther(court.feeForJuror)} ETH`; const date = @@ -63,18 +89,38 @@ const DisputeCard: React.FC = ({ const category = disputeTemplate ? disputeTemplate.category : undefined; const navigate = useNavigate(); return ( - navigate(`/cases/${id.toString()}`)}> - - -

{title}

- -
-
+ <> + {!isList ? ( + navigate(`/cases/${id.toString()}`)}> + + +

{title}

+ +
+
+ ) : ( + navigate(`/cases/${id.toString()}`)}> + + + +

{title}

+
+ +
+
+ )} + ); }; diff --git a/web/src/components/Field.tsx b/web/src/components/Field.tsx index af7b09df8..5c5b92540 100644 --- a/web/src/components/Field.tsx +++ b/web/src/components/Field.tsx @@ -7,9 +7,10 @@ const FieldContainer = styled.div` display: flex; align-items: center; justify-content: flex-start; + white-space: nowrap; .value { flex-grow: 1; - text-align: end; + text-align: ${({ isCard }) => (isCard ? "end" : "center")}; color: ${({ theme }) => theme.primaryText}; } svg { @@ -27,6 +28,7 @@ const FieldContainer = styled.div` type FieldContainerProps = { width?: string; + isCard?: boolean; }; interface IField { @@ -35,12 +37,17 @@ interface IField { value: string; link?: string; width?: string; + isCard?: boolean; } -const Field: React.FC = ({ icon: Icon, name, value, link, width }) => ( - - {} - +const Field: React.FC = ({ icon: Icon, name, value, link, width, isCard = true }) => ( + + {isCard && ( + <> + + + + )} {link ? ( {value} diff --git a/web/src/context/FilterProvider.tsx b/web/src/context/FilterProvider.tsx new file mode 100644 index 000000000..267059c5e --- /dev/null +++ b/web/src/context/FilterProvider.tsx @@ -0,0 +1,25 @@ +import React, { useState, createContext, useContext } from "react"; + +interface IFilters { + isList: boolean; + setIsList: (arg0: boolean) => void; +} + +const Context = createContext({ + isList: false, + setIsList: () => { + // + }, +}); + +export const FilterProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) => { + const [isList, setIsList] = useState(false); + + const value = { + isList, + setIsList, + }; + return {children}; +}; + +export const useFiltersContext = () => useContext(Context); diff --git a/web/src/context/Web3Provider.tsx b/web/src/context/Web3Provider.tsx index 1677ebbac..c6e161578 100644 --- a/web/src/context/Web3Provider.tsx +++ b/web/src/context/Web3Provider.tsx @@ -8,7 +8,7 @@ import { jsonRpcProvider } from "wagmi/providers/jsonRpc"; import { useToggleTheme } from "hooks/useToggleThemeContext"; import { useTheme } from "styled-components"; -const chains = [mainnet, arbitrumGoerli, gnosisChiado]; +const chains = [arbitrumGoerli, gnosisChiado]; const projectId = process.env.WALLETCONNECT_PROJECT_ID ?? "6efaa26765fa742153baf9281e218217"; const { publicClient, webSocketPublicClient } = configureChains(chains, [ diff --git a/web/src/hooks/queries/useCasesQuery.ts b/web/src/hooks/queries/useCasesQuery.ts index c6b813924..6d1cf7a9e 100644 --- a/web/src/hooks/queries/useCasesQuery.ts +++ b/web/src/hooks/queries/useCasesQuery.ts @@ -5,8 +5,8 @@ import { graphqlQueryFnHelper } from "~src/utils/graphqlQueryFnHelper"; export type { CasesPageQuery }; const casesQuery = graphql(` - query CasesPage($skip: Int) { - disputes(first: 3, skip: $skip, orderBy: lastPeriodChange, orderDirection: desc) { + query CasesPage($first: Int, $skip: Int) { + disputes(first: $first, skip: $skip, orderBy: lastPeriodChange, orderDirection: desc) { id arbitrated { id @@ -26,12 +26,12 @@ const casesQuery = graphql(` } `); -export const useCasesQuery = (skip: number) => { +export const useCasesQuery = (skip: number, first = 3) => { const isEnabled = skip !== undefined; return useQuery({ - queryKey: [`useCasesQuery${skip}`], + queryKey: [`useCasesQuery${skip},${first}`], enabled: isEnabled, - queryFn: async () => await graphqlQueryFnHelper(casesQuery, { skip: skip }), + queryFn: async () => await graphqlQueryFnHelper(casesQuery, { skip, first }), }); }; diff --git a/web/src/hooks/useWindowWidth.ts b/web/src/hooks/useWindowWidth.ts new file mode 100644 index 000000000..ff74a14ba --- /dev/null +++ b/web/src/hooks/useWindowWidth.ts @@ -0,0 +1,19 @@ +import { useState, useEffect } from "react"; + +export const useWindowWidth = () => { + const [windowWidth, setWindowWidth] = useState(window.innerWidth); + + useEffect(() => { + const handleResize = () => { + setWindowWidth(window.innerWidth); + }; + + window.addEventListener("resize", handleResize); + + return () => { + window.removeEventListener("resize", handleResize); + }; + }, []); + + return windowWidth; +}; diff --git a/web/src/pages/Cases/index.tsx b/web/src/pages/Cases/index.tsx index 86b623fdb..a34ce9a04 100644 --- a/web/src/pages/Cases/index.tsx +++ b/web/src/pages/Cases/index.tsx @@ -1,10 +1,12 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import styled from "styled-components"; import { Routes, Route } from "react-router-dom"; import { useCasesQuery } from "queries/useCasesQuery"; +import { useWindowWidth } from "hooks/useWindowWidth"; +import { BREAKPOINT_TABLET_SCREEN } from "styles/tabletScreenStyle"; import CasesDisplay from "components/CasesDisplay"; import CaseDetails from "./CaseDetails"; - +import { useFiltersContext } from "context/FilterProvider"; const Container = styled.div` width: 100%; min-height: calc(100vh - 144px); @@ -14,8 +16,18 @@ const Container = styled.div` const Cases: React.FC = () => { const [currentPage, setCurrentPage] = useState(1); - const casesPerPage = 3; - const { data } = useCasesQuery(casesPerPage * (currentPage - 1)); + const windowWidth = useWindowWidth(); + const { isList, setIsList } = useFiltersContext(); + const screenIsBig = windowWidth > BREAKPOINT_TABLET_SCREEN; + const casesPerPage = screenIsBig ? 9 : 3; + const { data } = useCasesQuery(casesPerPage * (currentPage - 1), casesPerPage); + + useEffect(() => { + if (!screenIsBig && isList) { + setIsList(false); + } + }, [screenIsBig]); + return ( diff --git a/web/src/styles/tabletScreenStyle.ts b/web/src/styles/tabletScreenStyle.ts new file mode 100644 index 000000000..7b1fe25e7 --- /dev/null +++ b/web/src/styles/tabletScreenStyle.ts @@ -0,0 +1,9 @@ +import { css, DefaultTheme, FlattenInterpolation, ThemeProps } from "styled-components"; + +export const BREAKPOINT_TABLET_SCREEN = 1024; + +export const tabletScreenStyle = (styleFn: () => FlattenInterpolation>) => css` + @media (max-width: ${BREAKPOINT_TABLET_SCREEN}px) { + ${() => styleFn()} + } +`; From 6fd16e89b6420b970f8921da82e88ebe078f9f5f Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Thu, 7 Sep 2023 11:19:31 +0200 Subject: [PATCH 16/38] refactor(web): use different hook for window size --- web/src/hooks/useWindowWidth.tsx | 19 ------------------- web/src/pages/Home/Header.tsx | 6 +++--- 2 files changed, 3 insertions(+), 22 deletions(-) delete mode 100644 web/src/hooks/useWindowWidth.tsx diff --git a/web/src/hooks/useWindowWidth.tsx b/web/src/hooks/useWindowWidth.tsx deleted file mode 100644 index ff74a14ba..000000000 --- a/web/src/hooks/useWindowWidth.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { useState, useEffect } from "react"; - -export const useWindowWidth = () => { - const [windowWidth, setWindowWidth] = useState(window.innerWidth); - - useEffect(() => { - const handleResize = () => { - setWindowWidth(window.innerWidth); - }; - - window.addEventListener("resize", handleResize); - - return () => { - window.removeEventListener("resize", handleResize); - }; - }, []); - - return windowWidth; -}; diff --git a/web/src/pages/Home/Header.tsx b/web/src/pages/Home/Header.tsx index bd0f44e92..f420b93bf 100644 --- a/web/src/pages/Home/Header.tsx +++ b/web/src/pages/Home/Header.tsx @@ -1,17 +1,17 @@ import React from "react"; import { useTheme } from "styled-components"; +import { useWindowSize } from "react-use"; import { BREAKPOINT_SMALL_SCREEN } from "styles/smallScreenStyle"; import HeaderLightMobile from "tsx:svgs/header/header-lightmode-mobile.svg"; import HeaderDarkMobile from "tsx:svgs/header/header-darkmode-mobile.svg"; import HeaderLightDesktop from "tsx:svgs/header/header-lightmode-desktop.svg"; import HeaderDarkDesktop from "tsx:svgs/header/header-darkmode-desktop.svg"; -import { useWindowWidth } from "hooks/useWindowWidth"; const Header = () => { - const windowWidth = useWindowWidth(); + const { width } = useWindowSize(); const theme = useTheme(); const themeIsLight = theme.name === "light"; - const screenIsBig = windowWidth > BREAKPOINT_SMALL_SCREEN; + const screenIsBig = width > BREAKPOINT_SMALL_SCREEN; return
{screenIsBig ? : }
; }; From 06eb085d4fb0b467a93a40578c7ad9eaeb828dd0 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Sat, 9 Sep 2023 07:15:58 +0200 Subject: [PATCH 17/38] feat(web): multiple changes to css across all frontend --- web/src/assets/svgs/icons/vea.svg | 5 ++ web/src/components/EvidenceCard.tsx | 68 ++++++++++++++++--- .../components/Verdict/DisputeTimeline.tsx | 6 +- web/src/components/Verdict/FinalDecision.tsx | 12 ++-- web/src/components/Verdict/VerdictBanner.tsx | 2 +- web/src/context/StyledComponentsProvider.tsx | 2 +- web/src/layout/Header/navbar/DappList.tsx | 16 +++-- web/src/layout/Header/navbar/Product.tsx | 17 +---- .../Cases/CaseDetails/Appeal/Classic/Fund.tsx | 10 ++- .../Appeal/Classic/Options/StageOne.tsx | 35 ++++++---- .../Appeal/Classic/Options/StageTwo.tsx | 10 ++- .../Appeal/Classic/Options/index.tsx | 10 ++- .../Appeal/Classic/StageExplainer.tsx | 1 + .../CaseDetails/Appeal/Classic/index.tsx | 2 +- .../Cases/CaseDetails/Appeal/OptionCard.tsx | 2 +- web/src/pages/Cases/CaseDetails/Overview.tsx | 59 ++++++++++++---- web/src/pages/Cases/CaseDetails/Tabs.tsx | 2 +- web/src/pages/Cases/CaseDetails/Timeline.tsx | 58 +++++++++++++--- web/src/pages/Cases/CaseDetails/index.tsx | 9 ++- web/src/pages/Cases/index.tsx | 4 +- web/src/pages/Courts/index.tsx | 4 +- web/src/pages/Dashboard/index.tsx | 4 +- web/src/pages/Home/index.tsx | 2 +- 23 files changed, 249 insertions(+), 91 deletions(-) create mode 100644 web/src/assets/svgs/icons/vea.svg diff --git a/web/src/assets/svgs/icons/vea.svg b/web/src/assets/svgs/icons/vea.svg new file mode 100644 index 000000000..1fa6470d0 --- /dev/null +++ b/web/src/assets/svgs/icons/vea.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/web/src/components/EvidenceCard.tsx b/web/src/components/EvidenceCard.tsx index 44a1cabeb..3da8d071a 100644 --- a/web/src/components/EvidenceCard.tsx +++ b/web/src/components/EvidenceCard.tsx @@ -1,5 +1,6 @@ import React from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; +import { smallScreenStyle } from "styles/smallScreenStyle"; import Identicon from "react-identicons"; import { Card } from "@kleros/ui-components-library"; import AttachmentIcon from "svgs/icons/attachment.svg"; @@ -13,7 +14,7 @@ const StyledCard = styled(Card)` `; const TextContainer = styled.div` - padding: 8px; + padding: calc(8px + (24 - 8) * (min(max(100vw, 375px), 1250px) - 375px) / 875); > * { overflow-wrap: break-word; margin: 0; @@ -32,8 +33,8 @@ const BottomShade = styled.div` background-color: ${({ theme }) => theme.lightBlue}; display: flex; align-items: center; - gap: 8px; - padding: 8px; + gap: 16px; + padding: 12px calc(8px + (24 - 8) * (min(max(100vw, 375px), 1250px) - 375px) / 875); > * { flex-basis: 1; flex-shrink: 0; @@ -42,15 +43,63 @@ const BottomShade = styled.div` `; const StyledA = styled.a` - margin-left: auto; - margin-right: 8px; + gap: calc(5px + (6 - 5) * (min(max(100vw, 375px), 1250px) - 375px) / 875); display: flex; > svg { width: 16px; fill: ${({ theme }) => theme.primaryBlue}; } + + ${smallScreenStyle( + () => css` + margin-left: auto; + ` + )} `; +const AccountContainer = styled.div` + display: flex; + flex-direction: row; + gap: 8px; + align-items: center; + + canvas { + width: 24px; + height: 24px; + } + + > * { + flex-basis: 1; + flex-shrink: 0; + margin: 0; + } +`; + +const DesktopText = styled.span` + ${smallScreenStyle( + () => css` + display: none; + ` + )} +`; + +const MobileText = styled.span` + display: none; + + ${smallScreenStyle( + () => css` + display: inline; + ` + )} +`; + +const AttachedFileText: React.FC = () => ( + <> + View attached file + File + +); + interface IEvidenceCard { evidence: string; sender: string; @@ -73,11 +122,14 @@ const EvidenceCard: React.FC = ({ evidence, sender, index }) => { )} - -

{shortenAddress(sender)}

+ + +

{shortenAddress(sender)}

+
{data && typeof data.fileURI !== "undefined" && ( + )}
diff --git a/web/src/components/Verdict/DisputeTimeline.tsx b/web/src/components/Verdict/DisputeTimeline.tsx index c2efa61e1..2daad4db0 100644 --- a/web/src/components/Verdict/DisputeTimeline.tsx +++ b/web/src/components/Verdict/DisputeTimeline.tsx @@ -16,19 +16,17 @@ const Container = styled.div` display: flex; position: relative; margin-left: 8px; + flex-direction: column; `; const StyledTimeline = styled(CustomTimeline)` width: 100%; - margin-bottom: 32px; `; const EnforcementContainer = styled.div` - position: absolute; - bottom: 0; display: flex; gap: 8px; - margin-bottom: 8px; + margin-top: calc(12px + (24 - 12) * (min(max(100vw, 375px), 1250px) - 375px) / 875); fill: ${({ theme }) => theme.secondaryText}; small { diff --git a/web/src/components/Verdict/FinalDecision.tsx b/web/src/components/Verdict/FinalDecision.tsx index 5c40e5d09..dfb30960c 100644 --- a/web/src/components/Verdict/FinalDecision.tsx +++ b/web/src/components/Verdict/FinalDecision.tsx @@ -19,6 +19,7 @@ const JuryContainer = styled.div` gap: 8px; h3 { line-height: 21px; + margin-bottom: 0px; } `; @@ -28,10 +29,6 @@ const JuryDecisionTag = styled.small` color: ${({ theme }) => theme.secondaryText}; `; -const Divider = styled.hr` - color: ${({ theme }) => theme.stroke}; -`; - const UserContainer = styled.div` display: flex; align-items: center; @@ -65,12 +62,19 @@ const StyledButton = styled(LightButton)` > .button-text { color: ${({ theme }) => theme.primaryBlue}; } + padding-top: 0px; `; const AnswerTitle = styled.h3` margin: 0; `; +const Divider = styled.hr` + display: flex; + color: ${({ theme }) => theme.stroke}; + margin: calc(16px + (32 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875) 0px; +`; + interface IFinalDecision { arbitrable?: `0x${string}`; } diff --git a/web/src/components/Verdict/VerdictBanner.tsx b/web/src/components/Verdict/VerdictBanner.tsx index 8cfa591f0..516b0779f 100644 --- a/web/src/components/Verdict/VerdictBanner.tsx +++ b/web/src/components/Verdict/VerdictBanner.tsx @@ -6,7 +6,7 @@ import HourglassIcon from "assets/svgs/icons/hourglass.svg"; const BannerContainer = styled.div` display: flex; gap: 8px; - margin: 16px 0px; + margin-bottom: calc(16px + (24 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); svg { width: 16px; height: 16px; diff --git a/web/src/context/StyledComponentsProvider.tsx b/web/src/context/StyledComponentsProvider.tsx index f5d88f952..7d11c3407 100644 --- a/web/src/context/StyledComponentsProvider.tsx +++ b/web/src/context/StyledComponentsProvider.tsx @@ -8,7 +8,7 @@ import { lightTheme, darkTheme } from "styles/themes"; const StyledComponentsProvider: React.FC<{ children: React.ReactNode; }> = ({ children }) => { - const [theme, setTheme] = useLocalStorage("theme", "light"); + const [theme, setTheme] = useLocalStorage("theme", "dark"); const toggleTheme = () => { if (theme === "light") setTheme("dark"); else setTheme("light"); diff --git a/web/src/layout/Header/navbar/DappList.tsx b/web/src/layout/Header/navbar/DappList.tsx index 8648e9f08..4200dd1c4 100644 --- a/web/src/layout/Header/navbar/DappList.tsx +++ b/web/src/layout/Header/navbar/DappList.tsx @@ -10,6 +10,7 @@ import Governor from "svgs/icons/governor.svg"; import Court from "svgs/icons/kleros.svg"; import Linguo from "svgs/icons/linguo.svg"; import POH from "svgs/icons/poh-image.png"; +import Vea from "svgs/icons/vea.svg"; import Tokens from "svgs/icons/tokens.svg"; import Product from "./Product"; import { Overlay } from "components/Overlay"; @@ -76,16 +77,16 @@ const ITEMS = [ Icon: Court, url: "https://court.kleros.io/", }, + { + text: "Vea", + Icon: Vea, + url: "https://veascan.io", + }, { text: "Escrow", Icon: Escrow, url: "https://escrow.kleros.io", }, - { - text: "Tokens", - Icon: Tokens, - url: "https://tokens.kleros.io", - }, { text: "POH", Icon: POH, @@ -96,6 +97,11 @@ const ITEMS = [ Icon: Curate, url: "https://curate.kleros.io", }, + { + text: "Tokens", + Icon: Tokens, + url: "https://tokens.kleros.io", + }, { text: "Resolver", Icon: Resolver, diff --git a/web/src/layout/Header/navbar/Product.tsx b/web/src/layout/Header/navbar/Product.tsx index 1fa47844c..0dd5c3cf5 100644 --- a/web/src/layout/Header/navbar/Product.tsx +++ b/web/src/layout/Header/navbar/Product.tsx @@ -24,24 +24,9 @@ const Container = styled.a` line-height: 19px; font-size: 14px; } - - svg { - max-width: 48px; - max-height: 48px; - fill: none; - visibility: visible; - display: inline-block; - } `; -const StyledIcon = styled.svg` - max-width: 48px; - max-height: 48px; - fill: none; - visibility: visible; - display: inline-block; - fill: ${({ theme }) => theme.secondaryPurple}; -`; +const StyledIcon = styled.svg``; const StyledImg = styled.img` max-width: 48px; diff --git a/web/src/pages/Cases/CaseDetails/Appeal/Classic/Fund.tsx b/web/src/pages/Cases/CaseDetails/Appeal/Classic/Fund.tsx index 2645336ea..019e70bff 100644 --- a/web/src/pages/Cases/CaseDetails/Appeal/Classic/Fund.tsx +++ b/web/src/pages/Cases/CaseDetails/Appeal/Classic/Fund.tsx @@ -15,6 +15,12 @@ import { useFundingContext, } from "hooks/useClassicAppealContext"; +const Container = styled.div` + display: flex; + flex-direction: column; + gap: 8px; +`; + const StyledField = styled(Field)` width: 100%; & > input { @@ -86,7 +92,7 @@ const Fund: React.FC = ({ amount, setAmount, setIsOpen }) => { const fundAppeal = useFundAppeal(parsedAmount); return needFund ? ( -
+
= ({ amount, setAmount, setIsOpen }) => { />
-
+
) : ( <> ); diff --git a/web/src/pages/Cases/CaseDetails/Appeal/Classic/Options/StageOne.tsx b/web/src/pages/Cases/CaseDetails/Appeal/Classic/Options/StageOne.tsx index 805ec3244..765a1a7e2 100644 --- a/web/src/pages/Cases/CaseDetails/Appeal/Classic/Options/StageOne.tsx +++ b/web/src/pages/Cases/CaseDetails/Appeal/Classic/Options/StageOne.tsx @@ -8,6 +8,7 @@ import { useOptionsContext, useSelectedOptionContext, } from "hooks/useClassicAppealContext"; +import { formatUnitsWei } from "utils/format"; const Container = styled.div` margin: 24px 0; @@ -20,7 +21,11 @@ const OptionsContainer = styled.div` margin-top: 12px; `; -const StageOne: React.FC = () => { +interface IStageOne { + setAmount: (val: string) => void; +} + +const StageOne: React.FC = ({ setAmount }) => { const { paidFees, winningChoice, loserRequiredFunding, winnerRequiredFunding } = useFundingContext(); const options = useOptionsContext(); const loserSideCountdown = useLoserSideCountdownContext(); @@ -33,17 +38,23 @@ const StageOne: React.FC = () => { {typeof paidFees !== "undefined" && typeof winnerRequiredFunding !== "undefined" && typeof loserRequiredFunding !== "undefined" && - options?.map((answer: string, i: number) => ( - setSelectedOption(i)} - /> - ))} + options?.map((answer: string, i: number) => { + const requiredFunding = i.toString() === winningChoice ? winnerRequiredFunding : loserRequiredFunding; + return ( + { + setSelectedOption(i); + setAmount(formatUnitsWei(requiredFunding)); + }} + /> + ); + })}
); diff --git a/web/src/pages/Cases/CaseDetails/Appeal/Classic/Options/StageTwo.tsx b/web/src/pages/Cases/CaseDetails/Appeal/Classic/Options/StageTwo.tsx index 6be1c1485..fe7a4ec66 100644 --- a/web/src/pages/Cases/CaseDetails/Appeal/Classic/Options/StageTwo.tsx +++ b/web/src/pages/Cases/CaseDetails/Appeal/Classic/Options/StageTwo.tsx @@ -3,6 +3,7 @@ import styled from "styled-components"; import OptionCard from "../../OptionCard"; import { useFundingContext, useOptionsContext, useSelectedOptionContext } from "hooks/useClassicAppealContext"; import { isUndefined } from "utils/index"; +import { formatUnitsWei } from "utils/format"; const Container = styled.div` margin: 24px 0; @@ -15,12 +16,17 @@ const OptionsContainer = styled.div` margin-top: 12px; `; -const StageOne: React.FC = () => { +interface IStageTwo { + setAmount: (val: string) => void; +} + +const StageTwo: React.FC = ({ setAmount }) => { const { paidFees, winningChoice, winnerRequiredFunding, fundedChoices } = useFundingContext(); const options = useOptionsContext(); const { selectedOption, setSelectedOption } = useSelectedOptionContext(); useEffect(() => { if (!isUndefined(winningChoice)) setSelectedOption(parseInt(winningChoice)); + if (!isUndefined(winnerRequiredFunding)) setAmount(formatUnitsWei(winnerRequiredFunding)); }); return ( @@ -50,4 +56,4 @@ const StageOne: React.FC = () => { ); }; -export default StageOne; +export default StageTwo; diff --git a/web/src/pages/Cases/CaseDetails/Appeal/Classic/Options/index.tsx b/web/src/pages/Cases/CaseDetails/Appeal/Classic/Options/index.tsx index 83219b2c1..95d81fc87 100644 --- a/web/src/pages/Cases/CaseDetails/Appeal/Classic/Options/index.tsx +++ b/web/src/pages/Cases/CaseDetails/Appeal/Classic/Options/index.tsx @@ -10,10 +10,16 @@ const Container = styled.div` margin: 24px 0; `; -const Options: React.FC = () => { +interface IOptions { + setAmount: (val: string) => void; +} + +const Options: React.FC = ({ setAmount }) => { const loserSideCountdown = useLoserSideCountdownContext(); return !isUndefined(loserSideCountdown) ? ( - {loserSideCountdown > 0 ? : } + + {loserSideCountdown > 0 ? : } + ) : ( ); diff --git a/web/src/pages/Cases/CaseDetails/Appeal/Classic/StageExplainer.tsx b/web/src/pages/Cases/CaseDetails/Appeal/Classic/StageExplainer.tsx index 123838747..d3fd96015 100644 --- a/web/src/pages/Cases/CaseDetails/Appeal/Classic/StageExplainer.tsx +++ b/web/src/pages/Cases/CaseDetails/Appeal/Classic/StageExplainer.tsx @@ -23,6 +23,7 @@ const CountdownLabel = styled.label` margin-bottom: 12px; border-bottom: 1px solid ${({ theme }) => theme.secondaryPurple}; color: ${({ theme }) => theme.primaryText}; + gap: 8px; & > svg { width: 14px; fill: ${({ theme }) => theme.secondaryPurple}; diff --git a/web/src/pages/Cases/CaseDetails/Appeal/Classic/index.tsx b/web/src/pages/Cases/CaseDetails/Appeal/Classic/index.tsx index 921fac7a9..c5b0a67b2 100644 --- a/web/src/pages/Cases/CaseDetails/Appeal/Classic/index.tsx +++ b/web/src/pages/Cases/CaseDetails/Appeal/Classic/index.tsx @@ -27,7 +27,7 @@ const Classic: React.FC = () => { )}

Appeal crowdfunding

- + ); diff --git a/web/src/pages/Cases/CaseDetails/Appeal/OptionCard.tsx b/web/src/pages/Cases/CaseDetails/Appeal/OptionCard.tsx index df23ed64c..729a402d6 100644 --- a/web/src/pages/Cases/CaseDetails/Appeal/OptionCard.tsx +++ b/web/src/pages/Cases/CaseDetails/Appeal/OptionCard.tsx @@ -18,7 +18,7 @@ const WinnerLabel = styled.label<{ winner: boolean }>` color: ${({ theme, winner }) => (winner ? theme.success : theme.warning)}; svg { width: 12px; - margin-right: 4px; + margin-right: 8px; fill: ${({ theme, winner }) => (winner ? theme.success : theme.warning)}; } `; diff --git a/web/src/pages/Cases/CaseDetails/Overview.tsx b/web/src/pages/Cases/CaseDetails/Overview.tsx index 7de07014f..0dc546168 100644 --- a/web/src/pages/Cases/CaseDetails/Overview.tsx +++ b/web/src/pages/Cases/CaseDetails/Overview.tsx @@ -1,5 +1,6 @@ import React from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; +import { smallScreenStyle } from "styles/smallScreenStyle"; import { useParams } from "react-router-dom"; import ReactMarkdown from "react-markdown"; import { formatEther } from "viem"; @@ -20,7 +21,7 @@ const Container = styled.div` height: auto; display: flex; flex-direction: column; - gap: 16px; + gap: calc(16px + (32 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); > h1 { margin: 0; @@ -42,7 +43,14 @@ const QuestionAndDescription = styled.div` const VotingOptions = styled(QuestionAndDescription)` display: flex; flex-direction: column; - > span { + gap: 8px; +`; + +const Answers = styled.div` + display: flex; + flex-direction: column; + + span { margin: 0px; display: flex; gap: 8px; @@ -50,13 +58,29 @@ const VotingOptions = styled(QuestionAndDescription)` `; const ShadeArea = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; width: 100%; - padding: 16px; - margin-top: 16px; + padding: calc(16px + (32 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + margin-top: calc(24px + (48 - 24) * (min(max(100vw, 375px), 1250px) - 375px) / 875); background-color: ${({ theme }) => theme.mediumBlue}; > p { margin-top: 0; + margin-bottom: 0; + ${smallScreenStyle( + () => css` + margin-bottom: 16px; + ` + )}; } + + ${smallScreenStyle( + () => css` + flex-direction: column; + justify-content: center; + ` + )}; `; const StyledA = styled.a` @@ -72,6 +96,13 @@ const StyledA = styled.a` const LinkContainer = styled.div` display: flex; justify-content: space-between; + gap: calc(8px + (24 - 8) * (min(max(100vw, 375px), 1250px) - 375px) / 875); +`; + +const Divider = styled.hr` + display: flex; + color: ${({ theme }) => theme.stroke}; + margin: 0; `; interface IOverview { @@ -111,18 +142,20 @@ const Overview: React.FC = ({ arbitrable, courtID, currentPeriodIndex )} {disputeTemplate &&

Voting Options

} - {disputeTemplate?.answers?.map((answer: { title: string; description: string }, i: number) => ( - - Option {i + 1}: - - - ))} + + {disputeTemplate?.answers?.map((answer: { title: string; description: string }, i: number) => ( + + Option {i + 1}: + + + ))} +
+ {currentPeriodIndex !== Periods.evidence && ( <> -
-
+ )} diff --git a/web/src/pages/Cases/CaseDetails/Tabs.tsx b/web/src/pages/Cases/CaseDetails/Tabs.tsx index f7c976c0c..dff98202b 100644 --- a/web/src/pages/Cases/CaseDetails/Tabs.tsx +++ b/web/src/pages/Cases/CaseDetails/Tabs.tsx @@ -16,7 +16,7 @@ const StyledTabs = styled(TabsComponent)` display: flex; flex-wrap: wrap; > svg { - margin-right: 0px !important; + margin-right: 8px !important; } } `; diff --git a/web/src/pages/Cases/CaseDetails/Timeline.tsx b/web/src/pages/Cases/CaseDetails/Timeline.tsx index 9fb621da0..f2db7f2bb 100644 --- a/web/src/pages/Cases/CaseDetails/Timeline.tsx +++ b/web/src/pages/Cases/CaseDetails/Timeline.tsx @@ -1,5 +1,6 @@ import React from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; +import { tabletScreenStyle } from "styles/tabletScreenStyle"; import { Periods } from "consts/periods"; import { DisputeDetailsQuery } from "queries/useDisputeDetailsQuery"; import { Box, Steps } from "@kleros/ui-components-library"; @@ -8,18 +9,49 @@ import { useCountdown } from "hooks/useCountdown"; import { secondsToDayHourMinute } from "utils/date"; const TimeLineContainer = styled(Box)` + display: flex; width: 100%; - height: 100px; - border-radius: 3px; - margin: 16px 0px; - padding: 8px; + height: 98px; + border-radius: 0px; + margin-top: calc(16px + (48 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + margin-bottom: calc(12px + (22 - 12) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + background-color: ${({ theme }) => theme.whiteBackground}; + + ${tabletScreenStyle( + () => css` + padding: 20px 8px 8px 8px; + display: block; + ` + )} `; -const StyledSteps = styled(Steps)` +const StyledSteps = styled(Steps)`d + display: flex; + justify-content: space-between; width: 85%; margin: auto; `; +const TitleMobile = styled.span` + display: none; + + ${tabletScreenStyle( + () => css` + display: inline-block; + ` + )} +`; + +const TitleDesktop = styled(TitleMobile)` + display: inline-block; + + ${tabletScreenStyle( + () => css` + display: none; + ` + )} +`; + const Timeline: React.FC<{ dispute: DisputeDetailsQuery["dispute"]; currentPeriodIndex: number; @@ -40,7 +72,12 @@ const currentPeriodToCurrentItem = (currentPeriodIndex: number, ruled?: boolean) }; const useTimeline = (dispute: DisputeDetailsQuery["dispute"], currentItemIndex: number, currentPeriodIndex: number) => { - const titles = ["Evidence Period", "Voting Period", "Appeal Period", "Executed"]; + const titles = [ + { mobile: "Evidence", desktop: "Evidence Period" }, + { mobile: "Voting", desktop: "Voting Period" }, + { mobile: "Appeal", desktop: "Appeal Period" }, + { mobile: "Executed", desktop: "Executed" }, + ]; const deadlineCurrentPeriod = getDeadline( currentPeriodIndex, dispute?.lastPeriodChange, @@ -64,7 +101,12 @@ const useTimeline = (dispute: DisputeDetailsQuery["dispute"], currentItemIndex: return []; }; return titles.map((title, i) => ({ - title, + title: ( + <> + {title.mobile} + {title.desktop} + + ), subitems: getSubitems(i), })); }; diff --git a/web/src/pages/Cases/CaseDetails/index.tsx b/web/src/pages/Cases/CaseDetails/index.tsx index 46dc66017..bf93c17eb 100644 --- a/web/src/pages/Cases/CaseDetails/index.tsx +++ b/web/src/pages/Cases/CaseDetails/index.tsx @@ -14,11 +14,14 @@ import Voting from "./Voting"; const Container = styled.div``; const StyledCard = styled(Card)` - margin-top: 16px; width: 100%; height: auto; min-height: 100px; - padding: 16px; + padding: calc(16px + (32 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); +`; + +const Header = styled.h1` + margin-bottom: calc(16px + (48 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); `; const CaseDetails: React.FC = () => { @@ -30,7 +33,7 @@ const CaseDetails: React.FC = () => { return ( -

Case #{id}

+
Case #{id}
diff --git a/web/src/pages/Cases/index.tsx b/web/src/pages/Cases/index.tsx index 1d8b7242a..bf4b32cdc 100644 --- a/web/src/pages/Cases/index.tsx +++ b/web/src/pages/Cases/index.tsx @@ -9,8 +9,8 @@ const Container = styled.div` width: 100%; min-height: calc(100vh - 144px); background-color: ${({ theme }) => theme.lightBackground}; - padding: calc(32px + (132 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); - padding-top: calc(32px + (64 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding: calc(32px + (136 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-top: calc(32px + (80 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); padding-bottom: calc(64px + (96 - 64) * (min(max(100vw, 375px), 1250px) - 375px) / 875); `; diff --git a/web/src/pages/Courts/index.tsx b/web/src/pages/Courts/index.tsx index c2f483ce3..fef9e6ab1 100644 --- a/web/src/pages/Courts/index.tsx +++ b/web/src/pages/Courts/index.tsx @@ -8,8 +8,8 @@ const Container = styled.div` width: 100%; min-height: calc(100vh - 144px); background-color: ${({ theme }) => theme.lightBackground}; - padding: calc(32px + (132 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); - padding-top: calc(32px + (64 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding: calc(32px + (136 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-top: calc(32px + (80 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); padding-bottom: calc(64px + (96 - 64) * (min(max(100vw, 375px), 1250px) - 375px) / 875); `; diff --git a/web/src/pages/Dashboard/index.tsx b/web/src/pages/Dashboard/index.tsx index db14e62e4..aaec003e6 100644 --- a/web/src/pages/Dashboard/index.tsx +++ b/web/src/pages/Dashboard/index.tsx @@ -11,8 +11,8 @@ const Container = styled.div` width: 100%; min-height: calc(100vh - 144px); background-color: ${({ theme }) => theme.lightBackground}; - padding: calc(32px + (132 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); - padding-top: calc(32px + (64 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding: calc(32px + (136 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-top: calc(32px + (80 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); padding-bottom: calc(64px + (96 - 64) * (min(max(100vw, 375px), 1250px) - 375px) / 875); `; diff --git a/web/src/pages/Home/index.tsx b/web/src/pages/Home/index.tsx index 62cd3ada1..3002b16ab 100644 --- a/web/src/pages/Home/index.tsx +++ b/web/src/pages/Home/index.tsx @@ -12,7 +12,7 @@ const Container = styled.div` min-height: calc(100vh - 144px); background-color: ${({ theme }) => theme.lightBackground}; padding: calc(32px + (132 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); - padding-top: calc(32px + (64 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-top: calc(32px + (72 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); padding-bottom: calc(64px + (96 - 64) * (min(max(100vw, 375px), 1250px) - 375px) / 875); `; From f27a98db5c8b0953ab00614b427a9524885b2094 Mon Sep 17 00:00:00 2001 From: nhestrompia Date: Mon, 11 Sep 2023 01:59:57 +0300 Subject: [PATCH 18/38] fix: mobile responsiveness --- web/src/components/CasesDisplay/CasesGrid.tsx | 16 ++++--- .../CasesDisplay/CasesListHeader.tsx | 3 +- .../components/DisputeCard/DisputeInfo.tsx | 26 ++++++----- web/src/components/DisputeCard/index.tsx | 3 +- web/src/components/Field.tsx | 43 ++++++++++--------- web/src/hooks/useWindowWidth.ts | 19 -------- web/src/pages/Cases/index.tsx | 10 +++-- web/src/pages/Dashboard/index.tsx | 4 +- web/src/pages/Home/LatestCases.tsx | 9 +++- web/src/styles/tabletScreenStyle.ts | 6 +-- 10 files changed, 68 insertions(+), 71 deletions(-) delete mode 100644 web/src/hooks/useWindowWidth.ts diff --git a/web/src/components/CasesDisplay/CasesGrid.tsx b/web/src/components/CasesDisplay/CasesGrid.tsx index 7f465ff1e..ad5d96857 100644 --- a/web/src/components/CasesDisplay/CasesGrid.tsx +++ b/web/src/components/CasesDisplay/CasesGrid.tsx @@ -1,7 +1,7 @@ import React from "react"; import styled, { css } from "styled-components"; import { StandardPagination } from "@kleros/ui-components-library"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import { tabletScreenStyle } from "styles/tabletScreenStyle"; import { useFiltersContext } from "context/FilterProvider"; import { CasesPageQuery } from "queries/useCasesQuery"; import DisputeCard from "components/DisputeCard"; @@ -9,14 +9,18 @@ import CasesListHeader from "./CasesListHeader"; const GridContainer = styled.div` display: grid; - gap: 16px; - grid-template-columns: repeat(3, minmax(50px, 1fr)); - justify-content: center; + row-gap: 16px; + column-gap: 8px; + grid-template-columns: repeat(auto-fit, minmax(380px, 1fr)); + justify-content: space-between; align-items: center; - gap: 8px; - ${smallScreenStyle(css` + justify-items: center; + ${tabletScreenStyle(css` display: flex; flex-wrap: wrap; + justify-content: center; + align-items: center; + gap: 8px; `)} `; const ListContainer = styled.div` diff --git a/web/src/components/CasesDisplay/CasesListHeader.tsx b/web/src/components/CasesDisplay/CasesListHeader.tsx index ac94d34b9..de51a6717 100644 --- a/web/src/components/CasesDisplay/CasesListHeader.tsx +++ b/web/src/components/CasesDisplay/CasesListHeader.tsx @@ -5,14 +5,15 @@ import WithHelpTooltip from "pages/Dashboard/WithHelpTooltip"; const Container = styled.div` display: flex; - flex-direction: row; justify-content: space-between; gap: 40vw; width: 100%; + height: 100%; `; const CasesData = styled.div` display: flex; + flex-wrap: wrap; align-items: center; width: 100%; gap: 48px; diff --git a/web/src/components/DisputeCard/DisputeInfo.tsx b/web/src/components/DisputeCard/DisputeInfo.tsx index 6ea8f9940..bf8b3c88e 100644 --- a/web/src/components/DisputeCard/DisputeInfo.tsx +++ b/web/src/components/DisputeCard/DisputeInfo.tsx @@ -1,5 +1,6 @@ import React from "react"; import styled from "styled-components"; +import { useFiltersContext } from "context/FilterProvider"; import { Periods } from "consts/periods"; import BookmarkIcon from "svgs/icons/bookmark.svg"; import CalendarIcon from "svgs/icons/calendar.svg"; @@ -7,11 +8,11 @@ import LawBalanceIcon from "svgs/icons/law-balance.svg"; import PileCoinsIcon from "svgs/icons/pile-coins.svg"; import Field from "../Field"; -const Container = styled.div<{ isCard: boolean }>` +const Container = styled.div<{ isList: boolean }>` display: flex; - flex-direction: ${({ isCard }) => (isCard ? "column" : "row")}; - gap: ${({ isCard }) => (isCard ? "8px" : "48px")}; - justify-content: ${({ isCard }) => (isCard ? "center" : "space-between")}; + flex-direction: ${({ isList }) => (isList ? "row" : "column")}; + gap: ${({ isList }) => (isList ? "48px" : "8px")}; + justify-content: ${({ isList }) => (isList ? "space-between" : "center")}; align-items: center; width: 100%; height: 100%; @@ -37,7 +38,6 @@ export interface IDisputeInfo { rewards?: string; period?: Periods; date?: number; - isCard?: boolean; } const formatDate = (date: number) => { @@ -47,20 +47,18 @@ const formatDate = (date: number) => { return formattedDate; }; -const DisputeInfo: React.FC = ({ courtId, court, category, rewards, period, date, isCard = true }) => { +const DisputeInfo: React.FC = ({ courtId, court, category, rewards, period, date }) => { + const { isList } = useFiltersContext(); return ( - - {court && courtId && ( - - )} - {category && } - {rewards && } + + {court && courtId && } + {category && } + {rewards && } {typeof period !== "undefined" && date && ( )} diff --git a/web/src/components/DisputeCard/index.tsx b/web/src/components/DisputeCard/index.tsx index 8ecc73562..b1df25e32 100644 --- a/web/src/components/DisputeCard/index.tsx +++ b/web/src/components/DisputeCard/index.tsx @@ -16,7 +16,7 @@ import { isUndefined } from "utils/index"; const StyledCard = styled(Card)` max-width: 380px; min-width: 312px; - width: auto; + width: 380px; height: 260px; `; const StyledListItem = styled(Card)` @@ -111,7 +111,6 @@ const DisputeCard: React.FC = ({

{title}

` width: ${({ width = "100%" }) => width}; @@ -10,7 +11,7 @@ const FieldContainer = styled.div` white-space: nowrap; .value { flex-grow: 1; - text-align: ${({ isCard }) => (isCard ? "end" : "center")}; + text-align: ${({ isList }) => (isList ? "center" : "end")}; color: ${({ theme }) => theme.primaryText}; } svg { @@ -28,7 +29,7 @@ const FieldContainer = styled.div` type FieldContainerProps = { width?: string; - isCard?: boolean; + isList?: boolean; }; interface IField { @@ -37,25 +38,27 @@ interface IField { value: string; link?: string; width?: string; - isCard?: boolean; } -const Field: React.FC = ({ icon: Icon, name, value, link, width, isCard = true }) => ( - - {isCard && ( - <> - - - - )} - {link ? ( - - {value} - - ) : ( - - )} - -); +const Field: React.FC = ({ icon: Icon, name, value, link, width }) => { + const { isList } = useFiltersContext(); + return ( + + {!isList && ( + <> + + + + )} + {link ? ( + + {value} + + ) : ( + + )} + + ); +}; export default Field; diff --git a/web/src/hooks/useWindowWidth.ts b/web/src/hooks/useWindowWidth.ts deleted file mode 100644 index ff74a14ba..000000000 --- a/web/src/hooks/useWindowWidth.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { useState, useEffect } from "react"; - -export const useWindowWidth = () => { - const [windowWidth, setWindowWidth] = useState(window.innerWidth); - - useEffect(() => { - const handleResize = () => { - setWindowWidth(window.innerWidth); - }; - - window.addEventListener("resize", handleResize); - - return () => { - window.removeEventListener("resize", handleResize); - }; - }, []); - - return windowWidth; -}; diff --git a/web/src/pages/Cases/index.tsx b/web/src/pages/Cases/index.tsx index a34ce9a04..ec746e268 100644 --- a/web/src/pages/Cases/index.tsx +++ b/web/src/pages/Cases/index.tsx @@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react"; import styled from "styled-components"; import { Routes, Route } from "react-router-dom"; import { useCasesQuery } from "queries/useCasesQuery"; -import { useWindowWidth } from "hooks/useWindowWidth"; +import { useWindowSize } from "react-use"; import { BREAKPOINT_TABLET_SCREEN } from "styles/tabletScreenStyle"; import CasesDisplay from "components/CasesDisplay"; import CaseDetails from "./CaseDetails"; @@ -11,14 +11,16 @@ const Container = styled.div` width: 100%; min-height: calc(100vh - 144px); background-color: ${({ theme }) => theme.lightBackground}; - padding: 32px; + padding: calc(32px + (132 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-top: calc(32px + (64 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-bottom: calc(64px + (96 - 64) * (min(max(100vw, 375px), 1250px) - 375px) / 875); `; const Cases: React.FC = () => { const [currentPage, setCurrentPage] = useState(1); - const windowWidth = useWindowWidth(); + const { width } = useWindowSize(); const { isList, setIsList } = useFiltersContext(); - const screenIsBig = windowWidth > BREAKPOINT_TABLET_SCREEN; + const screenIsBig = width > BREAKPOINT_TABLET_SCREEN; const casesPerPage = screenIsBig ? 9 : 3; const { data } = useCasesQuery(casesPerPage * (currentPage - 1), casesPerPage); diff --git a/web/src/pages/Dashboard/index.tsx b/web/src/pages/Dashboard/index.tsx index aaf615cec..f5d303e4c 100644 --- a/web/src/pages/Dashboard/index.tsx +++ b/web/src/pages/Dashboard/index.tsx @@ -11,7 +11,9 @@ const Container = styled.div` width: 100%; min-height: calc(100vh - 144px); background-color: ${({ theme }) => theme.lightBackground}; - padding: 32px; + padding: calc(32px + (132 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-top: calc(32px + (64 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875); + padding-bottom: calc(64px + (96 - 64) * (min(max(100vw, 375px), 1250px) - 375px) / 875); `; const StyledCasesDisplay = styled(CasesDisplay)` diff --git a/web/src/pages/Home/LatestCases.tsx b/web/src/pages/Home/LatestCases.tsx index d3f9028a6..353e8bece 100644 --- a/web/src/pages/Home/LatestCases.tsx +++ b/web/src/pages/Home/LatestCases.tsx @@ -1,6 +1,7 @@ -import React from "react"; +import React, { useEffect } from "react"; import styled from "styled-components"; import { useCasesQuery } from "queries/useCasesQuery"; +import { useFiltersContext } from "context/FilterProvider"; import DisputeCard from "components/DisputeCard"; import { StyledSkeleton } from "components/StyledSkeleton"; @@ -16,6 +17,12 @@ const Container = styled.div` const LatestCases: React.FC = () => { const { data } = useCasesQuery(0); + const { setIsList } = useFiltersContext(); + + useEffect(() => { + setIsList(false); + }, []); + return (

Latest Cases

diff --git a/web/src/styles/tabletScreenStyle.ts b/web/src/styles/tabletScreenStyle.ts index 7b1fe25e7..b047e6603 100644 --- a/web/src/styles/tabletScreenStyle.ts +++ b/web/src/styles/tabletScreenStyle.ts @@ -1,9 +1,9 @@ -import { css, DefaultTheme, FlattenInterpolation, ThemeProps } from "styled-components"; +import { css, FlattenSimpleInterpolation } from "styled-components"; export const BREAKPOINT_TABLET_SCREEN = 1024; -export const tabletScreenStyle = (styleFn: () => FlattenInterpolation>) => css` +export const tabletScreenStyle = (style: FlattenSimpleInterpolation) => css` @media (max-width: ${BREAKPOINT_TABLET_SCREEN}px) { - ${() => styleFn()} + ${style} } `; From d628e21f159b0c06203a037bda0b007cb57fdf38 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Mon, 11 Sep 2023 16:58:32 +0200 Subject: [PATCH 19/38] refactor(web): make website mobile first, landscape, portrait later, hero image refactor, styledlink --- .../hero-darkmode-desktop.svg} | 0 .../hero-darkmode-mobile.svg} | 0 .../hero-lightmode-desktop.svg} | 0 .../hero-lightmode-mobile.svg} | 0 .../ConnectWallet/AccountDisplay.tsx | 68 ++++++++----------- web/src/components/EvidenceCard.tsx | 27 ++++---- web/src/components/StatDisplay.tsx | 7 +- web/src/layout/Footer/index.tsx | 16 ++--- web/src/layout/Header/DesktopHeader.tsx | 16 ++--- web/src/layout/Header/MobileHeader.tsx | 35 +++++----- web/src/layout/Header/navbar/DappList.tsx | 14 ++-- web/src/layout/Header/navbar/Explore.tsx | 58 ++++++++-------- web/src/layout/Header/navbar/Menu/Help.tsx | 16 ++--- .../Header/navbar/Menu/Settings/index.tsx | 15 ++-- web/src/layout/Header/navbar/Menu/index.tsx | 24 ++++--- web/src/layout/Header/navbar/index.tsx | 44 ++++++------ web/src/pages/Cases/CaseDetails/Overview.tsx | 18 ++--- web/src/pages/Cases/CaseDetails/Timeline.tsx | 21 +++--- web/src/pages/Courts/CourtDetails/Stats.tsx | 8 +-- web/src/pages/Dashboard/JurorInfo/index.tsx | 13 ++-- web/src/pages/Home/Community/index.tsx | 32 +++++---- web/src/pages/Home/CourtOverview/Stats.tsx | 11 +-- web/src/pages/Home/Header.tsx | 26 ------- web/src/pages/Home/HeroImage.tsx | 26 +++++++ web/src/pages/Home/index.tsx | 4 +- web/src/styles/landscapeStyle.ts | 9 +++ web/src/styles/portraitStyle.ts | 9 +++ web/src/styles/smallScreenStyle.ts | 9 --- web/src/styles/tabletScreenStyle.ts | 9 --- 29 files changed, 260 insertions(+), 275 deletions(-) rename web/src/assets/svgs/{header/header-darkmode-desktop.svg => hero/hero-darkmode-desktop.svg} (100%) rename web/src/assets/svgs/{header/header-darkmode-mobile.svg => hero/hero-darkmode-mobile.svg} (100%) rename web/src/assets/svgs/{header/header-lightmode-desktop.svg => hero/hero-lightmode-desktop.svg} (100%) rename web/src/assets/svgs/{header/header-lightmode-mobile.svg => hero/hero-lightmode-mobile.svg} (100%) delete mode 100644 web/src/pages/Home/Header.tsx create mode 100644 web/src/pages/Home/HeroImage.tsx create mode 100644 web/src/styles/landscapeStyle.ts create mode 100644 web/src/styles/portraitStyle.ts delete mode 100644 web/src/styles/smallScreenStyle.ts delete mode 100644 web/src/styles/tabletScreenStyle.ts diff --git a/web/src/assets/svgs/header/header-darkmode-desktop.svg b/web/src/assets/svgs/hero/hero-darkmode-desktop.svg similarity index 100% rename from web/src/assets/svgs/header/header-darkmode-desktop.svg rename to web/src/assets/svgs/hero/hero-darkmode-desktop.svg diff --git a/web/src/assets/svgs/header/header-darkmode-mobile.svg b/web/src/assets/svgs/hero/hero-darkmode-mobile.svg similarity index 100% rename from web/src/assets/svgs/header/header-darkmode-mobile.svg rename to web/src/assets/svgs/hero/hero-darkmode-mobile.svg diff --git a/web/src/assets/svgs/header/header-lightmode-desktop.svg b/web/src/assets/svgs/hero/hero-lightmode-desktop.svg similarity index 100% rename from web/src/assets/svgs/header/header-lightmode-desktop.svg rename to web/src/assets/svgs/hero/hero-lightmode-desktop.svg diff --git a/web/src/assets/svgs/header/header-lightmode-mobile.svg b/web/src/assets/svgs/hero/hero-lightmode-mobile.svg similarity index 100% rename from web/src/assets/svgs/header/header-lightmode-mobile.svg rename to web/src/assets/svgs/hero/hero-lightmode-mobile.svg diff --git a/web/src/components/ConnectWallet/AccountDisplay.tsx b/web/src/components/ConnectWallet/AccountDisplay.tsx index 39022e922..9f97f38e5 100644 --- a/web/src/components/ConnectWallet/AccountDisplay.tsx +++ b/web/src/components/ConnectWallet/AccountDisplay.tsx @@ -1,29 +1,29 @@ import React from "react"; import styled, { css } from "styled-components"; -import { smallScreenStyle } from "styles/smallScreenStyle"; -import { tabletScreenStyle } from "styles/tabletScreenStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import { useAccount, useNetwork, useEnsAvatar, useEnsName } from "wagmi"; import Identicon from "react-identicons"; import { shortenAddress } from "utils/shortenAddress"; const Container = styled.div` display: flex; - flex-direction: row; + flex-direction: column; justify-content: space-between; - align-content: center; + height: auto; + align-items: flex-start; + gap: 8px; align-items: center; - border-radius: 300px; - background-color: ${({ theme }) => theme.whiteLowOpacity}; - padding: 0 12px; + background-color: ${({ theme }) => theme.whiteBackground}; + padding: 0px; - ${smallScreenStyle( + ${landscapeStyle( () => css` - background-color: ${({ theme }) => theme.whiteBackground}; - flex-direction: column; - align-items: flex-start; - gap: 8px; - padding: 0px; - height: auto; + background-color: ${({ theme }) => theme.whiteLowOpacity}; + flex-direction: row; + align-content: center; + border-radius: 300px; + gap: 0px; + padding: 0 12px; ` )} `; @@ -33,32 +33,33 @@ const AccountContainer = styled.div` display: flex; align-items: center; width: fit-content; - gap: 12px; + gap: 8px; > label { - color: ${({ theme }) => theme.primaryText}; - font-size: 14px; + font-size: 16px; + font-weight: 600; } - ${smallScreenStyle( + ${landscapeStyle( () => css` - gap: 8px; + gap: 12px; > label { - font-size: 16px; - font-weight: 600; + color: ${({ theme }) => theme.primaryText}; + font-size: 14px; } ` )} `; const ChainConnectionContainer = styled.div` + display: flex; width: fit-content; min-height: 32px; - display: flex; align-items: center; - padding-left: 12px; + padding-left: 0px; > label { color: ${({ theme }) => theme.success}; - font-size: 14px; + font-size: 16px; + font-weight: 500; } @@ -66,31 +67,16 @@ const ChainConnectionContainer = styled.div` content: ""; width: 8px; height: 8px; - margin: 0px 8px 0px 3px; + margin: 0px 13px 0px 3px; border-radius: 50%; background-color: ${({ theme }) => theme.success}; } - ${tabletScreenStyle( + ${landscapeStyle( () => css` display: none; ` )} - - ${smallScreenStyle( - () => css` - padding-left: 0px; - display: flex; - - > label { - font-size: 16px; - } - - :before { - margin: 0px 13px 0px 3px; - } - ` - )} `; const StyledIdenticon = styled(Identicon)<{ size: `${number}` }>` diff --git a/web/src/components/EvidenceCard.tsx b/web/src/components/EvidenceCard.tsx index 3da8d071a..c6f8d0154 100644 --- a/web/src/components/EvidenceCard.tsx +++ b/web/src/components/EvidenceCard.tsx @@ -1,6 +1,6 @@ import React from "react"; import styled, { css } from "styled-components"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import Identicon from "react-identicons"; import { Card } from "@kleros/ui-components-library"; import AttachmentIcon from "svgs/icons/attachment.svg"; @@ -43,16 +43,16 @@ const BottomShade = styled.div` `; const StyledA = styled.a` - gap: calc(5px + (6 - 5) * (min(max(100vw, 375px), 1250px) - 375px) / 875); display: flex; - > svg { - width: 16px; - fill: ${({ theme }) => theme.primaryBlue}; - } + margin-left: auto; + gap: calc(5px + (6 - 5) * (min(max(100vw, 375px), 1250px) - 375px) / 875); - ${smallScreenStyle( + ${landscapeStyle( () => css` - margin-left: auto; + > svg { + width: 16px; + fill: ${({ theme }) => theme.primaryBlue}; + } ` )} `; @@ -76,19 +76,18 @@ const AccountContainer = styled.div` `; const DesktopText = styled.span` - ${smallScreenStyle( + display: none; + ${landscapeStyle( () => css` - display: none; + display: inline; ` )} `; const MobileText = styled.span` - display: none; - - ${smallScreenStyle( + ${landscapeStyle( () => css` - display: inline; + display: none; ` )} `; diff --git a/web/src/components/StatDisplay.tsx b/web/src/components/StatDisplay.tsx index d12dc05a0..79d1073c6 100644 --- a/web/src/components/StatDisplay.tsx +++ b/web/src/components/StatDisplay.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import styled, { useTheme, css } from "styled-components"; const Container = styled.div` @@ -7,11 +7,10 @@ const Container = styled.div` max-width: 196px; align-items: center; gap: 8px; - margin-bottom: calc(16px + (30 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); - ${smallScreenStyle( + ${landscapeStyle( () => css` - margin-bottom: 0px; + margin-bottom: calc(16px + (30 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); ` )} `; diff --git a/web/src/layout/Footer/index.tsx b/web/src/layout/Footer/index.tsx index c51376b9c..e6d27e72c 100644 --- a/web/src/layout/Footer/index.tsx +++ b/web/src/layout/Footer/index.tsx @@ -1,25 +1,25 @@ import React from "react"; import styled, { css } from "styled-components"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import SecuredByKlerosLogo from "svgs/footer/secured-by-kleros.svg"; import { socialmedia } from "consts/socialmedia"; const Container = styled.div` - height: 64px; + height: 80px; width: 100%; background-color: ${({ theme }) => theme.primaryPurple}; display: flex; - flex-direction: row; - justify-content: space-between; + flex-direction: column; + justify-content: center; align-items: center; padding: 0 32px; gap: 16px; - ${smallScreenStyle( + ${landscapeStyle( () => css` - height: 80px; - flex-direction: column; - justify-content: center; + height: 64px; + flex-direction: row; + justify-content: space-between; ` )} diff --git a/web/src/layout/Header/DesktopHeader.tsx b/web/src/layout/Header/DesktopHeader.tsx index d3260bafa..5da2da518 100644 --- a/web/src/layout/Header/DesktopHeader.tsx +++ b/web/src/layout/Header/DesktopHeader.tsx @@ -1,8 +1,8 @@ import React from "react"; import styled, { css } from "styled-components"; +import { landscapeStyle } from "styles/landscapeStyle"; import { useToggle } from "react-use"; import { Link } from "react-router-dom"; -import { smallScreenStyle } from "styles/smallScreenStyle"; import KlerosSolutionsIcon from "svgs/menu-icons/kleros-solutions.svg"; import KlerosCourtLogo from "svgs/header/kleros-court.svg"; import ConnectWallet from "components/ConnectWallet"; @@ -12,15 +12,15 @@ import Explore from "./navbar/Explore"; import Menu from "./navbar/Menu"; const Container = styled.div` - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - position: relative; + display: none; - ${smallScreenStyle( + ${landscapeStyle( () => css` - display: none; + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + position: relative; ` )}; `; diff --git a/web/src/layout/Header/MobileHeader.tsx b/web/src/layout/Header/MobileHeader.tsx index eae620d51..f34626d06 100644 --- a/web/src/layout/Header/MobileHeader.tsx +++ b/web/src/layout/Header/MobileHeader.tsx @@ -1,6 +1,6 @@ import React, { useContext, useRef, useState } from "react"; import styled, { css } from "styled-components"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import { Link } from "react-router-dom"; import KlerosCourtLogo from "svgs/header/kleros-court.svg"; import HamburgerIcon from "svgs/header/hamburger.svg"; @@ -9,31 +9,28 @@ import NavBar from "./navbar"; import { useFocusOutside } from "hooks/useFocusOutside"; const Container = styled.div` - display: none; - ${smallScreenStyle( + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + + ${landscapeStyle( () => css` - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; + display: none; ` )} `; const StyledLightButton = styled(LightButton)` - ${smallScreenStyle( - () => css` - padding: 0; + padding: 0; - .button-svg { - margin-right: 0px; - fill: white; - } - .button-text { - display: none; - } - ` - )} + .button-svg { + margin-right: 0px; + fill: white; + } + .button-text { + display: none; + } `; const OpenContext = React.createContext({ diff --git a/web/src/layout/Header/navbar/DappList.tsx b/web/src/layout/Header/navbar/DappList.tsx index 4200dd1c4..5f9ea3c33 100644 --- a/web/src/layout/Header/navbar/DappList.tsx +++ b/web/src/layout/Header/navbar/DappList.tsx @@ -1,7 +1,7 @@ import React, { useRef } from "react"; import styled, { css } from "styled-components"; import { useLockBodyScroll } from "react-use"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import { useFocusOutside } from "hooks/useFocusOutside"; import Curate from "svgs/icons/curate-image.png"; import Resolver from "svgs/icons/dispute-resolver.svg"; @@ -28,7 +28,9 @@ const Container = styled.div` display: flex; position: absolute; max-height: 60vh; - top: 100%; + top: 5%; + left: 50%; + transform: translateX(-50%); z-index: 10; flex-direction: column; align-items: center; @@ -45,11 +47,11 @@ const Container = styled.div` visibility: visible; } - ${smallScreenStyle( + ${landscapeStyle( () => css` - top: 5%; - left: 50%; - transform: translateX(-50%); + top: 100%; + left: 0%; + transform: translateX(0%); ` )} `; diff --git a/web/src/layout/Header/navbar/Explore.tsx b/web/src/layout/Header/navbar/Explore.tsx index 60c0959aa..1afec3fe7 100644 --- a/web/src/layout/Header/navbar/Explore.tsx +++ b/web/src/layout/Header/navbar/Explore.tsx @@ -1,48 +1,50 @@ import React from "react"; import styled, { css } from "styled-components"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import { Link, useLocation } from "react-router-dom"; import { useOpenContext } from "../MobileHeader"; const Container = styled.div` display: flex; - flex-direction: row; - gap: calc(4px + (16 - 4) * ((100vw - 375px) / (1250 - 375))); - ${smallScreenStyle( + gap: 0px; + flex-direction: column; + + ${landscapeStyle( () => css` - flex-direction: column; - gap: 0px; + flex-direction: row; + gap: calc(4px + (16 - 4) * ((100vw - 375px) / (1250 - 375))); ` )}; `; const LinkContainer = styled.div` display: flex; - .sm-link { - color: ${({ theme }) => theme.white}; - text-decoration: none; - font-size: 16px; - &.active-link { - font-weight: 600; - } - } - ${smallScreenStyle( + min-height: 32px; + align-items: center; +`; + +const Title = styled.h1` + display: block; + + ${landscapeStyle( () => css` - min-height: 32px; - display: flex; - align-items: center; - .sm-link { - color: ${({ theme }) => theme.primaryText}; - } + display: none; ` )}; `; -const Title = styled.h1` - display: none; - ${smallScreenStyle( +const StyledLink = styled(Link)` + color: ${({ theme }) => theme.primaryText}; + text-decoration: none; + font-size: 16px; + + &.active { + font-weight: 600; + } + ${landscapeStyle( () => css` - display: block; + min-height: 32px; + color: ${({ theme }) => theme.white}; ` )}; `; @@ -62,13 +64,13 @@ const Explore: React.FC = () => { Explore {links.map(({ to, text }) => ( - {text} - + ))}
diff --git a/web/src/layout/Header/navbar/Menu/Help.tsx b/web/src/layout/Header/navbar/Menu/Help.tsx index c92ca04df..36c75b28c 100644 --- a/web/src/layout/Header/navbar/Menu/Help.tsx +++ b/web/src/layout/Header/navbar/Menu/Help.tsx @@ -1,7 +1,7 @@ import React, { useRef } from "react"; import styled, { css } from "styled-components"; import { useLockBodyScroll } from "react-use"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import { useFocusOutside } from "hooks/useFocusOutside"; import Book from "svgs/icons/book-open.svg"; import Guide from "svgs/icons/book.svg"; @@ -15,8 +15,9 @@ const Container = styled.div` display: flex; flex-direction: column; position: absolute; - width: 240px; - top: 100%; + width: auto; + top: 5%; + left: 50%; transform: translateX(-50%); z-index: 1; padding: 27px 10px; @@ -26,12 +27,11 @@ const Container = styled.div` border-radius: 3px; box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.06); - ${smallScreenStyle( + ${landscapeStyle( () => css` - top: 5%; - left: 50%; - transform: translateX(-50%); - width: auto; + top: 100%; + left: 92%; + width: 240px; ` )} `; diff --git a/web/src/layout/Header/navbar/Menu/Settings/index.tsx b/web/src/layout/Header/navbar/Menu/Settings/index.tsx index 69d621f69..428d1c472 100644 --- a/web/src/layout/Header/navbar/Menu/Settings/index.tsx +++ b/web/src/layout/Header/navbar/Menu/Settings/index.tsx @@ -1,7 +1,7 @@ import React, { Dispatch, SetStateAction, useRef, useState } from "react"; import styled, { css } from "styled-components"; import { useLockBodyScroll } from "react-use"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import { Tabs } from "@kleros/ui-components-library"; import General from "./General"; import SendMeNotifications from "./SendMeNotifications"; @@ -12,19 +12,20 @@ const Container = styled.div` display: flex; position: absolute; flex-direction: column; - top: 100%; - transform: translateX(-75%); + top: 5%; + left: 50%; + transform: translateX(-50%); z-index: 1; background-color: ${({ theme }) => theme.whiteBackground}; border: 1px solid ${({ theme }) => theme.stroke}; border-radius: 3px; overflow-y: auto; - ${smallScreenStyle( + ${landscapeStyle( () => css` - top: 5%; - left: 50%; - transform: translateX(-50%); + top: 100%; + left: 92%; + transform: translateX(-75%); ` )} `; diff --git a/web/src/layout/Header/navbar/Menu/index.tsx b/web/src/layout/Header/navbar/Menu/index.tsx index 517a764b8..eb608867c 100644 --- a/web/src/layout/Header/navbar/Menu/index.tsx +++ b/web/src/layout/Header/navbar/Menu/index.tsx @@ -1,6 +1,6 @@ import React, { useState } from "react"; import styled, { css } from "styled-components"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import { useToggle } from "react-use"; import LightButton from "components/LightButton"; import Help from "./Help"; @@ -14,12 +14,14 @@ import { useToggleTheme } from "hooks/useToggleThemeContext"; const Container = styled.div` display: flex; - flex-direction: row; - gap: 8px; - ${smallScreenStyle( + + flex-direction: column; + gap: 0px; + + ${landscapeStyle( () => css` - flex-direction: column; - gap: 0px; + flex-direction: row; + gap: 8px; ` )} `; @@ -34,20 +36,20 @@ const ButtonContainer = styled.div` } .button-text { - display: none; + display: block; } .button-svg { - fill: ${({ theme }) => theme.white}; + fill: ${({ theme }) => theme.secondaryPurple}; } - ${smallScreenStyle( + ${landscapeStyle( () => css` .button-svg { - fill: ${({ theme }) => theme.secondaryPurple}; + fill: ${({ theme }) => theme.white}; } .button-text { - display: block; + display: none; } ` )} diff --git a/web/src/layout/Header/navbar/index.tsx b/web/src/layout/Header/navbar/index.tsx index ff6c0f868..baa7f9bdc 100644 --- a/web/src/layout/Header/navbar/index.tsx +++ b/web/src/layout/Header/navbar/index.tsx @@ -1,6 +1,5 @@ import React from "react"; -import styled, { css } from "styled-components"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import styled from "styled-components"; import { useLockBodyScroll, useToggle } from "react-use"; import { useAccount } from "wagmi"; import ConnectWallet from "components/ConnectWallet"; @@ -14,32 +13,27 @@ import Debug from "./Debug"; import { DisconnectWalletButton } from "./Menu/Settings/General"; const Container = styled.div<{ isOpen: boolean }>` - ${({ isOpen }) => - smallScreenStyle( - () => css` - position: absolute; - top: 64px; - left: 0; - right: 0; - z-index: 1; - background-color: ${({ theme }) => theme.whiteBackground}; - border: 1px solid ${({ theme }) => theme.stroke}; - box-shadow: 0px 2px 3px ${({ theme }) => theme.defaultShadow}; + position: absolute; + top: 64px; + left: 0; + right: 0; + z-index: 1; + background-color: ${({ theme }) => theme.whiteBackground}; + border: 1px solid ${({ theme }) => theme.stroke}; + box-shadow: 0px 2px 3px ${({ theme }) => theme.defaultShadow}; - transform-origin: top; - transform: scaleY(${isOpen ? "1" : "0"}); - visibility: ${isOpen ? "visible" : "hidden"}; - transition-property: transform, visibility; - transition-duration: ${({ theme }) => theme.transitionSpeed}; - transition-timing-function: ease; + transform-origin: top; + transform: scaleY(${({ isOpen }) => (isOpen ? "1" : "0")}); + visibility: ${({ isOpen }) => (isOpen ? "visible" : "hidden")}; + transition-property: transform, visibility; + transition-duration: ${({ theme }) => theme.transitionSpeed}; + transition-timing-function: ease; - padding: 24px; + padding: 24px; - hr { - margin: 24px 0; - } - ` - )} + hr { + margin: 24px 0; + } `; const WalletContainer = styled.div` diff --git a/web/src/pages/Cases/CaseDetails/Overview.tsx b/web/src/pages/Cases/CaseDetails/Overview.tsx index 0dc546168..13c1fcff4 100644 --- a/web/src/pages/Cases/CaseDetails/Overview.tsx +++ b/web/src/pages/Cases/CaseDetails/Overview.tsx @@ -1,6 +1,6 @@ import React from "react"; import styled, { css } from "styled-components"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import { useParams } from "react-router-dom"; import ReactMarkdown from "react-markdown"; import { formatEther } from "viem"; @@ -59,26 +59,26 @@ const Answers = styled.div` const ShadeArea = styled.div` display: flex; - flex-direction: row; - justify-content: space-between; + flex-direction: column; + justify-content: center; width: 100%; padding: calc(16px + (32 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); margin-top: calc(24px + (48 - 24) * (min(max(100vw, 375px), 1250px) - 375px) / 875); background-color: ${({ theme }) => theme.mediumBlue}; > p { margin-top: 0; - margin-bottom: 0; - ${smallScreenStyle( + margin-bottom: 16px; + ${landscapeStyle( () => css` - margin-bottom: 16px; + margin-bottom: 0; ` )}; } - ${smallScreenStyle( + ${landscapeStyle( () => css` - flex-direction: column; - justify-content: center; + flex-direction: row; + justify-content: space-between; ` )}; `; diff --git a/web/src/pages/Cases/CaseDetails/Timeline.tsx b/web/src/pages/Cases/CaseDetails/Timeline.tsx index f2db7f2bb..7f83833a1 100644 --- a/web/src/pages/Cases/CaseDetails/Timeline.tsx +++ b/web/src/pages/Cases/CaseDetails/Timeline.tsx @@ -1,6 +1,6 @@ import React from "react"; import styled, { css } from "styled-components"; -import { tabletScreenStyle } from "styles/tabletScreenStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import { Periods } from "consts/periods"; import { DisputeDetailsQuery } from "queries/useDisputeDetailsQuery"; import { Box, Steps } from "@kleros/ui-components-library"; @@ -9,18 +9,19 @@ import { useCountdown } from "hooks/useCountdown"; import { secondsToDayHourMinute } from "utils/date"; const TimeLineContainer = styled(Box)` - display: flex; + display: block; width: 100%; height: 98px; border-radius: 0px; + padding: 20px 8px 0px 8px; margin-top: calc(16px + (48 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); margin-bottom: calc(12px + (22 - 12) * (min(max(100vw, 375px), 1250px) - 375px) / 875); background-color: ${({ theme }) => theme.whiteBackground}; - ${tabletScreenStyle( + ${landscapeStyle( () => css` - padding: 20px 8px 8px 8px; display: block; + padding: 28px 8px 8px 8px; ` )} `; @@ -33,21 +34,19 @@ const StyledSteps = styled(Steps)`d `; const TitleMobile = styled.span` - display: none; - - ${tabletScreenStyle( + ${landscapeStyle( () => css` - display: inline-block; + display: none; ` )} `; const TitleDesktop = styled(TitleMobile)` - display: inline-block; + display: none; - ${tabletScreenStyle( + ${landscapeStyle( () => css` - display: none; + display: inline-block; ` )} `; diff --git a/web/src/pages/Courts/CourtDetails/Stats.tsx b/web/src/pages/Courts/CourtDetails/Stats.tsx index 7771006b1..960293abb 100644 --- a/web/src/pages/Courts/CourtDetails/Stats.tsx +++ b/web/src/pages/Courts/CourtDetails/Stats.tsx @@ -1,6 +1,6 @@ import React from "react"; import styled, { css } from "styled-components"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import { useParams } from "react-router-dom"; import { useCourtDetails, CourtDetailsQuery } from "queries/useCourtDetails"; import { useCoinPrice } from "hooks/useCoinPrice"; @@ -21,14 +21,14 @@ const StyledCard = styled.div` width: auto; height: fit-content; display: grid; - gap: 16px; + gap: 32px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); padding: calc(0px + (32 - 0) * (min(max(100vw, 375px), 1250px) - 375px) / 875) 0; padding-bottom: 0px; - ${smallScreenStyle( + ${landscapeStyle( () => css` - gap: 32px; + gap: 16px; ` )} `; diff --git a/web/src/pages/Dashboard/JurorInfo/index.tsx b/web/src/pages/Dashboard/JurorInfo/index.tsx index 6e6b9ced8..64e4636ae 100644 --- a/web/src/pages/Dashboard/JurorInfo/index.tsx +++ b/web/src/pages/Dashboard/JurorInfo/index.tsx @@ -1,6 +1,6 @@ import React from "react"; import styled, { css } from "styled-components"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import { Card as _Card } from "@kleros/ui-components-library"; import Coherency from "./Coherency"; import JurorRewards from "./JurorRewards"; @@ -19,17 +19,18 @@ const Card = styled(_Card)` const Layout = styled.div` display: flex; - flex-direction: row; + flex-direction: column; align-items: center; justify-content: center; - gap: 48px; + + gap: 24px; width: auto; margin: 16px 32px; - ${smallScreenStyle( + ${landscapeStyle( () => css` - flex-direction: column; - gap: 24px; + flex-direction: row; + gap: 48px; ` )} `; diff --git a/web/src/pages/Home/Community/index.tsx b/web/src/pages/Home/Community/index.tsx index fc5df011f..cbfd5ca44 100644 --- a/web/src/pages/Home/Community/index.tsx +++ b/web/src/pages/Home/Community/index.tsx @@ -1,6 +1,6 @@ import React from "react"; import styled, { css } from "styled-components"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import { Card } from "@kleros/ui-components-library"; import { Element } from "./Element"; import { firstSection, secondSection } from "consts/community-elements"; @@ -24,33 +24,35 @@ const StyledSeparator = styled.hr` const Section = styled.div` width: 100%; - min-height: 64px; + gap: 8px; + flex-direction: column; + height: auto; flex-wrap: wrap; - padding: 0 32px; + padding: 12px; display: flex; align-items: center; - justify-content: space-between; + justify-content: center; - ${smallScreenStyle( + ${landscapeStyle( () => css` - flex-direction: column; - justify-content: center; - gap: 8px; - padding: 12px; - height: auto; + flex-direction: row; + justify-content: space-between; + gap: 0px; + padding: 0 32px; + min-height: 64px; ` )} `; const TwoElementContainer = styled.div` display: flex; - flex-direction: row; - gap: 48px; + flex-direction: column; + gap: 8px; - ${smallScreenStyle( + ${landscapeStyle( () => css` - flex-direction: column; - gap: 8px; + flex-direction: row; + gap: 48px; ` )} `; diff --git a/web/src/pages/Home/CourtOverview/Stats.tsx b/web/src/pages/Home/CourtOverview/Stats.tsx index 160c2b36e..6fbd57fa0 100644 --- a/web/src/pages/Home/CourtOverview/Stats.tsx +++ b/web/src/pages/Home/CourtOverview/Stats.tsx @@ -1,6 +1,6 @@ import React from "react"; import styled, { css } from "styled-components"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import { Card } from "@kleros/ui-components-library"; import StatDisplay, { IStatDisplay } from "components/StatDisplay"; import { StyledSkeleton } from "components/StyledSkeleton"; @@ -19,16 +19,17 @@ import { useCoinPrice } from "hooks/useCoinPrice"; const StyledCard = styled(Card)` width: auto; height: fit-content; + gap: 32px; padding: calc(16px + (30 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); padding-left: calc(16px + (35 - 16) * (min(max(100vw, 375px), 1250px) - 375px) / 875); - padding-bottom: 0px; + padding-bottom: 16px; display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); - ${smallScreenStyle( + ${landscapeStyle( () => css` - padding-bottom: 16px; - gap: 32px; + padding-bottom: 0px; + gap: 0px; ` )} `; diff --git a/web/src/pages/Home/Header.tsx b/web/src/pages/Home/Header.tsx deleted file mode 100644 index f420b93bf..000000000 --- a/web/src/pages/Home/Header.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from "react"; -import { useTheme } from "styled-components"; -import { useWindowSize } from "react-use"; -import { BREAKPOINT_SMALL_SCREEN } from "styles/smallScreenStyle"; -import HeaderLightMobile from "tsx:svgs/header/header-lightmode-mobile.svg"; -import HeaderDarkMobile from "tsx:svgs/header/header-darkmode-mobile.svg"; -import HeaderLightDesktop from "tsx:svgs/header/header-lightmode-desktop.svg"; -import HeaderDarkDesktop from "tsx:svgs/header/header-darkmode-desktop.svg"; - -const Header = () => { - const { width } = useWindowSize(); - const theme = useTheme(); - const themeIsLight = theme.name === "light"; - const screenIsBig = width > BREAKPOINT_SMALL_SCREEN; - return
{screenIsBig ? : }
; -}; - -const HeaderDesktop: React.FC<{ themeIsLight: boolean }> = ({ themeIsLight }) => { - return themeIsLight ? : ; -}; - -const HeaderMobile: React.FC<{ themeIsLight: boolean }> = ({ themeIsLight }) => { - return themeIsLight ? : ; -}; - -export default Header; diff --git a/web/src/pages/Home/HeroImage.tsx b/web/src/pages/Home/HeroImage.tsx new file mode 100644 index 000000000..3170244b5 --- /dev/null +++ b/web/src/pages/Home/HeroImage.tsx @@ -0,0 +1,26 @@ +import React from "react"; +import { useTheme } from "styled-components"; +import { useWindowSize } from "react-use"; +import { BREAKPOINT_LANDSCAPE } from "styles/landscapeStyle"; +import HeroLightMobile from "tsx:svgs/hero/hero-lightmode-mobile.svg"; +import HeroDarkMobile from "tsx:svgs/hero/hero-darkmode-mobile.svg"; +import HeroLightDesktop from "tsx:svgs/hero/hero-lightmode-desktop.svg"; +import HeroDarkDesktop from "tsx:svgs/hero/hero-darkmode-desktop.svg"; + +const HeroImage = () => { + const { width } = useWindowSize(); + const theme = useTheme(); + const themeIsLight = theme.name === "light"; + const screenIsBig = width > BREAKPOINT_LANDSCAPE; + return
{screenIsBig ? : }
; +}; + +const HeroDesktop: React.FC<{ themeIsLight: boolean }> = ({ themeIsLight }) => { + return themeIsLight ? : ; +}; + +const HeroMobile: React.FC<{ themeIsLight: boolean }> = ({ themeIsLight }) => { + return themeIsLight ? : ; +}; + +export default HeroImage; diff --git a/web/src/pages/Home/index.tsx b/web/src/pages/Home/index.tsx index 3002b16ab..cb1168923 100644 --- a/web/src/pages/Home/index.tsx +++ b/web/src/pages/Home/index.tsx @@ -3,7 +3,7 @@ import styled from "styled-components"; import CourtOverview from "./CourtOverview"; import LatestCases from "./LatestCases"; import Community from "./Community"; -import Header from "./Header"; +import HeroImage from "./HeroImage"; import { HomePageProvider } from "hooks/useHomePageContext"; import { getOneYearAgoTimestamp } from "utils/date"; @@ -19,7 +19,7 @@ const Container = styled.div` const Home: React.FC = () => { return ( -
+ diff --git a/web/src/styles/landscapeStyle.ts b/web/src/styles/landscapeStyle.ts new file mode 100644 index 000000000..a54121f1f --- /dev/null +++ b/web/src/styles/landscapeStyle.ts @@ -0,0 +1,9 @@ +import { css, DefaultTheme, FlattenInterpolation, ThemeProps } from "styled-components"; + +export const BREAKPOINT_LANDSCAPE = 900; + +export const landscapeStyle = (styleFn: () => FlattenInterpolation>) => css` + @media (min-width: ${BREAKPOINT_LANDSCAPE}px) { + ${() => styleFn()} + } +`; diff --git a/web/src/styles/portraitStyle.ts b/web/src/styles/portraitStyle.ts new file mode 100644 index 000000000..00fd3c062 --- /dev/null +++ b/web/src/styles/portraitStyle.ts @@ -0,0 +1,9 @@ +import { css, DefaultTheme, FlattenInterpolation, ThemeProps } from "styled-components"; + +export const BREAKPOINT_PORTRAIT = 600; + +export const portraitStyle = (styleFn: () => FlattenInterpolation>) => css` + @media (min-width: ${BREAKPOINT_PORTRAIT}px) { + ${() => styleFn()} + } +`; diff --git a/web/src/styles/smallScreenStyle.ts b/web/src/styles/smallScreenStyle.ts deleted file mode 100644 index fc7c68e19..000000000 --- a/web/src/styles/smallScreenStyle.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { css, DefaultTheme, FlattenInterpolation, ThemeProps } from "styled-components"; - -export const BREAKPOINT_SMALL_SCREEN = 768; - -export const smallScreenStyle = (styleFn: () => FlattenInterpolation>) => css` - @media (max-width: ${BREAKPOINT_SMALL_SCREEN}px) { - ${() => styleFn()} - } -`; diff --git a/web/src/styles/tabletScreenStyle.ts b/web/src/styles/tabletScreenStyle.ts deleted file mode 100644 index 7b1fe25e7..000000000 --- a/web/src/styles/tabletScreenStyle.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { css, DefaultTheme, FlattenInterpolation, ThemeProps } from "styled-components"; - -export const BREAKPOINT_TABLET_SCREEN = 1024; - -export const tabletScreenStyle = (styleFn: () => FlattenInterpolation>) => css` - @media (max-width: ${BREAKPOINT_TABLET_SCREEN}px) { - ${() => styleFn()} - } -`; From 6d76597e1498dd4a3acbaecb4c4b12f21a12baf0 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Mon, 11 Sep 2023 18:38:48 +0200 Subject: [PATCH 20/38] fix(web): font-weight of wallet address and margin top on Navbar --- web/src/components/ConnectWallet/AccountDisplay.tsx | 1 + web/src/layout/Header/DesktopHeader.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/web/src/components/ConnectWallet/AccountDisplay.tsx b/web/src/components/ConnectWallet/AccountDisplay.tsx index 9f97f38e5..d39e7c60e 100644 --- a/web/src/components/ConnectWallet/AccountDisplay.tsx +++ b/web/src/components/ConnectWallet/AccountDisplay.tsx @@ -45,6 +45,7 @@ const AccountContainer = styled.div` gap: 12px; > label { color: ${({ theme }) => theme.primaryText}; + font-weight: 400; font-size: 14px; } ` diff --git a/web/src/layout/Header/DesktopHeader.tsx b/web/src/layout/Header/DesktopHeader.tsx index 5da2da518..93ad5be88 100644 --- a/web/src/layout/Header/DesktopHeader.tsx +++ b/web/src/layout/Header/DesktopHeader.tsx @@ -34,6 +34,7 @@ const MiddleSide = styled.div` position: absolute; left: 50%; transform: translateX(-50%); + margin-top: 8px; color: ${({ theme }) => theme.white} !important; `; From f708cfe05065473080ab42050e3f0f1a344ba2b5 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Mon, 11 Sep 2023 18:50:40 +0200 Subject: [PATCH 21/38] fix(web): center vertically middle side component of desktop header --- web/src/layout/Header/DesktopHeader.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/layout/Header/DesktopHeader.tsx b/web/src/layout/Header/DesktopHeader.tsx index 93ad5be88..e5a4aa8f2 100644 --- a/web/src/layout/Header/DesktopHeader.tsx +++ b/web/src/layout/Header/DesktopHeader.tsx @@ -33,8 +33,8 @@ const MiddleSide = styled.div` display: flex; position: absolute; left: 50%; - transform: translateX(-50%); - margin-top: 8px; + top: 50%; + transform: translate(-50%, -50%); color: ${({ theme }) => theme.white} !important; `; From d05f1961351b935fa2e9372d4c01cadd0122a12d Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Mon, 11 Sep 2023 19:00:58 +0200 Subject: [PATCH 22/38] fix(web): weird min-height property causing problems --- web/src/layout/Header/navbar/Explore.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/web/src/layout/Header/navbar/Explore.tsx b/web/src/layout/Header/navbar/Explore.tsx index 1afec3fe7..2891ef794 100644 --- a/web/src/layout/Header/navbar/Explore.tsx +++ b/web/src/layout/Header/navbar/Explore.tsx @@ -43,7 +43,6 @@ const StyledLink = styled(Link)` } ${landscapeStyle( () => css` - min-height: 32px; color: ${({ theme }) => theme.white}; ` )}; From d7c876c6749bfe47f8b0e682f83d17f12a4d3cc1 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Mon, 11 Sep 2023 21:53:11 +0200 Subject: [PATCH 23/38] refactor(web): remove classname syntax for boolean in styled components --- web/src/layout/Header/navbar/Explore.tsx | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/web/src/layout/Header/navbar/Explore.tsx b/web/src/layout/Header/navbar/Explore.tsx index 2891ef794..816e3b643 100644 --- a/web/src/layout/Header/navbar/Explore.tsx +++ b/web/src/layout/Header/navbar/Explore.tsx @@ -33,14 +33,13 @@ const Title = styled.h1` )}; `; -const StyledLink = styled(Link)` +const StyledLink = styled(Link)<{ isActive: boolean }>` color: ${({ theme }) => theme.primaryText}; text-decoration: none; font-size: 16px; - &.active { - font-weight: 600; - } + font-weight: ${({ isActive }) => (isActive ? "600" : "normal")}; + ${landscapeStyle( () => css` color: ${({ theme }) => theme.white}; @@ -63,11 +62,7 @@ const Explore: React.FC = () => { Explore {links.map(({ to, text }) => ( - + {text} From 633f50f9537369c095c8c7ca6a18ed759d027544 Mon Sep 17 00:00:00 2001 From: nhestrompia Date: Tue, 12 Sep 2023 04:09:04 +0300 Subject: [PATCH 24/38] fix: responsive layout --- web/src/components/CasesDisplay/CasesGrid.tsx | 4 +- .../CasesDisplay/CasesListHeader.tsx | 47 ++++++++----------- web/src/components/CasesDisplay/Filters.tsx | 17 ++++++- .../components/DisputeCard/DisputeInfo.tsx | 14 ++++-- web/src/components/DisputeCard/index.tsx | 8 ++-- web/src/components/Field.tsx | 4 +- web/src/pages/Cases/CaseDetails/Overview.tsx | 11 ++++- web/src/pages/Cases/index.tsx | 4 +- web/src/pages/Home/Header.tsx | 4 +- web/src/styles/landscapeStyle.ts | 9 ++++ web/src/styles/portraitStyle.ts | 9 ++++ web/src/styles/smallScreenStyle.ts | 9 ---- web/src/styles/tabletScreenStyle.ts | 9 ---- 13 files changed, 87 insertions(+), 62 deletions(-) create mode 100644 web/src/styles/landscapeStyle.ts create mode 100644 web/src/styles/portraitStyle.ts delete mode 100644 web/src/styles/smallScreenStyle.ts delete mode 100644 web/src/styles/tabletScreenStyle.ts diff --git a/web/src/components/CasesDisplay/CasesGrid.tsx b/web/src/components/CasesDisplay/CasesGrid.tsx index ad5d96857..25fbeaf4d 100644 --- a/web/src/components/CasesDisplay/CasesGrid.tsx +++ b/web/src/components/CasesDisplay/CasesGrid.tsx @@ -1,7 +1,7 @@ import React from "react"; import styled, { css } from "styled-components"; import { StandardPagination } from "@kleros/ui-components-library"; -import { tabletScreenStyle } from "styles/tabletScreenStyle"; +import { portraitStyle } from "styles/portraitStyle"; import { useFiltersContext } from "context/FilterProvider"; import { CasesPageQuery } from "queries/useCasesQuery"; import DisputeCard from "components/DisputeCard"; @@ -15,7 +15,7 @@ const GridContainer = styled.div` justify-content: space-between; align-items: center; justify-items: center; - ${tabletScreenStyle(css` + ${portraitStyle(css` display: flex; flex-wrap: wrap; justify-content: center; diff --git a/web/src/components/CasesDisplay/CasesListHeader.tsx b/web/src/components/CasesDisplay/CasesListHeader.tsx index de51a6717..df4be5b0f 100644 --- a/web/src/components/CasesDisplay/CasesListHeader.tsx +++ b/web/src/components/CasesDisplay/CasesListHeader.tsx @@ -1,41 +1,32 @@ import React from "react"; import styled, { css } from "styled-components"; -import { smallScreenStyle } from "styles/smallScreenStyle"; +import { portraitStyle } from "styles/portraitStyle"; import WithHelpTooltip from "pages/Dashboard/WithHelpTooltip"; const Container = styled.div` display: flex; justify-content: space-between; - gap: 40vw; + gap: calc(15vw + (40 - 15) * ((100vw - 300px) / (1250 - 300))); width: 100%; height: 100%; `; const CasesData = styled.div` display: flex; - flex-wrap: wrap; align-items: center; + justify-content: space-around; width: 100%; - gap: 48px; + margin-left: calc(0px + (33) * (100vw - 370px) / (1250 - 370)); + gap: 12px; flex-wrap: wrap; - padding: 0 4%; - justify-content: space-between; - ${smallScreenStyle(css` - margin-left: calc(0px + (33) * (100vw - 370px) / (1250 - 370)); - gap: 12px; + padding: 0 3%; + ${portraitStyle(css` + gap: calc(24px + (48 - 24) * ((100vw - 300px) / (1250 - 300))); `)} `; -const CategoryLabel = styled.label` - margin-left: 32px; -`; - -const RewardsContainer = styled.div` - margin-right: -16px; -`; - const CaseTitle = styled.div` - display: flex; + display: none; margin-left: 32px; gap: 36px; label { @@ -45,11 +36,15 @@ const CaseTitle = styled.div` color: ${({ theme }) => theme.secondaryText} !important; } - ${smallScreenStyle(css` - display: none; + ${portraitStyle(css` + display: flex; `)} `; +const CategoryLabel = styled.label` + padding-left: calc(4px + (12 - 4) * ((100vw - 300px) / (900 - 300))); +`; + const tooltipMsg = "Users have an economic interest in serving as jurors in Kleros: " + "collecting the Juror Rewards in exchange for their work. Each juror who " + @@ -64,13 +59,11 @@ const CasesListHeader: React.FC = () => { - - Category - - - - - + Court + + + + diff --git a/web/src/components/CasesDisplay/Filters.tsx b/web/src/components/CasesDisplay/Filters.tsx index a4b596cd7..894b8487c 100644 --- a/web/src/components/CasesDisplay/Filters.tsx +++ b/web/src/components/CasesDisplay/Filters.tsx @@ -1,7 +1,9 @@ import React from "react"; import styled, { useTheme } from "styled-components"; +import { useWindowSize } from "react-use"; import { DropdownSelect } from "@kleros/ui-components-library"; import { useFiltersContext } from "context/FilterProvider"; +import { BREAKPOINT_LANDSCAPE } from "styles/landscapeStyle"; import ListIcon from "svgs/icons/list.svg"; import GridIcon from "svgs/icons/grid.svg"; @@ -27,8 +29,9 @@ const IconsContainer = styled.div` gap: 4px; `; -const StyledListIcon = styled(ListIcon)<{ isList: boolean }>` +const StyledListIcon = styled(ListIcon)<{ isList: boolean; isScreenBig: boolean }>` cursor: pointer; + display: ${({ isScreenBig }) => (isScreenBig ? "block" : "none")}; transition: fill 0.2s ease; fill: ${({ theme, isList }) => (isList ? theme.primaryBlue : theme.secondaryText)}; width: 16px; @@ -37,7 +40,9 @@ const StyledListIcon = styled(ListIcon)<{ isList: boolean }>` const Filters: React.FC = () => { const theme = useTheme(); + const { width } = useWindowSize(); const { isList, setIsList } = useFiltersContext(); + const screenIsBig = width > BREAKPOINT_LANDSCAPE; return ( @@ -65,7 +70,15 @@ const Filters: React.FC = () => { /> setIsList(false)} /> - setIsList(true)} /> + { + if (screenIsBig) { + setIsList(true); + } + }} + /> ); diff --git a/web/src/components/DisputeCard/DisputeInfo.tsx b/web/src/components/DisputeCard/DisputeInfo.tsx index bf8b3c88e..07816fec4 100644 --- a/web/src/components/DisputeCard/DisputeInfo.tsx +++ b/web/src/components/DisputeCard/DisputeInfo.tsx @@ -1,5 +1,5 @@ import React from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; import { useFiltersContext } from "context/FilterProvider"; import { Periods } from "consts/periods"; import BookmarkIcon from "svgs/icons/bookmark.svg"; @@ -11,8 +11,14 @@ import Field from "../Field"; const Container = styled.div<{ isList: boolean }>` display: flex; flex-direction: ${({ isList }) => (isList ? "row" : "column")}; - gap: ${({ isList }) => (isList ? "48px" : "8px")}; - justify-content: ${({ isList }) => (isList ? "space-between" : "center")}; + gap: 8px; + + ${({ isList }) => + isList && + css` + gap: calc(4px + (24px - 4px) * ((100vw - 300px) / (900 - 300))); + `}; + justify-content: ${({ isList }) => (isList ? "space-around" : "center")}; align-items: center; width: 100%; height: 100%; @@ -49,10 +55,12 @@ const formatDate = (date: number) => { const DisputeInfo: React.FC = ({ courtId, court, category, rewards, period, date }) => { const { isList } = useFiltersContext(); + return ( {court && courtId && } {category && } + {!category && isList && } {rewards && } {typeof period !== "undefined" && date && ( ` - width: ${({ width = "100%" }) => width}; + width: ${({ isList }) => (isList ? "auto" : "100%")}; display: flex; align-items: center; justify-content: flex-start; white-space: nowrap; .value { - flex-grow: 1; + flex-grow: ${({ isList }) => (isList ? "0" : "1")}; text-align: ${({ isList }) => (isList ? "center" : "end")}; color: ${({ theme }) => theme.primaryText}; } diff --git a/web/src/pages/Cases/CaseDetails/Overview.tsx b/web/src/pages/Cases/CaseDetails/Overview.tsx index 7de07014f..5e465ce8f 100644 --- a/web/src/pages/Cases/CaseDetails/Overview.tsx +++ b/web/src/pages/Cases/CaseDetails/Overview.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect } from "react"; import styled from "styled-components"; import { useParams } from "react-router-dom"; import ReactMarkdown from "react-markdown"; @@ -7,6 +7,7 @@ import { useDisputeDetailsQuery } from "queries/useDisputeDetailsQuery"; import { useDisputeTemplate } from "queries/useDisputeTemplate"; import { useCourtPolicy } from "queries/useCourtPolicy"; import { useCourtPolicyURI } from "queries/useCourtPolicyURI"; +import { useFiltersContext } from "context/FilterProvider"; import { isUndefined } from "utils/index"; import { Periods } from "consts/periods"; import { IPFS_GATEWAY } from "consts/index"; @@ -86,10 +87,18 @@ const Overview: React.FC = ({ arbitrable, courtID, currentPeriodIndex const { data: disputeDetails } = useDisputeDetailsQuery(id); const { data: courtPolicyURI } = useCourtPolicyURI(courtID); const { data: courtPolicy } = useCourtPolicy(courtID); + const { isList, setIsList } = useFiltersContext(); const courtName = courtPolicy?.name; const court = disputeDetails?.dispute?.court; const rewards = court ? `≥ ${formatEther(court.feeForJuror)} ETH` : undefined; const category = disputeTemplate ? disputeTemplate.category : undefined; + + useEffect(() => { + if (isList) { + setIsList(false); + } + }, []); + return ( <> diff --git a/web/src/pages/Cases/index.tsx b/web/src/pages/Cases/index.tsx index ec746e268..00e8f7f78 100644 --- a/web/src/pages/Cases/index.tsx +++ b/web/src/pages/Cases/index.tsx @@ -3,7 +3,7 @@ import styled from "styled-components"; import { Routes, Route } from "react-router-dom"; import { useCasesQuery } from "queries/useCasesQuery"; import { useWindowSize } from "react-use"; -import { BREAKPOINT_TABLET_SCREEN } from "styles/tabletScreenStyle"; +import { BREAKPOINT_LANDSCAPE } from "styles/landscapeStyle"; import CasesDisplay from "components/CasesDisplay"; import CaseDetails from "./CaseDetails"; import { useFiltersContext } from "context/FilterProvider"; @@ -20,7 +20,7 @@ const Cases: React.FC = () => { const [currentPage, setCurrentPage] = useState(1); const { width } = useWindowSize(); const { isList, setIsList } = useFiltersContext(); - const screenIsBig = width > BREAKPOINT_TABLET_SCREEN; + const screenIsBig = width > BREAKPOINT_LANDSCAPE; const casesPerPage = screenIsBig ? 9 : 3; const { data } = useCasesQuery(casesPerPage * (currentPage - 1), casesPerPage); diff --git a/web/src/pages/Home/Header.tsx b/web/src/pages/Home/Header.tsx index 05c825635..17d0e7e96 100644 --- a/web/src/pages/Home/Header.tsx +++ b/web/src/pages/Home/Header.tsx @@ -1,7 +1,7 @@ import React from "react"; import { useTheme } from "styled-components"; import { useMeasure } from "react-use"; -import { BREAKPOINT_SMALL_SCREEN } from "styles/smallScreenStyle"; +import { BREAKPOINT_LANDSCAPE } from "styles/landscapeStyle"; import HeaderLightMobile from "tsx:svgs/header/header-lightmode-mobile.svg"; import HeaderDarkMobile from "tsx:svgs/header/header-darkmode-mobile.svg"; import HeaderLightDesktop from "tsx:svgs/header/header-lightmode-desktop.svg"; @@ -11,7 +11,7 @@ const Header = () => { const [ref, { width }] = useMeasure(); const theme = useTheme(); const themeIsLight = theme.name === "light"; - const screenIsBig = width > BREAKPOINT_SMALL_SCREEN; + const screenIsBig = width > BREAKPOINT_LANDSCAPE; return (
{screenIsBig ? : } diff --git a/web/src/styles/landscapeStyle.ts b/web/src/styles/landscapeStyle.ts new file mode 100644 index 000000000..69205ca07 --- /dev/null +++ b/web/src/styles/landscapeStyle.ts @@ -0,0 +1,9 @@ +import { css, FlattenSimpleInterpolation } from "styled-components"; + +export const BREAKPOINT_LANDSCAPE = 900; + +export const landscapeStyle = (style: FlattenSimpleInterpolation) => css` + @media (min-width: ${BREAKPOINT_LANDSCAPE}px) { + ${style} + } +`; diff --git a/web/src/styles/portraitStyle.ts b/web/src/styles/portraitStyle.ts new file mode 100644 index 000000000..540bb3d96 --- /dev/null +++ b/web/src/styles/portraitStyle.ts @@ -0,0 +1,9 @@ +import { css, FlattenSimpleInterpolation } from "styled-components"; + +export const BREAKPOINT_PORTRAIT = 600; + +export const portraitStyle = (style: FlattenSimpleInterpolation) => css` + @media (min-width: ${BREAKPOINT_PORTRAIT}px) { + ${style} + } +`; diff --git a/web/src/styles/smallScreenStyle.ts b/web/src/styles/smallScreenStyle.ts deleted file mode 100644 index 10ee1e008..000000000 --- a/web/src/styles/smallScreenStyle.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { css, FlattenSimpleInterpolation } from "styled-components"; - -export const BREAKPOINT_SMALL_SCREEN = 768; - -export const smallScreenStyle = (style: FlattenSimpleInterpolation) => css` - @media (max-width: ${BREAKPOINT_SMALL_SCREEN}px) { - ${style} - } -`; diff --git a/web/src/styles/tabletScreenStyle.ts b/web/src/styles/tabletScreenStyle.ts deleted file mode 100644 index b047e6603..000000000 --- a/web/src/styles/tabletScreenStyle.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { css, FlattenSimpleInterpolation } from "styled-components"; - -export const BREAKPOINT_TABLET_SCREEN = 1024; - -export const tabletScreenStyle = (style: FlattenSimpleInterpolation) => css` - @media (max-width: ${BREAKPOINT_TABLET_SCREEN}px) { - ${style} - } -`; From dff0822709cde19c50e99298ab0533f6286d4ede Mon Sep 17 00:00:00 2001 From: nhestrompia Date: Tue, 12 Sep 2023 04:19:15 +0300 Subject: [PATCH 25/38] fix: dashboard list view --- web/src/components/CasesDisplay/CasesGrid.tsx | 4 ++-- .../components/CasesDisplay/CasesListHeader.tsx | 6 +++--- web/src/pages/Dashboard/index.tsx | 14 +++++++++++++- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/web/src/components/CasesDisplay/CasesGrid.tsx b/web/src/components/CasesDisplay/CasesGrid.tsx index 25fbeaf4d..bbb290777 100644 --- a/web/src/components/CasesDisplay/CasesGrid.tsx +++ b/web/src/components/CasesDisplay/CasesGrid.tsx @@ -1,7 +1,7 @@ import React from "react"; import styled, { css } from "styled-components"; import { StandardPagination } from "@kleros/ui-components-library"; -import { portraitStyle } from "styles/portraitStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import { useFiltersContext } from "context/FilterProvider"; import { CasesPageQuery } from "queries/useCasesQuery"; import DisputeCard from "components/DisputeCard"; @@ -15,7 +15,7 @@ const GridContainer = styled.div` justify-content: space-between; align-items: center; justify-items: center; - ${portraitStyle(css` + ${landscapeStyle(css` display: flex; flex-wrap: wrap; justify-content: center; diff --git a/web/src/components/CasesDisplay/CasesListHeader.tsx b/web/src/components/CasesDisplay/CasesListHeader.tsx index df4be5b0f..845c66ee9 100644 --- a/web/src/components/CasesDisplay/CasesListHeader.tsx +++ b/web/src/components/CasesDisplay/CasesListHeader.tsx @@ -1,6 +1,6 @@ import React from "react"; import styled, { css } from "styled-components"; -import { portraitStyle } from "styles/portraitStyle"; +import { landscapeStyle } from "styles/landscapeStyle"; import WithHelpTooltip from "pages/Dashboard/WithHelpTooltip"; const Container = styled.div` @@ -20,7 +20,7 @@ const CasesData = styled.div` gap: 12px; flex-wrap: wrap; padding: 0 3%; - ${portraitStyle(css` + ${landscapeStyle(css` gap: calc(24px + (48 - 24) * ((100vw - 300px) / (1250 - 300))); `)} `; @@ -36,7 +36,7 @@ const CaseTitle = styled.div` color: ${({ theme }) => theme.secondaryText} !important; } - ${portraitStyle(css` + ${landscapeStyle(css` display: flex; `)} `; diff --git a/web/src/pages/Dashboard/index.tsx b/web/src/pages/Dashboard/index.tsx index f5d303e4c..918a179df 100644 --- a/web/src/pages/Dashboard/index.tsx +++ b/web/src/pages/Dashboard/index.tsx @@ -1,7 +1,10 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import styled from "styled-components"; +import { useWindowSize } from "react-use"; import { useAccount } from "wagmi"; +import { useFiltersContext } from "context/FilterProvider"; import { useCasesQuery } from "queries/useCasesQuery"; +import { BREAKPOINT_LANDSCAPE } from "styles/landscapeStyle"; import JurorInfo from "./JurorInfo"; import Courts from "./Courts"; import CasesDisplay from "components/CasesDisplay"; @@ -30,10 +33,19 @@ const ConnectWalletContainer = styled.div` const Dashboard: React.FC = () => { const { isConnected } = useAccount(); + const { width } = useWindowSize(); + const screenIsBig = width > BREAKPOINT_LANDSCAPE; + const { isList, setIsList } = useFiltersContext(); const [currentPage, setCurrentPage] = useState(1); const casesPerPage = 3; const { data } = useCasesQuery(casesPerPage * (currentPage - 1)); + useEffect(() => { + if (!screenIsBig && isList) { + setIsList(false); + } + }, [screenIsBig]); + return ( {isConnected ? ( From d233f690769f6e01b0e57b7ebfab1c953583a7de Mon Sep 17 00:00:00 2001 From: nhestrompia Date: Tue, 12 Sep 2023 04:21:32 +0300 Subject: [PATCH 26/38] fix: code smell --- web/src/components/CasesDisplay/CasesGrid.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web/src/components/CasesDisplay/CasesGrid.tsx b/web/src/components/CasesDisplay/CasesGrid.tsx index bbb290777..6bf6cf5e6 100644 --- a/web/src/components/CasesDisplay/CasesGrid.tsx +++ b/web/src/components/CasesDisplay/CasesGrid.tsx @@ -50,15 +50,15 @@ const CasesGrid: React.FC = ({ disputes, currentPage, setCurrentPage <> {!isList ? ( - {disputes.map((dispute, i) => { - return ; + {disputes.map((dispute) => { + return ; })} ) : ( {isList && } - {disputes.map((dispute, i) => { - return ; + {disputes.map((dispute) => { + return ; })} )} From 92f09ad1639dcd87395e3c3e5e49b456f135064c Mon Sep 17 00:00:00 2001 From: alcercu <333aleix333@gmail.com> Date: Tue, 12 Sep 2023 12:46:06 +0200 Subject: [PATCH 27/38] refactor(web): remove header link classname --- web/src/layout/Header/DesktopHeader.tsx | 8 ++++++-- web/src/layout/Header/MobileHeader.tsx | 9 +++++++-- web/src/layout/Header/index.tsx | 4 ---- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/web/src/layout/Header/DesktopHeader.tsx b/web/src/layout/Header/DesktopHeader.tsx index e5a4aa8f2..611eaa4a2 100644 --- a/web/src/layout/Header/DesktopHeader.tsx +++ b/web/src/layout/Header/DesktopHeader.tsx @@ -55,6 +55,10 @@ const LightButtonContainer = styled.div` margin-right: calc(12px + (16 - 12) * ((100vw - 375px) / (1250 - 375))); `; +const StyledLink = styled(Link)` + min-height: 48px; +`; + const StyledKlerosSolutionsIcon = styled(KlerosSolutionsIcon)` fill: ${({ theme }) => theme.white} !important; `; @@ -80,9 +84,9 @@ const DesktopHeader = () => { /> {isSolutionsOpen && } - + - + diff --git a/web/src/layout/Header/MobileHeader.tsx b/web/src/layout/Header/MobileHeader.tsx index f34626d06..15cd74ffb 100644 --- a/web/src/layout/Header/MobileHeader.tsx +++ b/web/src/layout/Header/MobileHeader.tsx @@ -33,12 +33,17 @@ const StyledLightButton = styled(LightButton)` } `; +const StyledLink = styled(Link)` + min-height: 48px; +`; + const OpenContext = React.createContext({ isOpen: false, toggleIsOpen: () => { // Placeholder }, }); + export function useOpenContext() { return useContext(OpenContext); } @@ -51,9 +56,9 @@ const MobileHeader = () => { return ( - + - + diff --git a/web/src/layout/Header/index.tsx b/web/src/layout/Header/index.tsx index 498920263..e018b1675 100644 --- a/web/src/layout/Header/index.tsx +++ b/web/src/layout/Header/index.tsx @@ -13,10 +13,6 @@ const Container = styled.div` padding: 0 24px; display: flex; - - .kleros-court-link { - min-height: 48px; - } `; const Header: React.FC = () => { From bca75422852b42e035ae536d48b1ccf6b00e63c9 Mon Sep 17 00:00:00 2001 From: alcercu <333aleix333@gmail.com> Date: Tue, 12 Sep 2023 15:41:55 +0200 Subject: [PATCH 28/38] fix(web): useToggle instead of useState to avoid re-renders --- web/src/layout/Header/MobileHeader.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web/src/layout/Header/MobileHeader.tsx b/web/src/layout/Header/MobileHeader.tsx index 15cd74ffb..195d0647a 100644 --- a/web/src/layout/Header/MobileHeader.tsx +++ b/web/src/layout/Header/MobileHeader.tsx @@ -1,5 +1,6 @@ -import React, { useContext, useRef, useState } from "react"; +import React, { useContext, useRef } from "react"; import styled, { css } from "styled-components"; +import { useToggle } from "react-use"; import { landscapeStyle } from "styles/landscapeStyle"; import { Link } from "react-router-dom"; import KlerosCourtLogo from "svgs/header/kleros-court.svg"; @@ -49,10 +50,9 @@ export function useOpenContext() { } const MobileHeader = () => { - const [isOpen, setIsOpen] = useState(false); - const toggleIsOpen = () => setIsOpen(!isOpen); + const [isOpen, toggleIsOpen] = useToggle(false); const containerRef = useRef(null); - useFocusOutside(containerRef, () => setIsOpen(false)); + useFocusOutside(containerRef, () => toggleIsOpen(false)); return ( From 0a7e5ced89573ef0e6980891773a22b169d01987 Mon Sep 17 00:00:00 2001 From: alcercu <333aleix333@gmail.com> Date: Tue, 12 Sep 2023 15:47:08 +0200 Subject: [PATCH 29/38] fix(web): memoize mobile header context to improve performance --- web/src/layout/Header/MobileHeader.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/web/src/layout/Header/MobileHeader.tsx b/web/src/layout/Header/MobileHeader.tsx index 195d0647a..4cc4d115c 100644 --- a/web/src/layout/Header/MobileHeader.tsx +++ b/web/src/layout/Header/MobileHeader.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useRef } from "react"; +import React, { useContext, useMemo, useRef } from "react"; import styled, { css } from "styled-components"; import { useToggle } from "react-use"; import { landscapeStyle } from "styles/landscapeStyle"; @@ -53,9 +53,10 @@ const MobileHeader = () => { const [isOpen, toggleIsOpen] = useToggle(false); const containerRef = useRef(null); useFocusOutside(containerRef, () => toggleIsOpen(false)); + const memoizedContext = useMemo(() => ({ isOpen, toggleIsOpen }), [isOpen, toggleIsOpen]); return ( - + From 2288b775bd016df3ca9d536e12437a3f2ccb37d0 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Wed, 13 Sep 2023 10:50:06 +0200 Subject: [PATCH 30/38] feat(web): style scrollbar a bit and add placeholder if not scrollable section --- web/src/styles/global-style.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/web/src/styles/global-style.ts b/web/src/styles/global-style.ts index bf9404551..2cfdf3412 100644 --- a/web/src/styles/global-style.ts +++ b/web/src/styles/global-style.ts @@ -15,6 +15,7 @@ export const GlobalStyle = createGlobalStyle` html { box-sizing: border-box; + scrollbar-gutter: stable; } *, *:before, *:after { @@ -103,4 +104,21 @@ export const GlobalStyle = createGlobalStyle` --base-color: ${({ theme }) => theme.skeletonBackground}; --highlight-color: ${({ theme }) => theme.skeletonHighlight}; } + *::-webkit-scrollbar { + width: 6px; + height: 6px; + } + + *::-webkit-scrollbar-track { + background-color: ${({ theme }) => theme.mediumPurple}; +} + +*::-webkit-scrollbar-thumb { + background-color: ${({ theme }) => theme.primaryPurple}; + border-radius: 3px; +} + +*::-webkit-scrollbar-thumb:hover { + background-color: ${({ theme }) => theme.secondaryPurple}; +} `; From 7e3dc943af58e6d4f4d7e322cbdc4c8f464c5c65 Mon Sep 17 00:00:00 2001 From: nhestrompia Date: Wed, 13 Sep 2023 12:25:58 +0300 Subject: [PATCH 31/38] fix: change vote stake formula --- web/src/pages/Courts/CourtDetails/Stats.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/web/src/pages/Courts/CourtDetails/Stats.tsx b/web/src/pages/Courts/CourtDetails/Stats.tsx index d6798c079..2bb78a6f7 100644 --- a/web/src/pages/Courts/CourtDetails/Stats.tsx +++ b/web/src/pages/Courts/CourtDetails/Stats.tsx @@ -44,8 +44,14 @@ const stats: IStat[] = [ { title: "Vote Stake", coinId: 0, - getText: (data) => formatPNK(data?.alpha), - getSubtext: (data, coinPrice) => formatUSD(Number(formatUnitsWei(data?.alpha)) * (coinPrice ?? 0)), + getText: (data) => { + const stake = BigInt((data?.minStake * data?.alpha) / 1e4); + return formatPNK(stake); + }, + getSubtext: (data, coinPrice) => { + const stake = BigInt((data?.minStake * data?.alpha) / 1e4); + return formatUSD(Number(formatUnitsWei(stake)) * (coinPrice ?? 0)); + }, color: "purple", icon: VoteStake, }, From 8490c32691ada16fd95926d68dbdd492f70dce38 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Wed, 13 Sep 2023 18:17:27 +0200 Subject: [PATCH 32/38] feat(web): add overlay scrollbars plugin, style it, lock functionality --- web/package.json | 2 ++ web/src/context/OverlayScrollContext.tsx | 3 ++ web/src/hooks/useLockOverlayScroll.ts | 28 +++++++++++++++ web/src/layout/Header/navbar/index.tsx | 5 +-- web/src/layout/index.tsx | 34 ++++++++++++++----- .../pages/Cases/CaseDetails/Voting/index.tsx | 4 +-- .../Courts/CourtDetails/StakePanel/index.tsx | 4 +-- web/src/styles/global-style.ts | 21 +++--------- web/src/styles/themes.ts | 4 +++ yarn.lock | 19 +++++++++++ 10 files changed, 93 insertions(+), 31 deletions(-) create mode 100644 web/src/context/OverlayScrollContext.tsx create mode 100644 web/src/hooks/useLockOverlayScroll.ts diff --git a/web/package.json b/web/package.json index 7fb6d1826..ea2cc5bb4 100644 --- a/web/package.json +++ b/web/package.json @@ -82,6 +82,8 @@ "graphql": "^16.7.1", "graphql-request": "~6.1.0", "moment": "^2.29.4", + "overlayscrollbars": "^2.3.0", + "overlayscrollbars-react": "^0.5.2", "react": "^18.2.0", "react-chartjs-2": "^4.3.1", "react-dom": "^18.2.0", diff --git a/web/src/context/OverlayScrollContext.tsx b/web/src/context/OverlayScrollContext.tsx new file mode 100644 index 000000000..7b9629317 --- /dev/null +++ b/web/src/context/OverlayScrollContext.tsx @@ -0,0 +1,3 @@ +import { createContext, MutableRefObject } from "react"; + +export const OverlayScrollContext = createContext | null>(null); diff --git a/web/src/hooks/useLockOverlayScroll.ts b/web/src/hooks/useLockOverlayScroll.ts new file mode 100644 index 000000000..146cdcd2a --- /dev/null +++ b/web/src/hooks/useLockOverlayScroll.ts @@ -0,0 +1,28 @@ +import { useContext, useEffect, useCallback } from "react"; +import { OverlayScrollContext } from "context/OverlayScrollContext"; + +export const useLockOverlayScroll = (shouldLock: boolean) => { + const osInstanceRef = useContext(OverlayScrollContext); + + const lockScroll = useCallback(() => { + const osInstance = osInstanceRef?.current?.osInstance(); + if (osInstance) { + osInstance.options({ overflow: { x: "hidden", y: "hidden" } }); + } + }, [osInstanceRef]); + + const unlockScroll = useCallback(() => { + const osInstance = osInstanceRef?.current?.osInstance(); + if (osInstance) { + osInstance.options({ overflow: { x: "scroll", y: "scroll" } }); + } + }, [osInstanceRef]); + + useEffect(() => { + if (shouldLock) { + lockScroll(); + } else { + unlockScroll(); + } + }, [shouldLock, lockScroll, unlockScroll]); +}; diff --git a/web/src/layout/Header/navbar/index.tsx b/web/src/layout/Header/navbar/index.tsx index 684a36ebf..15e300754 100644 --- a/web/src/layout/Header/navbar/index.tsx +++ b/web/src/layout/Header/navbar/index.tsx @@ -1,6 +1,7 @@ import React from "react"; import styled from "styled-components"; -import { useLockBodyScroll, useToggle } from "react-use"; +import { useToggle } from "react-use"; +import { useLockOverlayScroll } from "hooks/useLockOverlayScroll"; import ConnectWallet from "components/ConnectWallet"; import LightButton from "components/LightButton"; import KlerosSolutionsIcon from "svgs/menu-icons/kleros-solutions.svg"; @@ -37,7 +38,7 @@ const Container = styled.div<{ isOpen: boolean }>` const NavBar: React.FC = () => { const [isSolutionsOpen, toggleSolution] = useToggle(false); const { isOpen } = useOpenContext(); - useLockBodyScroll(isOpen); + useLockOverlayScroll(isOpen); return ( diff --git a/web/src/layout/index.tsx b/web/src/layout/index.tsx index 4a50039d3..ab8859d71 100644 --- a/web/src/layout/index.tsx +++ b/web/src/layout/index.tsx @@ -1,7 +1,10 @@ -import React from "react"; +import React, { useRef } from "react"; import styled from "styled-components"; +import "overlayscrollbars/styles/overlayscrollbars.css"; import { Outlet } from "react-router-dom"; import { ToastContainer } from "react-toastify"; +import { OverlayScrollbarsComponent } from "overlayscrollbars-react"; +import { OverlayScrollContext } from "context/OverlayScrollContext"; import Header from "./Header"; import Footer from "./Footer"; @@ -10,18 +13,31 @@ const Container = styled.div` width: 100%; `; +const StyledOverlayScrollbarsComponent = styled(OverlayScrollbarsComponent)` + height: 100vh; + width: 100vw; +`; + const StyledToastContainer = styled(ToastContainer)` padding: 16px; padding-top: 70px; `; -const Layout: React.FC = () => ( - -
- - -