diff --git a/client/cypress/e2e/_05layoutFooter.cy.ts b/client/cypress/e2e/_05layoutFooter.cy.ts index 3c39779555..9f9cbfcc1f 100644 --- a/client/cypress/e2e/_05layoutFooter.cy.ts +++ b/client/cypress/e2e/_05layoutFooter.cy.ts @@ -12,7 +12,7 @@ import { ROOT, ROOT_ROUTES } from 'src/routes/RootRoutes/routes'; chai.use(chaiColors); -Object.values(viewports).forEach(({ device, viewportWidth, viewportHeight }) => { +Object.values(viewports).forEach(({ device, viewportWidth, viewportHeight, isMobile }) => { describe(`[AW IS CLOSED] LayoutFooter: ${device}`, { viewportHeight, viewportWidth }, () => { before(() => { cy.clearLocalStorage(); @@ -76,26 +76,29 @@ Object.values(viewports).forEach(({ device, viewportWidth, viewportHeight }) => .should('eq', '_blank'); }); - it('Discord link is visible, has correct text and attributes', () => { - cy.get('[data-test=LayoutFooter__link--discord]').should('be.visible'); - cy.get('[data-test=LayoutFooter__link--discord]').invoke('text').should('eq', '→ Discord'); - cy.get('[data-test=LayoutFooter__link--discord]') + it('Blog link is visible, has correct text and attributes', () => { + cy.get('[data-test=LayoutFooter__link--blog]').should('be.visible'); + cy.get('[data-test=LayoutFooter__link--blog]').invoke('text').should('eq', '→ Blog'); + cy.get('[data-test=LayoutFooter__link--blog]') .invoke('attr', 'href') - .should('eq', 'https://discord.gg/octant'); - cy.get('[data-test=LayoutFooter__link--discord]') + .should('eq', 'https://blog.octant.build/'); + cy.get('[data-test=LayoutFooter__link--blog]') .invoke('attr', 'target') .should('eq', '_blank'); }); - it('Farcaster link is visible, has correct text and attributes', () => { - cy.get('[data-test=LayoutFooter__link--farcaster]').should('be.visible'); - cy.get('[data-test=LayoutFooter__link--farcaster]') + it('Brand assets link is visible, has correct text and attributes', () => { + cy.get('[data-test=LayoutFooter__link--brandAssets]').should('be.visible'); + cy.get('[data-test=LayoutFooter__link--brandAssets]') .invoke('text') - .should('eq', '→ Farcaster'); - cy.get('[data-test=LayoutFooter__link--farcaster]') + .should('eq', isMobile ? '→ Brand' : '→ Brand assets'); + cy.get('[data-test=LayoutFooter__link--brandAssets]') .invoke('attr', 'href') - .should('eq', 'https://warpcast.com/octant'); - cy.get('[data-test=LayoutFooter__link--farcaster]') + .should( + 'eq', + 'https://www.figma.com/community/file/1295533951881708349/octant-brand-assets', + ); + cy.get('[data-test=LayoutFooter__link--brandAssets]') .invoke('attr', 'target') .should('eq', '_blank'); }); @@ -133,41 +136,32 @@ Object.values(viewports).forEach(({ device, viewportWidth, viewportHeight }) => .should('eq', 'Get PGF news and updates from Octant. No spam, ever'); }); - if (device === 'desktop' || device === 'large-desktop') { - it('Blog of use link is visible, has correct text and attributes', () => { - cy.get('[data-test=LayoutFooter__link--blog]').should('be.visible'); - cy.get('[data-test=LayoutFooter__link--blog]').invoke('text').should('eq', '→ Blog'); - cy.get('[data-test=LayoutFooter__link--blog]') - .invoke('attr', 'href') - .should('eq', 'https://blog.octant.build/'); - cy.get('[data-test=LayoutFooter__link--blog]') - .invoke('attr', 'target') - .should('eq', '_blank'); - }); - - it('Terms of use link is visible, has correct text and attributes', () => { - cy.get('[data-test=LayoutFooter__link--brandAssets]').should('be.visible'); - cy.get('[data-test=LayoutFooter__link--brandAssets]') - .invoke('text') - .should('eq', '→ Brand assets'); - cy.get('[data-test=LayoutFooter__link--brandAssets]') - .invoke('attr', 'href') - .should( - 'eq', - 'https://www.figma.com/community/file/1295533951881708349/octant-brand-assets', - ); - cy.get('[data-test=LayoutFooter__link--brandAssets]') - .invoke('attr', 'target') - .should('eq', '_blank'); - }); - } else { - it('Blog of use link doesn`t exist', () => { - cy.get('[data-test=LayoutFooter__link--blog]').should('not.exist'); - }); - - it('Terms of use link doesn`t exist', () => { - cy.get('[data-test=LayoutFooter__link--brandAssets]').should('not.exist'); - }); - } + it('X link is visible and has correct attributes', () => { + cy.get('[data-test=LayoutFooter__Button--x]').should('be.visible'); + cy.get('[data-test=LayoutFooter__Button--x]') + .invoke('attr', 'href') + .should('eq', 'https://x.com/OctantApp'); + cy.get('[data-test=LayoutFooter__Button--x]').invoke('attr', 'target').should('eq', '_blank'); + }); + + it('Farcaster link is visible and has correct attributes', () => { + cy.get('[data-test=LayoutFooter__Button--farcaster]').should('be.visible'); + cy.get('[data-test=LayoutFooter__Button--farcaster]') + .invoke('attr', 'href') + .should('eq', 'https://warpcast.com/octant'); + cy.get('[data-test=LayoutFooter__Button--farcaster]') + .invoke('attr', 'target') + .should('eq', '_blank'); + }); + + it('Discord link is visible and has correct attributes', () => { + cy.get('[data-test=LayoutFooter__Button--discord]').should('be.visible'); + cy.get('[data-test=LayoutFooter__Button--discord]') + .invoke('attr', 'href') + .should('eq', 'https://discord.gg/octant'); + cy.get('[data-test=LayoutFooter__Button--discord]') + .invoke('attr', 'target') + .should('eq', '_blank'); + }); }); }); diff --git a/client/cypress/e2e/_07onboardingTOSNotAccepted.cy.ts b/client/cypress/e2e/_07onboardingTOSNotAccepted.cy.ts index e30b974ccd..baf2de9871 100644 --- a/client/cypress/e2e/_07onboardingTOSNotAccepted.cy.ts +++ b/client/cypress/e2e/_07onboardingTOSNotAccepted.cy.ts @@ -22,7 +22,7 @@ import { chai.use(chaiColors); Object.values(viewports).forEach( - ({ device, viewportWidth, viewportHeight, isMobile }, index, arr) => { + ({ device, viewportWidth, viewportHeight, isMobile, isTablet }, index, arr) => { describe( `[AW IS CLOSED] Onboarding (TOS not accepted): ${device}`, { viewportHeight, viewportWidth }, @@ -77,11 +77,11 @@ Object.values(viewports).forEach( }); it('user cannot change steps by clicking the edge of the screen (up to 25px from each edge)', () => { - checkChangeStepsByClickingEdgeOfTheScreenUpTo25px(false, isMobile); + checkChangeStepsByClickingEdgeOfTheScreenUpTo25px(false, isMobile || isTablet); }); it('user cannot change steps by clicking the edge of the screen (more than 25px from each edge)', () => { - checkChangeStepsByClickingEdgeOfTheScreenMoreThan25px(false, isMobile); + checkChangeStepsByClickingEdgeOfTheScreenMoreThan25px(false, isMobile || isTablet); }); it('user cannot change steps by swiping on screen (difference more than or equal 5px)', () => { diff --git a/client/cypress/e2e/_08onboardingTOSAccepted.cy.ts b/client/cypress/e2e/_08onboardingTOSAccepted.cy.ts index c4c861e67e..5c87d733fb 100644 --- a/client/cypress/e2e/_08onboardingTOSAccepted.cy.ts +++ b/client/cypress/e2e/_08onboardingTOSAccepted.cy.ts @@ -22,7 +22,7 @@ import { chai.use(chaiColors); Object.values(viewports).forEach( - ({ device, viewportWidth, viewportHeight, isMobile, isDesktop, isLargeDesktop }) => { + ({ device, viewportWidth, viewportHeight, isMobile, isTablet, isDesktop, isLargeDesktop }) => { describe( `[AW IS CLOSED] onboarding (TOS accepted): ${device}`, { viewportHeight, viewportWidth }, @@ -104,13 +104,11 @@ Object.values(viewports).forEach( }); it('user can change steps by clicking the edge of the screen (up to 25px from each edge)', () => { - checkChangeStepsByClickingEdgeOfTheScreenUpTo25px(true, isMobile); + checkChangeStepsByClickingEdgeOfTheScreenUpTo25px(true, isMobile || isTablet); }); - // TODO will be unskipped in https://github.com/golemfoundation/octant/pull/624. - // eslint-disable-next-line it('user cannot change steps by clicking the edge of the screen (more than 25px from each edge)', () => { - checkChangeStepsByClickingEdgeOfTheScreenMoreThan25px(true, isMobile); + checkChangeStepsByClickingEdgeOfTheScreenMoreThan25px(true, isMobile || isTablet); }); it('user can change steps by swiping on screen (difference more than or equal 5px)', () => { diff --git a/client/cypress/utils/onboarding.ts b/client/cypress/utils/onboarding.ts index 62b859e789..d4642bd6e3 100644 --- a/client/cypress/utils/onboarding.ts +++ b/client/cypress/utils/onboarding.ts @@ -77,7 +77,7 @@ export const checkChangeStepsWithArrowKeys = (isTOSAccepted: boolean): void => { export const checkChangeStepsByClickingEdgeOfTheScreenUpTo25px = ( isTOSAccepted: boolean, - isMobile = false, + isMobileOrTablet = false, ): void => { checkCurrentElement(0, true); @@ -93,7 +93,7 @@ export const checkChangeStepsByClickingEdgeOfTheScreenUpTo25px = ( { clientX: leftEdgeX, el: 0 }, ].forEach(({ clientX, el }) => { cy.get('[data-test=ModalOnboarding]').click(clientX, element.height()! / 2, { - force: isMobile, + force: isMobileOrTablet, }); checkCurrentElement(el, isTOSAccepted || el === 0); @@ -106,7 +106,7 @@ export const checkChangeStepsByClickingEdgeOfTheScreenUpTo25px = ( export const checkChangeStepsByClickingEdgeOfTheScreenMoreThan25px = ( isTOSAccepted: boolean, - isMobile = false, + isMobileOrTablet = false, ): void => { checkCurrentElement(0, true); @@ -121,7 +121,7 @@ export const checkChangeStepsByClickingEdgeOfTheScreenMoreThan25px = ( { clientX: leftEdgeX + 25, el: 0 }, ].forEach(({ clientX, el }) => { cy.get('[data-test=ModalOnboarding]').click(clientX, element.height()! / 2, { - force: isMobile, + force: isMobileOrTablet, }); checkCurrentElement(el, isTOSAccepted || el === 0); diff --git a/client/src/components/shared/Layout/LayoutFooter/LayoutFooter.module.scss b/client/src/components/shared/Layout/LayoutFooter/LayoutFooter.module.scss index 191968f4b3..a898ec8905 100644 --- a/client/src/components/shared/Layout/LayoutFooter/LayoutFooter.module.scss +++ b/client/src/components/shared/Layout/LayoutFooter/LayoutFooter.module.scss @@ -29,6 +29,7 @@ } .info { + order: 1; width: 100%; display: flex; text-align: start; @@ -56,6 +57,7 @@ } .links { + order: 1; grid-template-columns: repeat(3, minmax(11.2rem, auto) [col-start]); padding: 3.2rem 0; width: 100%; @@ -66,6 +68,7 @@ border-bottom: 0.1rem solid $color-octant-grey1; @media #{$tablet-up} { + grid-template-columns: repeat(3, minmax(13.2rem, auto) [col-start]); margin: 0; border-bottom: none; padding: 0; @@ -107,6 +110,7 @@ } .newsletterWrapper { + order: 1; width: 100%; display: flex; flex-direction: column; @@ -147,3 +151,26 @@ } } } +.socialMedia { + display: flex; + gap: 3.2rem; + margin-right: auto; + padding-top: 4rem; + padding-bottom: 1.6rem; + + @media #{$tablet-up} { + padding-top: 3.2rem; + order: 1; + } + + @media #{$desktop-up} { + gap: 1.6rem; + } + + .socialMediaSvg:hover { + circle { + fill: $color-octant-dark; + transition: all $transition-time-1; + } + } +} diff --git a/client/src/components/shared/Layout/LayoutFooter/LayoutFooter.tsx b/client/src/components/shared/Layout/LayoutFooter/LayoutFooter.tsx index eb48f8414f..8bc4e60adf 100644 --- a/client/src/components/shared/Layout/LayoutFooter/LayoutFooter.tsx +++ b/client/src/components/shared/Layout/LayoutFooter/LayoutFooter.tsx @@ -3,6 +3,7 @@ import React, { FC, memo, useLayoutEffect, useRef } from 'react'; import { Trans, useTranslation } from 'react-i18next'; import LanguageSelectorWrapped from 'components/shared/Layout/LanguageSelectorWrapped'; +import Button from 'components/ui/Button'; import Svg from 'components/ui/Svg'; import { BLOG_POST, @@ -13,43 +14,33 @@ import { OCTANT_BUILD_LINK, OCTANT_DOCS, TERMS_OF_USE, - // TODO OCT-2097 Bring Twitter link back. - // TWITTER_LINK, PRIVACY_POLICY, + X_LINK, } from 'constants/urls'; import useMediaQuery from 'hooks/helpers/useMediaQuery'; -import { octantSemiTransparent } from 'svg/logo'; +import { discord, farcaster, octantSemiTransparent, X } from 'svg/logo'; import styles from './LayoutFooter.module.scss'; import LayoutFooterProps from './types'; const LayoutFooter: FC = ({ className }) => { const { t } = useTranslation('translation', { keyPrefix: 'layout.footer' }); - const { isDesktop, isMobile } = useMediaQuery(); + const { isMobile } = useMediaQuery(); const newsletterRef = useRef(null); const dataTestRoot = 'LayoutFooter'; - const links = isDesktop - ? [ - { id: 'website', label: t('links.website'), link: OCTANT_BUILD_LINK }, - { id: 'docs', label: t('links.docs'), link: OCTANT_DOCS }, - { id: 'blog', label: t('links.blog'), link: BLOG_POST }, - { id: 'discord', label: t('links.discord'), link: DISCORD_LINK }, - { id: 'farcaster', label: t('links.farcaster'), link: FARCASTER_LINK }, - // TODO OCT-2097 Bring Twitter/X back. - // { label: t('links.twitterX'), link: TWITTER_LINK }, - { id: 'brandAssets', label: t('links.brandAssets'), link: BRAND_ASSETS_FIGMA_LINK }, - { id: 'privacyPolicy', label: t('links.privacyPolicy'), link: PRIVACY_POLICY }, - { id: 'termsOfUse', label: t('links.termsOfUse'), link: TERMS_OF_USE }, - ] - : [ - { id: 'website', label: t('links.website'), link: OCTANT_BUILD_LINK }, - { id: 'docs', label: t('links.docs'), link: OCTANT_DOCS }, - { id: 'farcaster', label: t('links.farcaster'), link: FARCASTER_LINK }, - { id: 'discord', label: t('links.discord'), link: DISCORD_LINK }, - { id: 'privacyPolicy', label: t('links.privacyPolicy'), link: PRIVACY_POLICY }, - { id: 'termsOfUse', label: t('links.termsOfUse'), link: TERMS_OF_USE }, - ]; + const links = [ + { id: 'website', label: t('links.website'), link: OCTANT_BUILD_LINK }, + { id: 'docs', label: t('links.docs'), link: OCTANT_DOCS }, + { id: 'blog', label: t('links.blog'), link: BLOG_POST }, + { + id: 'brandAssets', + label: isMobile ? t('links.brand') : t('links.brandAssets'), + link: BRAND_ASSETS_FIGMA_LINK, + }, + { id: 'privacyPolicy', label: t('links.privacyPolicy'), link: PRIVACY_POLICY }, + { id: 'termsOfUse', label: t('links.termsOfUse'), link: TERMS_OF_USE }, + ]; useLayoutEffect(() => { if (!newsletterRef.current || newsletterRef.current.children.length || window.Cypress) { @@ -118,6 +109,29 @@ const LayoutFooter: FC = ({ className }) => { {!isMobile && } +
+
); }; diff --git a/client/src/constants/urls.ts b/client/src/constants/urls.ts index d84ff08244..dc87ee02d4 100644 --- a/client/src/constants/urls.ts +++ b/client/src/constants/urls.ts @@ -5,7 +5,7 @@ export const OCTANT_DOCS = 'https://docs.octant.app/'; export const DISCORD_LINK = 'https://discord.gg/octant'; export const BLOG_POST = 'https://blog.octant.build/'; export const OCTANT_BUILD_LINK = 'https://octant.build/'; -export const TWITTER_LINK = 'https://x.com/OctantApp'; +export const X_LINK = 'https://x.com/OctantApp'; export const FARCASTER_LINK = 'https://warpcast.com/octant'; export const TERMS_OF_USE = 'https://docs.octant.app/terms-of-use.html'; export const GITCOIN_PASSPORT = 'https://support.passport.xyz/passport-knowledge-base'; diff --git a/client/src/hooks/helpers/useOnboardingSteps/steps.tsx b/client/src/hooks/helpers/useOnboardingSteps/steps.tsx index 2be7e12523..f48fe0f9df 100644 --- a/client/src/hooks/helpers/useOnboardingSteps/steps.tsx +++ b/client/src/hooks/helpers/useOnboardingSteps/steps.tsx @@ -4,7 +4,7 @@ import { Trans } from 'react-i18next'; import styles from 'components/shared/ModalOnboarding/ModalOnboarding.module.scss'; import { Step } from 'components/shared/ModalOnboarding/types'; import Button from 'components/ui/Button'; -import { DISCORD_LINK, FARCASTER_LINK, OCTANT_BUILD_LINK, TWITTER_LINK } from 'constants/urls'; +import { DISCORD_LINK, FARCASTER_LINK, OCTANT_BUILD_LINK, X_LINK } from 'constants/urls'; import i18n from 'i18n'; export const getStepsDecisionWindowOpen = (epoch: string, changeAWDate: string): Step[] => [ @@ -90,7 +90,7 @@ export const getStepsDecisionWindowClosed = (epoch: string, changeAWDate: string components={[