From bb40f96730f20152da22224b702e255c107d1ced Mon Sep 17 00:00:00 2001 From: Rye Nguyen Date: Tue, 30 May 2023 00:19:17 +0700 Subject: [PATCH 1/5] feat: add sidebar layout --- src/components/Header/index.tsx | 23 +++++++------ src/components/Header/styled.tsx | 17 +++++++--- src/components/Layout/index.tsx | 22 +++++++++---- src/components/Layout/styled.tsx | 5 +++ src/components/Sidebar/index.tsx | 34 +++++++++++++++++++ src/components/Sidebar/styled.tsx | 54 +++++++++++++++++++++++++++++++ 6 files changed, 132 insertions(+), 23 deletions(-) create mode 100644 src/components/Sidebar/index.tsx create mode 100644 src/components/Sidebar/styled.tsx diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index 28609a98..fc03a52b 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -4,10 +4,14 @@ import React, { useCallback } from 'react'; import { useIntl } from 'react-intl'; import { useThemeSettings } from '../../modules/store/settings'; +import { Sidebar } from '../Sidebar'; +import { NavHandlerProps } from '../Layout'; -import { HeaderContainer } from './styled'; +import { HeaderContainer, HeaderAction } from './styled'; -export const Header = () => { +type Props = NavHandlerProps; + +export const Header = ({ navOpen, setNavOpen }: Props) => { const { push, asPath, locales } = useRouter(); const { locale } = useIntl(); const [theme, setTheme] = useThemeSettings(); @@ -18,16 +22,11 @@ export const Header = () => { ]); return ( - - - - - - } - /> + + + +
+ ACTION ); }; diff --git a/src/components/Header/styled.tsx b/src/components/Header/styled.tsx index ae260991..e4430c88 100644 --- a/src/components/Header/styled.tsx +++ b/src/components/Header/styled.tsx @@ -1,9 +1,18 @@ import styled from 'styled-components'; -export const HeaderContainer = styled.div` - width: 100%; - left: 0; - top: 0; +export const HeaderContainer = styled.div<{ open: boolean }>` position: fixed; + top: 0; + left: ${({ open }) => (open ? '216px' : '72px')}; + right: 0; + display: flex; + justify-content: space-between; + height: 70px; + border-bottom: 1px solid ${({ theme }) => theme.pulsar.color.border.normal}; + transition: all 0.2s linear; z-index: 20; `; + +export const HeaderAction = styled.div` + align-self: flex-end; +`; diff --git a/src/components/Layout/index.tsx b/src/components/Layout/index.tsx index f6709840..2a543aa4 100644 --- a/src/components/Layout/index.tsx +++ b/src/components/Layout/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { useDispatch } from 'react-redux'; import { mode } from '../../modules/env'; @@ -10,12 +10,18 @@ import { Header } from '../Header'; import { Swap } from '../Swap'; import { CookieConsentHandler } from './CookieConsentHandler'; -import { SwapContainer } from './styled'; +import { SwapContainer, LayoutBody } from './styled'; type Props = { children: React.ReactNode }; +export type NavHandlerProps = { + navOpen: boolean; + setNavOpen: (navOpen: boolean) => void; +}; + export const Layout = ({ children }: Props) => { const dispatch = useDispatch(); + const [navOpen, setNavOpen] = useState(true); useEffect(() => { (async () => { @@ -28,13 +34,15 @@ export const Layout = ({ children }: Props) => { <> -
+
- - - + + + + - {children} + {children} + diff --git a/src/components/Layout/styled.tsx b/src/components/Layout/styled.tsx index 73f1c784..6622930b 100644 --- a/src/components/Layout/styled.tsx +++ b/src/components/Layout/styled.tsx @@ -9,3 +9,8 @@ export const SwapContainer = styled.div` margin: 0 auto; padding-top: ${rem(70)}; `; + +export const LayoutBody = styled.div<{ open: boolean }>` + margin-left: ${({ open }) => (open ? '216px' : '72px')}; + transition: all 0.2s linear; +`; diff --git a/src/components/Sidebar/index.tsx b/src/components/Sidebar/index.tsx new file mode 100644 index 00000000..6384ac54 --- /dev/null +++ b/src/components/Sidebar/index.tsx @@ -0,0 +1,34 @@ +import { Icon } from '@swingby-protocol/pulsar'; +import { useIntl } from 'react-intl'; + +import { NavHandlerProps } from '../Layout'; + +import { SidebarInput, SidebarToggle, SidebarContainer, AppLogoLink } from './styled'; + +const TOGGLE_ID = 'sidebar-menu-toggle'; + +type Props = NavHandlerProps; + +export const Sidebar = ({ navOpen, setNavOpen }: Props) => { + const { locale } = useIntl(); + + return ( + <> + + + + setNavOpen(!navOpen)}> + {navOpen ? : } + + + + {navOpen ? ( + + ) : ( + + )} + + + + ); +}; diff --git a/src/components/Sidebar/styled.tsx b/src/components/Sidebar/styled.tsx new file mode 100644 index 00000000..35a55901 --- /dev/null +++ b/src/components/Sidebar/styled.tsx @@ -0,0 +1,54 @@ +import styled from 'styled-components'; +import { rem } from 'polished'; + +export const SidebarInput = styled.input` + position: fixed; + visibility: hidden; + opacity: 0; +`; + +export const SidebarToggle = styled.label` + position: absolute; + top: 24px; + right: -12px; + width: 24px; + height: 24px; + line-height: 24px; + text-align: center; + border-radius: 50%; + border: 1px solid ${({ theme }) => theme.pulsar.color.border.normal}; + cursor: pointer; + + svg { + width: 0.7em; + height: 0.7em; + } +`; + +export const SidebarContainer = styled.aside<{ open: boolean }>` + background-color: ${({ theme }) => theme.pulsar.color.bg.accent}; + width: ${({ open }) => (open ? '216px' : '72px')}; + border-right: 1px solid ${({ theme }) => theme.pulsar.color.border.normal}; + padding: ${({ theme }) => `${rem(theme.pulsar.size.street)} ${rem(theme.pulsar.size.closet)}`}; + position: fixed; + top: 0; + left: 0; + height: 100vh; + transition: all 0.2s linear; + display: flex; + flex-direction: column; + align-items: center; + z-index: 20; +`; + +export const AppLogoLink = styled.a` + color: inherit; + text-decoration: none; + display: flex; + align-items: center; + justify-content: center; + + > svg { + height: 1.5em; + } +`; From 1832bc9f463bb52a3289b555e00915ad28ef0a89 Mon Sep 17 00:00:00 2001 From: Rye Nguyen Date: Thu, 1 Jun 2023 01:46:28 +0700 Subject: [PATCH 2/5] feat: success handle sidebar --- src/components/Header/index.tsx | 55 +++++--- src/components/Header/styled.tsx | 46 ++++++- src/components/Layout/index.tsx | 12 +- src/components/Layout/styled.tsx | 21 ++- src/components/Sidebar/index.tsx | 205 +++++++++++++++++++++++++++++- src/components/Sidebar/styled.tsx | 118 ++++++++++++++++- 6 files changed, 424 insertions(+), 33 deletions(-) diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index fc03a52b..85eda9ea 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -1,32 +1,53 @@ -import { SwingbyHeader, LocaleSwitcher, ThemeSwitcher } from '@swingby-protocol/header'; -import { useRouter } from 'next/router'; -import React, { useCallback } from 'react'; -import { useIntl } from 'react-intl'; +import React from 'react'; +import { FormattedMessage } from 'react-intl'; +import { Icon } from '@swingby-protocol/pulsar'; -import { useThemeSettings } from '../../modules/store/settings'; import { Sidebar } from '../Sidebar'; import { NavHandlerProps } from '../Layout'; +import { useOnboard } from '../../modules/onboard'; -import { HeaderContainer, HeaderAction } from './styled'; +import { + HeaderContainer, + SidebarToggleMobile, + HeaderAction, + HeaderLogo, + ButtonConnect, +} from './styled'; type Props = NavHandlerProps; -export const Header = ({ navOpen, setNavOpen }: Props) => { - const { push, asPath, locales } = useRouter(); - const { locale } = useIntl(); - const [theme, setTheme] = useThemeSettings(); +const ConnectWallet = () => { + const { address, onboard } = useOnboard(); - const changeLocale = useCallback((locale: string) => push(asPath, null, { locale }), [ - push, - asPath, - ]); + if (address) { + return
{address}
; + } + return ( + await onboard?.walletSelect()} + > + + + ); +}; + +export const Header = ({ navOpen, toggleNav }: Props) => { return ( - + + + + + + + -
- ACTION + + + ); }; diff --git a/src/components/Header/styled.tsx b/src/components/Header/styled.tsx index e4430c88..c2d93208 100644 --- a/src/components/Header/styled.tsx +++ b/src/components/Header/styled.tsx @@ -1,18 +1,58 @@ import styled from 'styled-components'; +import { rem } from 'polished'; +import { Button } from '@swingby-protocol/pulsar'; + +import { StylingConstants } from '../../modules/styles'; + +const { media } = StylingConstants; export const HeaderContainer = styled.div<{ open: boolean }>` position: fixed; top: 0; - left: ${({ open }) => (open ? '216px' : '72px')}; + left: 0; right: 0; display: flex; justify-content: space-between; + align-items: center; height: 70px; + padding: ${({ theme }) => rem(theme.pulsar.size.street)}; border-bottom: 1px solid ${({ theme }) => theme.pulsar.color.border.normal}; transition: all 0.2s linear; z-index: 20; + + @media (min-width: ${rem(media.md)}) { + left: ${({ open }) => (open ? '216px' : '72px')}; + } `; -export const HeaderAction = styled.div` - align-self: flex-end; +export const HeaderLogo = styled.div` + display: flex; + align-items: center; + gap: ${({ theme }) => rem(theme.pulsar.size.closet)}; +`; + +export const HeaderAction = styled.div``; + +export const SidebarToggleMobile = styled.label` + cursor: pointer; + + @media (min-width: ${rem(media.md)}) { + display: none; + } +`; + +export const AppLogoLink = styled.a` + color: inherit; + text-decoration: none; + display: flex; + align-items: center; + justify-content: center; + + > svg { + height: 1.5em; + } +`; +export const ButtonConnect = styled(Button)` + width: ${rem(176)}; + z-index: 10; `; diff --git a/src/components/Layout/index.tsx b/src/components/Layout/index.tsx index 2a543aa4..6062c17e 100644 --- a/src/components/Layout/index.tsx +++ b/src/components/Layout/index.tsx @@ -16,12 +16,18 @@ type Props = { children: React.ReactNode }; export type NavHandlerProps = { navOpen: boolean; - setNavOpen: (navOpen: boolean) => void; + toggleNav: (e: React.MouseEvent) => void; }; export const Layout = ({ children }: Props) => { const dispatch = useDispatch(); - const [navOpen, setNavOpen] = useState(true); + const [navOpen, setNavOpen] = useState(false); + + const toggleNav = (e: React.MouseEvent) => { + e.stopPropagation(); + e.preventDefault(); + setNavOpen(!navOpen); + }; useEffect(() => { (async () => { @@ -34,7 +40,7 @@ export const Layout = ({ children }: Props) => { <> -
+
diff --git a/src/components/Layout/styled.tsx b/src/components/Layout/styled.tsx index 6622930b..ae20f9ff 100644 --- a/src/components/Layout/styled.tsx +++ b/src/components/Layout/styled.tsx @@ -1,6 +1,10 @@ import { rem } from 'polished'; import styled from 'styled-components'; +import { StylingConstants } from '../../modules/styles'; + +const { media } = StylingConstants; + export const SwapContainer = styled.div` max-width: ${rem(847)}; display: flex; @@ -11,6 +15,21 @@ export const SwapContainer = styled.div` `; export const LayoutBody = styled.div<{ open: boolean }>` - margin-left: ${({ open }) => (open ? '216px' : '72px')}; transition: all 0.2s linear; + + @media (min-width: ${rem(media.md)}) { + margin-left: ${({ open }) => (open ? '216px' : '72px')}; + } +`; + +export const AppLogoLink = styled.a` + color: inherit; + text-decoration: none; + display: flex; + align-items: center; + justify-content: center; + + > svg { + height: 1.5em; + } `; diff --git a/src/components/Sidebar/index.tsx b/src/components/Sidebar/index.tsx index 6384ac54..2f1c2918 100644 --- a/src/components/Sidebar/index.tsx +++ b/src/components/Sidebar/index.tsx @@ -1,25 +1,195 @@ -import { Icon } from '@swingby-protocol/pulsar'; +import { Icon, Testable } from '@swingby-protocol/pulsar'; +import { useRouter } from 'next/router'; +import { LocaleSwitcher, ThemeSwitcher } from '@swingby-protocol/header'; import { useIntl } from 'react-intl'; +import { useCallback, useEffect, useState, useMemo } from 'react'; +import { useThemeSettings } from '../../modules/store/settings'; import { NavHandlerProps } from '../Layout'; -import { SidebarInput, SidebarToggle, SidebarContainer, AppLogoLink } from './styled'; +import { + SidebarInput, + SidebarToggle, + SidebarToggleMobile, + SidebarContainer, + SidebarActionContainer, + AppLogoLink, + MenuContainer, + MenuItemContainer, + MenuItemAnchor, +} from './styled'; + +type Props = { + productName?: string; + logoHref?: string; + barItems?: React.ReactNode; + items?: Array< + { render: React.ReactNode; icon: React.ReactNode; key: string } & Pick< + React.ComponentPropsWithoutRef, + 'onClick' | 'target' | 'href' + > + > | null; +} & NavHandlerProps; + +type MenuItemProps = { children?: React.ReactNode; isActive?: boolean } & Testable & + Pick, 'onClick' | 'target' | 'href'>; const TOGGLE_ID = 'sidebar-menu-toggle'; +export const DEFAULT_ITEMS: Props['items'] = [ + { + render: 'Explorer', + icon: , + key: 'explorer', + href: 'https://skybridge.info', + }, + { + render: 'Liquidity', + icon: , + key: 'liquidity', + href: 'https://skybridge.info/pool', + }, + { + render: 'Farm', + icon: , + key: 'farm', + href: 'https://farm.swingby.network', + }, + { + render: 'Metanodes', + icon: , + key: 'metanodes', + href: 'https://skybridge.info/metanodes', + }, + { + render: 'ERC20 Bridge', + icon: , + key: 'erc20-bridge', + href: 'https://bridge.swingby.network', + }, + { + render: 'DAO', + icon: , + key: 'dao', + href: 'https://dao.swingby.network/', + }, +]; + +const MenuItem = ({ + children, + href, + onClick, + target, + isActive = false, + 'data-testid': testId, +}: MenuItemProps) => { + return ( + + {href ? ( + + {children} + + ) : ( + children + )} + + ); +}; -type Props = NavHandlerProps; +export const Sidebar = ({ navOpen, toggleNav, items: itemsParam = DEFAULT_ITEMS }: Props) => { + const [href, setHref] = useState( + (() => { + try { + return window.location.href; + } catch (e) { + return null; + } + })(), + ); -export const Sidebar = ({ navOpen, setNavOpen }: Props) => { const { locale } = useIntl(); + const items = useMemo((): typeof itemsParam => { + if (!itemsParam) return null; + if (!locale) return itemsParam; + + return itemsParam.map((it) => { + if (it === DEFAULT_ITEMS[0]) { + return { ...it, href: `https://skybridge.info/${locale}` }; + } + + if (it === DEFAULT_ITEMS[1]) { + return { ...it, href: `https://skybridge.info/${locale}/pool` }; + } + + if (it === DEFAULT_ITEMS[2]) { + return { ...it, href: `https://farm.swingby.network/${locale}` }; + } + + if (it === DEFAULT_ITEMS[3]) { + return { ...it, href: `https://skybridge.info/${locale}/metanodes` }; + } + + if (it === DEFAULT_ITEMS[4]) { + return { ...it, href: `https://bridge.swingby.network/${locale}` }; + } + + if (it === DEFAULT_ITEMS[5]) { + return { ...it, href: `https://dao.swingby.network/${locale}` }; + } + + return it; + }); + }, [itemsParam, locale]); + + const currentItem = useMemo(() => { + if (!href) return null; + if (!items) return null; + const results = items + .filter((it) => { + if (!it.href) return false; + return href.toLowerCase().startsWith(it.href.toLowerCase()); + }) + .sort((a, b) => b.href!.length - a.href!.length); + + return results[0] ?? null; + }, [href, items]); + + useEffect(() => { + if (typeof document === 'undefined') return; + const body = document.querySelector('body'); + if (!body) return; + + const observer = new MutationObserver((mutations) => { + mutations.forEach(() => { + setHref(document.location.href); + }); + }); + + observer.observe(body, { childList: true, subtree: true }); + return () => { + observer.disconnect(); + }; + }, []); + + const { push, asPath, locales } = useRouter(); + const [theme, setTheme] = useThemeSettings(); + + const changeLocale = useCallback((locale: string) => push(asPath, null, { locale }), [ + push, + asPath, + ]); + return ( <> - + - setNavOpen(!navOpen)}> + {navOpen ? : } + + + {navOpen ? ( @@ -28,6 +198,29 @@ export const Sidebar = ({ navOpen, setNavOpen }: Props) => { )} + + {!!items && items.length > 0 && ( + + {items.map((it) => ( + + {it.icon} + {navOpen && {it.render}} + + ))} + + )} + + + + {navOpen && } + ); diff --git a/src/components/Sidebar/styled.tsx b/src/components/Sidebar/styled.tsx index 35a55901..6e65605c 100644 --- a/src/components/Sidebar/styled.tsx +++ b/src/components/Sidebar/styled.tsx @@ -1,10 +1,22 @@ -import styled from 'styled-components'; -import { rem } from 'polished'; +import styled, { css } from 'styled-components'; +import { rem, transitions } from 'polished'; -export const SidebarInput = styled.input` +import { StylingConstants } from '../../modules/styles'; + +const { media } = StylingConstants; + +export const SidebarInput = styled.input<{ open: boolean }>` position: fixed; + inset: 0; + width: 100vw; + height: 100vh; visibility: hidden; opacity: 0; + z-index: 10; + + @media (max-width: ${rem(media.md - 1)}) { + visibility: ${({ open }) => (open ? 'visible' : 'hidden')}; + } `; export const SidebarToggle = styled.label` @@ -23,6 +35,25 @@ export const SidebarToggle = styled.label` width: 0.7em; height: 0.7em; } + + @media (max-width: ${rem(media.md - 1)}) { + display: none; + } +`; + +export const SidebarToggleMobile = styled.label` + position: absolute; + top: 24px; + left: 12px; + width: 24px; + height: 24px; + line-height: 24px; + text-align: center; + cursor: pointer; + + @media (min-width: ${rem(media.md)}) { + display: none; + } `; export const SidebarContainer = styled.aside<{ open: boolean }>` @@ -39,6 +70,35 @@ export const SidebarContainer = styled.aside<{ open: boolean }>` flex-direction: column; align-items: center; z-index: 20; + + @media (max-width: ${rem(media.md - 1)}) { + width: 275px; + left: ${({ open }) => (open ? '0' : '-100%')}; + + &:before { + ${({ open }) => + open && + ` + content: ''; + position: fixed; + inset: 0; + width: 100vw; + height: 100vh; + pointer-events: none; + background-color: rgba(0,0,0,0.3); + z-index: -1; + `} + } + } +`; + +export const SidebarActionContainer = styled.div` + display: flex; + flex-direction: row; + + > * + * { + margin-left: ${({ theme }) => rem(theme.pulsar.size.closet)}; + } `; export const AppLogoLink = styled.a` @@ -52,3 +112,55 @@ export const AppLogoLink = styled.a` height: 1.5em; } `; + +export const MenuContainer = styled.ol` + flex: 1; + width: 100%; + padding: 0; + list-style: none; +`; + +export const MenuItemContainer = styled.li` + display: flex; + flex-direction: column; + align-items: stretch; + padding: ${({ theme }) => rem(theme.pulsar.size.house)} 0; +`; + +const activeAnchor = css` + color: ${({ theme }) => theme.pulsar.color.primary.normal}; +`; + +export const MenuItemAnchor = styled.a<{ isActive: boolean }>` + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + margin: ${({ theme }) => rem(-theme.pulsar.size.house)} 0; + padding-top: ${({ theme }) => rem(theme.pulsar.size.house)}; + padding-bottom: ${({ theme }) => rem(theme.pulsar.size.house)}; + font-size: ${({ theme }) => rem(theme.pulsar.size.closet)}; + font-weight: 500; + text-decoration: none; + color: inherit; + cursor: pointer; + ${({ theme }) => transitions(['background'], theme.pulsar.duration.normal)}; + ${({ isActive }) => isActive && activeAnchor}; + + :hover { + background: ${({ theme }) => theme.pulsar.color.bg.hover}; + } + + :has(span) { + justify-content: flex-start; + padding-left: ${({ theme }) => rem(theme.pulsar.size.house)}; + padding-right: ${({ theme }) => rem(theme.pulsar.size.house)}; + > svg { + margin-right: ${({ theme }) => rem(theme.pulsar.size.house)}; + } + } + + > svg { + font-size: 20px; + } +`; From 0bb3dbb45c9fffe5fe3d4220b8957ff6845314f8 Mon Sep 17 00:00:00 2001 From: Rye Nguyen Date: Sat, 3 Jun 2023 00:40:25 +0700 Subject: [PATCH 3/5] feat: add icon + header accountId --- src/components/Header/index.tsx | 3 ++- src/components/Sidebar/index.tsx | 10 +++++----- src/components/Sidebar/styled.tsx | 17 +++++++++++++---- src/modules/scenes/Common/index.tsx | 27 ++++++++++++++++++++++++++- 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index 85eda9ea..af13dff0 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -5,6 +5,7 @@ import { Icon } from '@swingby-protocol/pulsar'; import { Sidebar } from '../Sidebar'; import { NavHandlerProps } from '../Layout'; import { useOnboard } from '../../modules/onboard'; +import { AccountId } from '../../components/AccountId'; import { HeaderContainer, @@ -20,7 +21,7 @@ const ConnectWallet = () => { const { address, onboard } = useOnboard(); if (address) { - return
{address}
; + return ; } return ( diff --git a/src/components/Sidebar/index.tsx b/src/components/Sidebar/index.tsx index 2f1c2918..4c931b68 100644 --- a/src/components/Sidebar/index.tsx +++ b/src/components/Sidebar/index.tsx @@ -44,31 +44,31 @@ export const DEFAULT_ITEMS: Props['items'] = [ }, { render: 'Liquidity', - icon: , + icon: , key: 'liquidity', href: 'https://skybridge.info/pool', }, { render: 'Farm', - icon: , + icon: , key: 'farm', href: 'https://farm.swingby.network', }, { render: 'Metanodes', - icon: , + icon: , key: 'metanodes', href: 'https://skybridge.info/metanodes', }, { render: 'ERC20 Bridge', - icon: , + icon: , key: 'erc20-bridge', href: 'https://bridge.swingby.network', }, { render: 'DAO', - icon: , + icon: , key: 'dao', href: 'https://dao.swingby.network/', }, diff --git a/src/components/Sidebar/styled.tsx b/src/components/Sidebar/styled.tsx index 6e65605c..4fccb60b 100644 --- a/src/components/Sidebar/styled.tsx +++ b/src/components/Sidebar/styled.tsx @@ -107,6 +107,12 @@ export const AppLogoLink = styled.a` display: flex; align-items: center; justify-content: center; + align-self: flex-start; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + padding-left: ${({ theme }) => rem(theme.pulsar.size.closet)}; + padding-right: ${({ theme }) => rem(theme.pulsar.size.closet)}; > svg { height: 1.5em; @@ -135,15 +141,20 @@ export const MenuItemAnchor = styled.a<{ isActive: boolean }>` display: flex; flex-direction: row; align-items: center; - justify-content: center; margin: ${({ theme }) => rem(-theme.pulsar.size.house)} 0; padding-top: ${({ theme }) => rem(theme.pulsar.size.house)}; padding-bottom: ${({ theme }) => rem(theme.pulsar.size.house)}; + padding-left: ${({ theme }) => rem(theme.pulsar.size.closet)}; + padding-right: ${({ theme }) => rem(theme.pulsar.size.closet)}; font-size: ${({ theme }) => rem(theme.pulsar.size.closet)}; font-weight: 500; text-decoration: none; color: inherit; cursor: pointer; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + ${({ theme }) => transitions(['background'], theme.pulsar.duration.normal)}; ${({ isActive }) => isActive && activeAnchor}; @@ -152,9 +163,6 @@ export const MenuItemAnchor = styled.a<{ isActive: boolean }>` } :has(span) { - justify-content: flex-start; - padding-left: ${({ theme }) => rem(theme.pulsar.size.house)}; - padding-right: ${({ theme }) => rem(theme.pulsar.size.house)}; > svg { margin-right: ${({ theme }) => rem(theme.pulsar.size.house)}; } @@ -162,5 +170,6 @@ export const MenuItemAnchor = styled.a<{ isActive: boolean }>` > svg { font-size: 20px; + flex-shrink: 0; } `; diff --git a/src/modules/scenes/Common/index.tsx b/src/modules/scenes/Common/index.tsx index edb1b4fb..8ed12edb 100644 --- a/src/modules/scenes/Common/index.tsx +++ b/src/modules/scenes/Common/index.tsx @@ -1,4 +1,29 @@ +import { + IconInfo, + Atag, + IconArrowLeft, + LineBox, + TextDanger, + TextSecondary, + TextPrimary, + TextBlock, + TextEllipsis, + SizeS, + SizeM, + SizeL, + ButtonScale, + IconBack, + TextEstimated, + TextChosenFilter, + AddressLinkP, + TextRoom, + IconExternalLink, + ColumnInlineBlock, + ButtonScaleNarrow, +} from './Styled'; + export { ExplorerMain } from './ExplorerMain'; + export { IconInfo, Atag, @@ -21,4 +46,4 @@ export { IconExternalLink, ColumnInlineBlock, ButtonScaleNarrow, -} from './Styled'; +}; From 5816fda4465b3148f567d8ffc9edb530755d918c Mon Sep 17 00:00:00 2001 From: Rye Nguyen Date: Wed, 7 Jun 2023 23:16:16 +0700 Subject: [PATCH 4/5] feat: theme setting --- src/components/Globals/index.tsx | 16 ++- src/components/Header/styled.tsx | 1 + src/components/Sidebar/styled.tsx | 9 +- .../scenes/Main/Explorer/Browser/styled.tsx | 5 +- .../Main/Explorer/FloatVolume/styled.tsx | 2 +- .../scenes/Main/Explorer/StatsInfo/styled.tsx | 13 +- src/modules/store/settings/index.tsx | 2 + src/modules/store/settings/useMatchMedia.tsx | 46 +++++++ src/modules/store/settings/useSystemTheme.tsx | 12 ++ src/pages/style.css | 130 +++++++++++++++++- 10 files changed, 219 insertions(+), 17 deletions(-) create mode 100644 src/modules/store/settings/useMatchMedia.tsx create mode 100644 src/modules/store/settings/useSystemTheme.tsx diff --git a/src/components/Globals/index.tsx b/src/components/Globals/index.tsx index cca69eff..c2eb3f1f 100644 --- a/src/components/Globals/index.tsx +++ b/src/components/Globals/index.tsx @@ -5,13 +5,25 @@ import { PULSAR_GLOBAL_FONT_HREF, } from '@swingby-protocol/pulsar'; import Head from 'next/head'; -import React from 'react'; +import React, { useEffect } from 'react'; -import { useThemeSettings } from '../../modules/store/settings'; +import { useThemeSettings, useSystemTheme } from '../../modules/store/settings'; import { Favicon } from '../Favicon'; export const Globals = ({ children }: { children: React.ReactNode }) => { const [theme] = useThemeSettings(); + const systemTheme = useSystemTheme(); + + useEffect(() => { + if (['light', 'dark'].includes(theme)) { + document.body.setAttribute('data-theme', theme); + } else if (['auto'].includes(theme)) { + document.body.setAttribute('data-theme', systemTheme); + } else { + document.body.removeAttribute('data-theme'); + } + }, [theme, systemTheme]); + return ( diff --git a/src/components/Header/styled.tsx b/src/components/Header/styled.tsx index c2d93208..d3da0fe6 100644 --- a/src/components/Header/styled.tsx +++ b/src/components/Header/styled.tsx @@ -16,6 +16,7 @@ export const HeaderContainer = styled.div<{ open: boolean }>` align-items: center; height: 70px; padding: ${({ theme }) => rem(theme.pulsar.size.street)}; + background-color: ${({ theme }) => theme.pulsar.color.bg.accent}; border-bottom: 1px solid ${({ theme }) => theme.pulsar.color.border.normal}; transition: all 0.2s linear; z-index: 20; diff --git a/src/components/Sidebar/styled.tsx b/src/components/Sidebar/styled.tsx index 4fccb60b..eef2a918 100644 --- a/src/components/Sidebar/styled.tsx +++ b/src/components/Sidebar/styled.tsx @@ -44,7 +44,7 @@ export const SidebarToggle = styled.label` export const SidebarToggleMobile = styled.label` position: absolute; top: 24px; - left: 12px; + left: 24px; width: 24px; height: 24px; line-height: 24px; @@ -57,7 +57,8 @@ export const SidebarToggleMobile = styled.label` `; export const SidebarContainer = styled.aside<{ open: boolean }>` - background-color: ${({ theme }) => theme.pulsar.color.bg.accent}; + background-color: var(--theme-card-color); + /* background-color: ${({ theme }) => theme.pulsar.color.bg.accent}; */ width: ${({ open }) => (open ? '216px' : '72px')}; border-right: 1px solid ${({ theme }) => theme.pulsar.color.border.normal}; padding: ${({ theme }) => `${rem(theme.pulsar.size.street)} ${rem(theme.pulsar.size.closet)}`}; @@ -117,6 +118,10 @@ export const AppLogoLink = styled.a` > svg { height: 1.5em; } + + @media (max-width: ${rem(media.md - 1)}) { + margin-left: 40px; + } `; export const MenuContainer = styled.ol` diff --git a/src/modules/scenes/Main/Explorer/Browser/styled.tsx b/src/modules/scenes/Main/Explorer/Browser/styled.tsx index cb8b2f13..7db56717 100644 --- a/src/modules/scenes/Main/Explorer/Browser/styled.tsx +++ b/src/modules/scenes/Main/Explorer/Browser/styled.tsx @@ -34,7 +34,7 @@ export const BrowserDiv = styled(Card)` padding-bottom: ${({ theme }) => rem(theme.pulsar.size.closet)}; } @media (min-width: ${rem(media.xl)}) { - width: ${rem(1188)}; + /* width: ${rem(1188)}; */ padding-left: ${({ theme }) => rem(theme.pulsar.size.town)}; padding-right: ${({ theme }) => rem(theme.pulsar.size.town)}; padding-bottom: ${({ theme }) => rem(theme.pulsar.size.house)}; @@ -44,8 +44,7 @@ export const BrowserDiv = styled(Card)` export const Top = styled.div` @media (min-width: ${rem(media.lg)}) { display: grid; - grid-template-columns: auto auto; - grid-template-rows: 1fr; + grid-template-columns: repeat(12, minmax(0, 1fr)); align-items: start; } padding-top: 0; diff --git a/src/modules/scenes/Main/Explorer/FloatVolume/styled.tsx b/src/modules/scenes/Main/Explorer/FloatVolume/styled.tsx index f6d5bfe9..5a60993b 100644 --- a/src/modules/scenes/Main/Explorer/FloatVolume/styled.tsx +++ b/src/modules/scenes/Main/Explorer/FloatVolume/styled.tsx @@ -23,6 +23,7 @@ export const FloatVolumeContainer = styled.div` } @media (min-width: ${rem(media.lg)}) { grid-area: auto; + grid-column: span 4 / span 4; padding-top: 0; padding-bottom: 0; padding-right: 0; @@ -53,7 +54,6 @@ export const CoinContainer = styled.div` grid-column-gap: ${({ theme }) => rem(theme.pulsar.size.room)}; } @media (min-width: ${rem(media.xl)}) { - padding-right: ${({ theme }) => rem(theme.pulsar.size.city)}; grid-column-gap: ${({ theme }) => rem(theme.pulsar.size.street)}; } `; diff --git a/src/modules/scenes/Main/Explorer/StatsInfo/styled.tsx b/src/modules/scenes/Main/Explorer/StatsInfo/styled.tsx index 0a36a23c..5833929a 100644 --- a/src/modules/scenes/Main/Explorer/StatsInfo/styled.tsx +++ b/src/modules/scenes/Main/Explorer/StatsInfo/styled.tsx @@ -15,6 +15,7 @@ export const StatsInfoContainer = styled.div` } @media (min-width: ${rem(media.lg)}) { grid-area: auto; + grid-column: span 8 / span 8; border-left: 1px solid #cecddc; padding-right: 0; padding-left: ${({ theme }) => rem(theme.pulsar.size.house)}; @@ -147,36 +148,32 @@ export const Left = styled.div` margin-right: ${({ theme }) => rem(theme.pulsar.size.box)}; } `; -export const Right = styled.div``; +export const Right = styled.div` + flex: 1; +`; export const ChartBox = styled.div` - width: ${rem(176)}; height: ${rem(60)}; @media (min-width: ${rem(media.xs)}) { - width: ${rem(186)}; height: ${rem(64)}; } @media (min-width: ${rem(media.md)}) { - width: ${rem(200)}; height: ${rem(70)}; } @media (min-width: ${rem((media.md + media.lg) / 2)}) { - width: ${rem(258)}; height: ${rem(90)}; } @media (min-width: ${rem(media.lg)}) { - width: ${rem(170)}; height: ${rem(76)}; } @media (min-width: ${rem(media.xl)}) { - width: ${rem(220)}; height: ${rem(76)}; } `; export const StatsWithoutChart = styled.div` display: flex; - justify-content: space-around; + justify-content: space-between; `; export const DataRow = styled.div` diff --git a/src/modules/store/settings/index.tsx b/src/modules/store/settings/index.tsx index a10b3f5d..43671a50 100644 --- a/src/modules/store/settings/index.tsx +++ b/src/modules/store/settings/index.tsx @@ -1,3 +1,5 @@ export { settings } from './reducer'; export { useThemeSettings } from './useThemeSettings'; +export { useMatchMedia } from './useMatchMedia'; +export { useSystemTheme } from './useSystemTheme'; export { settingsSelector, themeSelector } from './selectors'; diff --git a/src/modules/store/settings/useMatchMedia.tsx b/src/modules/store/settings/useMatchMedia.tsx new file mode 100644 index 00000000..7ff2eda6 --- /dev/null +++ b/src/modules/store/settings/useMatchMedia.tsx @@ -0,0 +1,46 @@ +import { useState, useEffect, useLayoutEffect as _useLayoutEffect } from 'react'; + +const useLayoutEffect = typeof window !== 'undefined' ? _useLayoutEffect : useEffect; + +export const useMatchMedia = ({ + defaultValue = false, + query, +}: { + defaultValue?: boolean; + query: string; +}) => { + const [value, setValue] = useState(defaultValue); + + useEffect(() => { + if (typeof window === 'undefined' || !window.matchMedia) { + return; + } + + const media = window.matchMedia(query); + const listener = ({ matches }: MediaQueryListEventMap['change']) => { + setValue(matches); + }; + + if (media.addEventListener) { + media.addEventListener('change', listener); + return () => { + media.removeEventListener('change', listener); + }; + } + + media.addListener(listener); + return () => { + media.removeListener(listener); + }; + }, [query]); + + useLayoutEffect(() => { + if (typeof window === 'undefined' || !window.matchMedia) { + return; + } + + setValue(window.matchMedia(query).matches); + }, [query]); + + return value; +}; diff --git a/src/modules/store/settings/useSystemTheme.tsx b/src/modules/store/settings/useSystemTheme.tsx new file mode 100644 index 00000000..d43bc8d5 --- /dev/null +++ b/src/modules/store/settings/useSystemTheme.tsx @@ -0,0 +1,12 @@ +import { useMatchMedia } from './useMatchMedia'; + +export const useSystemTheme = ({ + defaultTheme = 'light', +}: { defaultTheme?: 'light' | 'dark' } = {}) => { + const perfersDark = useMatchMedia({ + query: '(prefers-color-scheme: dark)', + defaultValue: defaultTheme === 'dark', + }); + + return perfersDark ? 'dark' : 'light'; +}; diff --git a/src/pages/style.css b/src/pages/style.css index 138363ac..44c33a0e 100644 --- a/src/pages/style.css +++ b/src/pages/style.css @@ -5,5 +5,133 @@ /* Memo: To fix stars background bug */ body { - overflow-x: hidden; + background: var(--theme-body-color); + color: var(--theme-primary-color); + font-family: var(--font-family); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + min-block-size: 100%; + min-inline-size: 100%; + font-feature-settings: 'tnum'; +} + +:root { + /* --font-family: Montserrat, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; */ + --font-family: sans-serif; + --font-size-h1: 32px; + --font-size-h2: 24px; + --font-size-h3: 18px; + --font-size-p1: 16px; + --font-size-p2: 14px; + --font-size-lb1: 14px; + --font-size-lb2: 12px; + --font-size-sm: 12px; + + --font-h1: var(--font-size-h1) / 1.25 var(--font-family); + --font-h1-bold: bold var(--font-h1); + --font-h1-semibold: 600 var(--font-h1); + --font-h2: var(--font-size-h2) / 1.3333333333 var(--font-family); + --font-h2-bold: bold var(--font-h2); + --font-h2-semibold: 600 var(--font-h2); + --font-h3: var(--font-size-h3) / 1.3333333333 var(--font-family); + --font-h3-bold: bold var(--font-h3); + --font-h3-semibold: 600 var(--font-h3); + --font-p1: var(--font-size-p1) / 1.5 var(--font-family); + --font-p1-bold: bold var(--font-p1); + --font-p1-semibold: 600 var(--font-p1); + --font-p2: var(--font-size-p2) / 1.7142857143 var(--font-family); + --font-p2-bold: bold var(--font-p2); + --font-p2-semibold: 600 var(--font-p2); + --font-lb1: var(--font-size-lb1) / 1.7142857143 var(--font-family); + --font-lb1-bold: bold var(--font-lb1); + --font-lb1-semibold: 600 var(--font-lb1); + --font-lb2: var(--font-size-lb2) / 1.3333333333 var(--font-family); + --font-lb2-bold: bold var(--font-lb2); + --font-lb2-semibold: 600 var(--font-lb2); + --font-sm: var(--font-size-sm) / 1.3333333333 var(--font-family); + --font-sm-bold: bold var(--font-sm); + --font-sm-semibold: 600 var(--font-sm); + + --theme-body-color: #f8f8f9; /* grey50 */ + --theme-card-color: #fff; + --theme-overlay-color: #fff; + --theme-mask-color: rgba(19, 32, 43, 0.8); + --theme-border-color: #e3e4e6; /* grey100 */ + --theme-border-color-rgb: 227, 228, 230; + --theme-icon-color: #aaafb3; /* grey300 */ + --theme-icon-hover-color: #060a0d; /* grey900 */ + + --theme-primary-color: #060a0d; /* grey900 */ + --theme-secondary-color: #717980; /* grey500 */ + --theme-secondary-color-rgb: 113, 121, 128; /* grey500 */ + --theme-default-color: #aaafb3; /* grey300 */ + + --theme-card-shadow: 0px 0px 0px 1px rgba(6, 10, 13, 0.03), 0px 2px 4px rgba(6, 10, 13, 0.04); + --theme-modal-shadow: 0 0 0.5px rgba(6, 10, 13, 0.4), 0 16px 32px rgba(19, 32, 43, 0.4); + --theme-overlay-shadow: 0 0 0.5px rgba(0, 0, 0, 0.4), 0 32px 64px rgba(113, 121, 128, 0.32); + + --theme-input-background: #fff; + --theme-input-placeholder: #aaafb3; + + --theme-red-color: #ff4339; /* red500 */ + --theme-red-color-rgb: 255, 67, 57; /* red500 */ + --theme-red400-color: #ff6961; + --theme-red400-color-rgb: 255, 105, 97; + --theme-red600-color: #cc362e; + --theme-red600-color-rgb: 204, 54, 46; + + --theme-green-color: #00d395; /* green500 */ + --theme-green-color-rgb: 0, 211, 149; /* green500 */ + + --theme-green700-color: #007f59; + + --theme-blue-color: #4f6ae5; /* blue500 */ + --theme-blue-color-rgb: 79, 106, 230; /* blue500 */ + --theme-blue400-color: #7288ea; + + --theme-yellow-color: #cca74d; /* yellow600 */ + --theme-yellow-color-rgb: 204, 167, 77; /* yellow600 */ + + --theme-purple-color: #a26ee3; /* purple500 */ + --theme-purple-color-rgb: 162, 110, 227; /* purple500 */ + --theme-purple700-color: #614288; + + --theme-grey-color: #c6c9cc; + --theme-grey-color-rgb: 198, 201, 204; + --theme-grey200-color: #c6c9cc; + --theme-grey300-color: #aaafb3; + --theme-grey900-color: #060a0d; + + --theme-white-color: #fff; + + --horizontal-padding: 64px; +} + +@media (max-width: 768px) { + :root { + --horizontal-padding: 24px; + } +} + +[data-theme='dark'] { + --theme-body-color: #202529; + --theme-card-color: #282c30; + --theme-overlay-color: #36393d; + --theme-mask-color: rgba(32, 37, 41, 0.8); + --theme-border-color: #43484d; + --theme-icon-color: #606268; + --theme-icon-hover-color: #fff; + + --theme-primary-color: #fff; + --theme-secondary-color: #939496; + --theme-default-color: #939496; + + --theme-card-shadow: 0px 0px 0px 1px rgba(255, 255, 255, 0.08), 0px 2px 4px rgba(0, 0, 0, 0.16); + --theme-modal-shadow: 0 0 0.5px #fff, 0 32px 64px rgba(0, 0, 0, 0.32); + --theme-overlay-shadow: 0 0 0.5px #fff, 0 32px 64px rgba(0, 0, 0, 0.32); + + --theme-input-background: #202529; + --theme-input-placeholder: #606268; + + --theme-grey-color: #606268; } From 3e215dd365aa6cda143c00c8c25526e81f3204fb Mon Sep 17 00:00:00 2001 From: Rye Nguyen Date: Thu, 8 Jun 2023 00:40:22 +0700 Subject: [PATCH 5/5] feat: new theme for homepage --- src/components/Header/styled.tsx | 7 ++++++- src/components/Search/styled.tsx | 3 ++- src/components/Sidebar/styled.tsx | 2 +- src/modules/scenes/Common/ExplorerMain/styled.tsx | 5 ----- src/modules/scenes/Main/Explorer/Browser/styled.tsx | 3 ++- src/pages/style.css | 6 +----- 6 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/components/Header/styled.tsx b/src/components/Header/styled.tsx index d3da0fe6..37c98fc7 100644 --- a/src/components/Header/styled.tsx +++ b/src/components/Header/styled.tsx @@ -16,7 +16,8 @@ export const HeaderContainer = styled.div<{ open: boolean }>` align-items: center; height: 70px; padding: ${({ theme }) => rem(theme.pulsar.size.street)}; - background-color: ${({ theme }) => theme.pulsar.color.bg.accent}; + background-color: var(--theme-card-color); + box-shadow: var(--theme-card-shadow); border-bottom: 1px solid ${({ theme }) => theme.pulsar.color.border.normal}; transition: all 0.2s linear; z-index: 20; @@ -56,4 +57,8 @@ export const AppLogoLink = styled.a` export const ButtonConnect = styled(Button)` width: ${rem(176)}; z-index: 10; + background-color: var(--theme-blue-color); + :hover { + background-color: var(--theme-blue400-color); + } `; diff --git a/src/components/Search/styled.tsx b/src/components/Search/styled.tsx index ef109138..e390bf7f 100644 --- a/src/components/Search/styled.tsx +++ b/src/components/Search/styled.tsx @@ -13,6 +13,7 @@ export const SearchInput = styled(TextInput)` padding-left: ${({ theme }) => rem(theme.pulsar.size.closet)}; padding-right: ${({ theme }) => rem(theme.pulsar.size.closet)}; font-size: ${({ theme }) => rem(theme.pulsar.size.house)}; + @media (min-width: ${rem(media.sm)}) { width: ${rem(250)}; font-size: ${({ theme }) => rem(theme.pulsar.size.room)}; @@ -34,6 +35,6 @@ export const SearchInput = styled(TextInput)` `; export const SearchIcon = styled(Icon.Search)` - color: ${({ theme }) => theme.pulsar.color.primary.normal}; + color: var(--theme-blue-color); font-size: ${({ theme }) => rem(theme.pulsar.size.street)}; `; diff --git a/src/components/Sidebar/styled.tsx b/src/components/Sidebar/styled.tsx index eef2a918..8ca0ee4f 100644 --- a/src/components/Sidebar/styled.tsx +++ b/src/components/Sidebar/styled.tsx @@ -58,7 +58,7 @@ export const SidebarToggleMobile = styled.label` export const SidebarContainer = styled.aside<{ open: boolean }>` background-color: var(--theme-card-color); - /* background-color: ${({ theme }) => theme.pulsar.color.bg.accent}; */ + box-shadow: var(--theme-card-shadow); width: ${({ open }) => (open ? '216px' : '72px')}; border-right: 1px solid ${({ theme }) => theme.pulsar.color.border.normal}; padding: ${({ theme }) => `${rem(theme.pulsar.size.street)} ${rem(theme.pulsar.size.closet)}`}; diff --git a/src/modules/scenes/Common/ExplorerMain/styled.tsx b/src/modules/scenes/Common/ExplorerMain/styled.tsx index 7654c924..232c8592 100644 --- a/src/modules/scenes/Common/ExplorerMain/styled.tsx +++ b/src/modules/scenes/Common/ExplorerMain/styled.tsx @@ -11,13 +11,9 @@ interface ThemeProps { const { media } = StylingConstants; export const ExplorerMainContainer = styled.div` position: relative; - height: ${rem(250)}; - background: ${({ theme }) => theme.pulsar.color.bg.normal}; - background-image: url(${logos.StarsBgAnimated}); z-index: 0; background-size: ${(props) => (props.isLightTheme ? '80%' : '55%')}; @media (min-width: ${rem(media.xs)}) { - height: ${rem(240)}; display: grid; width: 100%; } @@ -31,7 +27,6 @@ export const ExplorerMainContainer = styled.div` padding-right: ${({ theme }) => rem(theme.pulsar.size.street)}; } @media (min-width: ${rem(media.lg)}) { - height: ${rem(274)}; padding-left: ${({ theme }) => rem(theme.pulsar.size.closet)}; padding-right: ${({ theme }) => rem(theme.pulsar.size.closet)}; padding-top: ${({ theme }) => rem(theme.pulsar.size.country)}; diff --git a/src/modules/scenes/Main/Explorer/Browser/styled.tsx b/src/modules/scenes/Main/Explorer/Browser/styled.tsx index 7db56717..5c99ae0a 100644 --- a/src/modules/scenes/Main/Explorer/Browser/styled.tsx +++ b/src/modules/scenes/Main/Explorer/Browser/styled.tsx @@ -26,6 +26,8 @@ export const BrowserContainer = styled.div` `; export const BrowserDiv = styled(Card)` + background-color: var(--theme-card-color); + box-shadow: var(--theme-card-shadow); padding-bottom: ${({ theme }) => rem(theme.pulsar.size.drawer)}; @media (min-width: ${rem(media.lg)}) { padding-top: ${({ theme }) => rem(theme.pulsar.size.town)}; @@ -34,7 +36,6 @@ export const BrowserDiv = styled(Card)` padding-bottom: ${({ theme }) => rem(theme.pulsar.size.closet)}; } @media (min-width: ${rem(media.xl)}) { - /* width: ${rem(1188)}; */ padding-left: ${({ theme }) => rem(theme.pulsar.size.town)}; padding-right: ${({ theme }) => rem(theme.pulsar.size.town)}; padding-bottom: ${({ theme }) => rem(theme.pulsar.size.house)}; diff --git a/src/pages/style.css b/src/pages/style.css index 44c33a0e..f920dd2d 100644 --- a/src/pages/style.css +++ b/src/pages/style.css @@ -8,11 +8,7 @@ body { background: var(--theme-body-color); color: var(--theme-primary-color); font-family: var(--font-family); - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - min-block-size: 100%; - min-inline-size: 100%; - font-feature-settings: 'tnum'; + overflow-x: hidden; } :root {