From a2f24fc8dba264f92db12a1b3bff203c9d966b67 Mon Sep 17 00:00:00 2001 From: Maya Raman Date: Tue, 27 Feb 2024 18:11:45 -0500 Subject: [PATCH] DOP 4340/1: Homepage Redesign (#1016) Co-authored-by: Anabella Buckvar Co-authored-by: anabellabuckvar <41971124+anabellabuckvar@users.noreply.github.com> --- src/components/Card/CardGroup.js | 28 ++- src/components/Card/index.js | 94 +++++++-- src/components/Sidenav/Sidenav.js | 3 +- src/templates/landing.js | 127 +++++------- tests/unit/__snapshots__/Card.test.js.snap | 48 ++--- .../unit/__snapshots__/CardGroup.test.js.snap | 142 +++++++------- tests/unit/__snapshots__/CardRef.test.js.snap | 180 +++++++++--------- 7 files changed, 338 insertions(+), 284 deletions(-) diff --git a/src/components/Card/CardGroup.js b/src/components/Card/CardGroup.js index 6a8f5c30f..d51203bd2 100644 --- a/src/components/Card/CardGroup.js +++ b/src/components/Card/CardGroup.js @@ -5,11 +5,14 @@ import PropTypes from 'prop-types'; import ComponentFactory from '../ComponentFactory'; import { theme } from '../../theme/docsTheme'; -const getMarginStyles = (isForDriver, sideMarginValue) => { +const getMarginStyles = (isForDriver, isLanding, columns, sideMarginValue) => { if (typeof sideMarginValue !== 'number') { console.warn('sideMarginValue only accepts a number'); } - return isForDriver ? `0 ${sideMarginValue}px ${theme.size.xlarge}` : `${theme.size.large} 0`; + if (isForDriver) return `0 ${sideMarginValue}px ${theme.size.xlarge}`; + else if (isLanding && columns !== 3) return `${theme.size.large} ${sideMarginValue}px`; + else if (isLanding && columns === 3) return `${theme.size.medium} ${sideMarginValue}px ${theme.size.xlarge}`; + else return `${theme.size.large} 0`; }; const getColumnValue = (props) => props.columns || React.Children.count(props.children); @@ -48,19 +51,25 @@ const StyledGrid = styled('div')` grid-column-gap: ${theme.size.medium}; grid-row-gap: ${theme.size.medium}; grid-template-columns: ${(props) => `repeat(${getColumnValue(props)}, 1fr)`}; - margin: ${({ isForDrivers }) => getMarginStyles(isForDrivers, 0)}; + + margin: ${({ isForDrivers, isLanding, columns }) => getMarginStyles(isForDrivers, isLanding, columns, 0)}; @media ${theme.screenSize.upToMedium} { - margin: ${({ isForDrivers }) => getMarginStyles(isForDrivers, 42)}; + margin: ${({ isForDrivers, isLanding, columns }) => getMarginStyles(isForDrivers, isLanding, columns, 42)}; } @media ${theme.screenSize.upToSmall} { - margin: ${({ isForDrivers }) => getMarginStyles(isForDrivers, 24)}; + margin: ${({ isForDrivers, isLanding, columns }) => getMarginStyles(isForDrivers, isLanding, columns, 24)}; } - @media ${theme.screenSize.upToXLarge} { - grid-template-columns: repeat(2, 1fr); + ${ + '' /*want first 4 cards on landing page to stay as one column, and not affect group of 3 cards (so hacky i'm sorry) */ } + @media ${theme.screenSize.upToXLarge} { + ${({ isLanding, columns }) => { + if (isLanding) return `grid-template-columns: repeat(${columns}, 1fr);`; + else return `grid-template-columns: repeat(2, 1fr);`; + }} @media ${theme.screenSize.upToMedium} { ${({ isCarousel, ...props }) => @@ -81,12 +90,14 @@ const CardGroup = ({ children, options: { columns, layout, style, type }, }, + page, ...rest }) => { const isCompact = style === 'compact'; const isExtraCompact = style === 'extra-compact'; const isCarousel = layout === 'carousel'; const isForDrivers = type === 'drivers'; + const isLanding = page?.options?.template === 'landing'; return ( {children.map((child, i) => ( ))} @@ -124,6 +137,7 @@ CardGroup.propTypes = { columns: PropTypes.number, }), }).isRequired, + page: PropTypes.object, }; export default CardGroup; diff --git a/src/components/Card/index.js b/src/components/Card/index.js index ffd33db59..6257f5622 100644 --- a/src/components/Card/index.js +++ b/src/components/Card/index.js @@ -17,6 +17,36 @@ const cardBaseStyles = css` height: 100%; `; +const landingStyles = css` + flex-direction: row; + padding-left: ${theme.size.medium}; + img { + width: ${theme.size.xlarge}; + height: fit-content; + } + div { + display: flex; + flex-direction: column; + margin-left: ${theme.size.large}; + p:first-child { + font-size: ${theme.fontSize.h2}; + font-weight: 500; + margin: 0px 0px ${theme.size.default} 0px; + } + } + + ${'' /* Mobile view */} + @media ${theme.screenSize.upToSmall} { + flex-direction: column; + img { + margin-bottom: ${theme.size.medium}; + } + div { + margin-left: 0px; + } + } +`; + const cardStyling = css` flex-direction: column; padding: ${theme.size.large}; @@ -36,6 +66,16 @@ const cardDriverStyle = css` } `; +const landingBottomStyling = css` + img { + width: 50px; + } + p { + font-weight: 500; + line-height: ${theme.size.medium}; + } +`; + const CardIcon = styled('img')` width: ${theme.size.large}; `; @@ -97,13 +137,22 @@ const Card = ({ options: { cta, headline, icon, 'icon-alt': iconAlt, tag, url }, }, }) => { + const template = page?.options?.template; + + const isLanding = template === 'landing'; + const Icon = ['landing', 'product-landing'].includes(template) ? CardIcon : CompactIcon; + + /* If tag == 'landing-bottom', this is 2nd group of cards on + landing page which we want to keep exempt from landing styles */ + const isLandingBottom = tag === 'landing-bottom'; + const styling = [ cardBaseStyles, isForDrivers ? cardDriverStyle : cardStyling, + isLanding && !isLandingBottom ? landingStyles : '', // must come after other styles to override + isLandingBottom ? landingBottomStyling : '', isCompact || isExtraCompact ? compactCardStyling : '', ]; - const template = page?.options?.template; - const Icon = ['landing', 'product-landing'].includes(template) ? CardIcon : CompactIcon; return ( onCardClick(url) : undefined}> @@ -112,25 +161,28 @@ const Card = ({ condition={isCompact || isExtraCompact} wrapper={(children) => {children}} > - {tag && {tag}} - {headline && ( - - {headline} - - )} - {children.map((child, i) => ( - // The cardRef prop's purpose to distinguish wich RefRoles are coming from the Card component (a workaround while we figure out card-ref support in the parser/) - - ))} - {cta && ( - - {cta} - - )} + {tag && !isLandingBottom && {tag}} +
+ {headline && ( + + {headline} + + )} + {children.map((child, i) => ( + // The cardRef prop's purpose to distinguish wich RefRoles are coming from the Card component (a workaround while we figure out card-ref support in the parser/) + + ))} + + {cta && ( + + {cta} + + )} +
); diff --git a/src/components/Sidenav/Sidenav.js b/src/components/Sidenav/Sidenav.js index f9a86c659..db250f18b 100644 --- a/src/components/Sidenav/Sidenav.js +++ b/src/components/Sidenav/Sidenav.js @@ -189,6 +189,7 @@ const Sidenav = ({ chapters, guides, page, pageTitle, repoBranches, siteTitle, s const ia = page?.options?.ia; const template = page?.options?.template; + const isLanding = template === 'landing'; const isGuidesLanding = project === 'guides' && template === 'product-landing'; const isGuidesTemplate = template === 'guide'; @@ -264,7 +265,7 @@ const Sidenav = ({ chapters, guides, page, pageTitle, repoBranches, siteTitle, s /> {ia && ( {formatText(pageTitle)}} + header={!isLanding && {formatText(pageTitle)}} handleClick={() => { setBack(false); hideMobileSidenav(); diff --git a/src/templates/landing.js b/src/templates/landing.js index e8b78ce9b..5f1b93708 100644 --- a/src/templates/landing.js +++ b/src/templates/landing.js @@ -9,28 +9,6 @@ const CONTENT_MAX_WIDTH = 1440; const SHOW_CHATBOT = process.env['GATSBY_SHOW_CHATBOT'] === 'true'; -const newLandingCardStyling = () => css` - &:not(.compact, .extra-compact, .drivers) { - p { - font-weight: 500; - - a { - margin-top: ${({ theme }) => theme.size.medium}; - } - } - - @media ${({ theme }) => theme.screenSize.upToMedium} { - margin-left: 42px; - margin-right: 42px; - } - - @media ${({ theme }) => theme.screenSize.upToSmall} { - margin-left: ${({ theme }) => theme.size.medium}; - margin-right: ${({ theme }) => theme.size.medium}; - } - } -`; - const Wrapper = styled('main')` margin: 0 auto; width: 100%; @@ -65,8 +43,6 @@ const Wrapper = styled('main')` @media ${({ theme }) => theme.screenSize.mediumAndUp} { grid-column: 2 / -2 !important; } - - ${({ newChatbotLanding }) => newChatbotLanding && newLandingCardStyling()} } } `; @@ -127,24 +103,29 @@ const Landing = ({ children, pageContext, useChatbot }) => { } main h1:first-of-type { color: ${palette.white}; - ${SHOW_CHATBOT && useChatbot - ? ` - color: ${palette.black}; - grid-column: 2/-1; - margin: ${size.large} 0; - font-size: 48px; - line-height: 62px; - - @media ${screenSize.upToSmall} { - font-size: 32px; - line-height: 40px; - } - ` - : ` - @media ${screenSize.upToMedium} { - color: ${palette.green.dark2}; - } - `} + grid-column: 2/-1; + margin-top: ${size.medium}; + font-size: 48px; + line-height: 62px; + margin-bottom: 10px; + align-self: end; + @media ${screenSize.upToMedium} { + font-size: 32px; + line-height: 40px; + margin-top: ${size.medium}; + } + } + ${ + '' /* :first-of-type selector used for precedence + above LeafyGreen class selector */ + } + main>section>section:first-of-type h2 { + color: ${palette.gray.dark4}; + font-size: 32px; + font-family: 'MongoDB Value Serif'; + font-weight: 400; + margin-top: ${size.medium}; + margin-bottom: 0px; } .span-columns { grid-column: 3 / -3 !important; @@ -161,59 +142,53 @@ const Landing = ({ children, pageContext, useChatbot }) => { .hero-img { grid-column: 1 / -1; grid-row: 1 / 3; - height: 310px; width: 100%; object-fit: cover; z-index: -1; + object-position: 50%; - @media ${screenSize.upToMedium} { - grid-row: unset; - object-position: 100%; + @media ${screenSize.upToXSmall} { + height: 555px; } - @media ${screenSize.upToSmall} { - grid-row: unset; - height: 200px; - object-position: 85%; + @media ${screenSize.xSmallAndUp} { + height: 430px; + } + + @media ${screenSize.smallAndUp} { + height: 317px; } - @media only screen and (max-width: 320px) { - object-position: 100%; + @media ${screenSize.largeAndUp} { + height: 280px; + } + + @media ${screenSize.xLargeAndUp} { + height: 250px; } } + .introduction { - grid-column: 2 / 8; + grid-column: 2 / -4; grid-row: 2 / 3; + p { + color: ${palette.white}; + } @media ${screenSize.upToMedium} { grid-column: 2 / -2; - - p { - color: ${palette.black}; - } } - @media ${screenSize.mediumAndUp} { - p { - color: ${palette.white}; - } + @media ${screenSize.xLargeAndUp} { + grid-column: 2 / -5; } - } - @media ${screenSize.upToLarge} { - .footer { - padding: ${size.medium}; - } - } - @media ${screenSize.mediumAndUp} { - .right-column { - grid-column: 7 / -1 !important; - grid-row-start: 1 !important; - grid-row-end: 3 !important; + + @media ${screenSize['2XLargeAndUp']} { + grid-column: 2 / -3; } - } - @media ${screenSize.largeAndUp} { - .right-column { - grid-column: 9 / -1 !important; + + @media ${screenSize['3XLargeAndUp']} { + grid-column: 2 / -2; } } `} diff --git a/tests/unit/__snapshots__/Card.test.js.snap b/tests/unit/__snapshots__/Card.test.js.snap index 23cecfee8..d256bbebe 100644 --- a/tests/unit/__snapshots__/Card.test.js.snap +++ b/tests/unit/__snapshots__/Card.test.js.snap @@ -197,31 +197,33 @@ exports[`renders correctly 1`] = ` > Test card tag -

- Test card headline -

-

- Test card paragraph -

-

- +

+ Test card headline +

+

+ Test card paragraph +

+

- - Test card CTA - - -

+ + Test card CTA + + +

+ `; diff --git a/tests/unit/__snapshots__/CardGroup.test.js.snap b/tests/unit/__snapshots__/CardGroup.test.js.snap index d51ccc4c0..564b8e672 100644 --- a/tests/unit/__snapshots__/CardGroup.test.js.snap +++ b/tests/unit/__snapshots__/CardGroup.test.js.snap @@ -31,22 +31,22 @@ exports[`renders correctly 1`] = ` .emotion-0 { grid-template-columns: repeat(2, 1fr); } -} -@media only screen and (max-width: 767px) { - .emotion-0 { - grid-gap: calc(24px * 0.75); - grid-template-columns: calc(24px / 2) repeat(3, calc(75% - calc(2 * 24px))) calc(24px / 2); - grid-template-rows: minmax(150px, 1fr); - margin: 24px 0; - overflow-x: scroll; - padding-bottom: calc(24px / 2); - scroll-snap-type: x proximity; - } + @media only screen and (max-width: 767px) { + .emotion-0 { + grid-gap: calc(24px * 0.75); + grid-template-columns: calc(24px / 2) repeat(3, calc(75% - calc(2 * 24px))) calc(24px / 2); + grid-template-rows: minmax(150px, 1fr); + margin: 24px 0; + overflow-x: scroll; + padding-bottom: calc(24px / 2); + scroll-snap-type: x proximity; + } - .emotion-0:before, - .emotion-0:after { - content: ''; + .emotion-0:before, + .emotion-0:after { + content: ''; + } } } @@ -241,26 +241,28 @@ exports[`renders correctly 1`] = `
-

- Use Compass to connect to your Atlas cluster -

-

- +

- +

+ - Read Atlas docs - - -

+ + Read Atlas docs + + +

+
-

- Learn MongoDB Basics with MongoDB University -

-

- +

+ Learn MongoDB Basics with MongoDB University +

+

- - Learn MongoDB Basics - - -

+ + Learn MongoDB Basics + + +

+
-

- Access more in-depth examples of querying data -

-

- +

+ Access more in-depth examples of querying data +

+

- - Read Server docs - - -

+ + Read Server docs + + +

+
diff --git a/tests/unit/__snapshots__/CardRef.test.js.snap b/tests/unit/__snapshots__/CardRef.test.js.snap index ef807af31..39f4cf783 100644 --- a/tests/unit/__snapshots__/CardRef.test.js.snap +++ b/tests/unit/__snapshots__/CardRef.test.js.snap @@ -31,20 +31,20 @@ exports[`card correctly with and without url 1`] = ` .emotion-0 { grid-template-columns: repeat(2, 1fr); } -} -@media only screen and (max-width: 767px) { - .emotion-0 { - grid-template-columns: repeat(1, 1fr); - grid-column-gap: 16px; + @media only screen and (max-width: 767px) { + .emotion-0 { + grid-template-columns: repeat(1, 1fr); + grid-column-gap: 16px; + } } -} -@media only screen and (max-width: 480px) { - .emotion-0 { - grid-column-gap: 16px; - grid-template-columns: 'auto'; - grid-row-gap: '16px'; + @media only screen and (max-width: 480px) { + .emotion-0 { + grid-column-gap: 16px; + grid-template-columns: 'auto'; + grid-row-gap: '16px'; + } } } @@ -351,66 +351,68 @@ exports[`card correctly with and without url 1`] = `
-

- Realm SDKs -

-

- Use platform-specific libraries to include and work with the Realm database in your application. -

-

- +

- Android - - - - +

- iOS - - - - +

- .Net - - + + Android + + - - Web - - + + iOS + + - - React Native - - + + .Net + + - - Node.js - -

+ + Web + + + + + React Native + + + + + Node.js + +

+
-

- MongoDB Realm -

-

- Discover how to sync data, define permissions, and connect to other services, including MongoDB Atlas. -

-

- +

+ MongoDB Realm +

+

+ Discover how to sync data, define permissions, and connect to other services, including MongoDB Atlas. +

+

- - Learn more about MongoDB Realm Application Services - - -

+ + Learn more about MongoDB Realm Application Services + + +

+