diff --git a/components/molecules/Hero/index.tsx b/components/molecules/Hero/index.tsx new file mode 100644 index 00000000..01f328ac --- /dev/null +++ b/components/molecules/Hero/index.tsx @@ -0,0 +1,37 @@ +import { FunctionComponent, PropsWithChildren } from "react"; +import * as Styled from "./styles"; + +interface HeroProps { + data: Array; + focalPointX?: number; + focalPointY?: number; + className?: string; +} +const Hero: FunctionComponent> = ({ + data, + focalPointX = 50, + focalPointY = 50, + className, + children, +}) => { + const imageData = data && data[0]; + + if (!imageData?.url) return null; + + return ( + + + {children} + + ); +}; + +Hero.displayName = "Molecule.Hero"; + +export default Hero; diff --git a/components/page/Hero/styles.js b/components/molecules/Hero/styles.ts similarity index 74% rename from components/page/Hero/styles.js rename to components/molecules/Hero/styles.ts index cc432a93..625b73e0 100644 --- a/components/page/Hero/styles.js +++ b/components/molecules/Hero/styles.ts @@ -1,6 +1,7 @@ +"use client"; import styled from "styled-components"; import { fluidScale, containerFullBleed } from "@/styles/globalStyles"; -import { Image } from "@rubin-epo/epo-react-lib"; +import Image from "@rubin-epo/epo-react-lib/Image"; export const HeroContainer = styled.div` ${containerFullBleed("CONTAINER_FULL")} @@ -10,10 +11,6 @@ export const HeroContainer = styled.div` `; export const HeroImage = styled(Image)` - --Hero-object-position: ${({ $focalPointX, $focalPointY }) => - `${$focalPointX}% ${$focalPointY}%;`} - width: 100%; - /* stylelint-disable declaration-no-important */ height: 100% !important; object-fit: cover; diff --git a/components/page/Hero/index.js b/components/page/Hero/index.js deleted file mode 100644 index c3956684..00000000 --- a/components/page/Hero/index.js +++ /dev/null @@ -1,37 +0,0 @@ -import PropTypes from "prop-types"; -import imageShape from "@/shapes/image"; -import * as Styled from "./styles"; - -export default function Hero({ - data, - focalPointX, - focalPointY, - className, - children, -}) { - const imageData = data && data[0]; - - if (!imageData?.url) return null; - - return ( - - - {children} - - ); -} - -Hero.displayName = "Global.Hero"; - -Hero.propTypes = { - data: PropTypes.arrayOf(imageShape), - children: PropTypes.node, - className: PropTypes.string, - focalPointX: PropTypes.number, - focalPointY: PropTypes.number, -}; diff --git a/components/page/PageContent/styles.js b/components/page/PageContent/styles.js index 053e8ce4..e4acd26d 100644 --- a/components/page/PageContent/styles.js +++ b/components/page/PageContent/styles.js @@ -1,5 +1,5 @@ import styled from "styled-components"; -import HeroComponent from "@/page/Hero"; +import HeroComponent from "@/components/molecules/Hero"; import { fluidScale, respond, @@ -23,8 +23,6 @@ export const Hero = styled(HeroComponent)` WIDE_BREAKPOINT, MOBILE_BREAKPOINT )}; - --Hero-object-position: ${({ $focalPointX, $focalPointY }) => - `${$focalPointX}% ${$focalPointY}%;`} --hero-overlap: ${HERO_OVERLAP}; `; diff --git a/components/templates/EventPage/index.js b/components/templates/EventPage/index.js index 2225e213..6e90a9e0 100644 --- a/components/templates/EventPage/index.js +++ b/components/templates/EventPage/index.js @@ -6,7 +6,7 @@ import { createLocationString, useCustomBreadcrumbs, } from "@/lib/utils"; -import Hero from "@/page/Hero"; +import Hero from "@/components/molecules/Hero"; import ContentBlockFactory from "@/factories/ContentBlockFactory"; import { Share } from "@/content-blocks"; import Breadcrumbs from "@/page/Breadcrumbs"; diff --git a/components/templates/HomePage/index.js b/components/templates/HomePage/index.js index efc52429..64c6e39f 100644 --- a/components/templates/HomePage/index.js +++ b/components/templates/HomePage/index.js @@ -2,7 +2,7 @@ import PropTypes from "prop-types"; import { useTranslation } from "react-i18next"; import ContentBlockFactory from "@/factories/ContentBlockFactory"; -import Hero from "@/page/Hero"; +import Hero from "@/components/molecules/Hero"; import { Buttonish, MixedLink } from "@rubin-epo/epo-react-lib"; import { makeDateString, makeTruncatedString } from "@/lib/utils"; import { SlideBlock } from "@/components/content-blocks"; diff --git a/cypress/e2e/homepage.cy.js b/cypress/e2e/homepage.cy.js index db8a64f7..7d23b879 100644 --- a/cypress/e2e/homepage.cy.js +++ b/cypress/e2e/homepage.cy.js @@ -1,4 +1,4 @@ -describe("Search from Homepage", () => { +describe("Homepage", () => { beforeEach(() => { // Cypress starts out with a blank slate for each test // so we must tell it to visit our website with the `cy.visit()` command. @@ -6,7 +6,13 @@ describe("Search from Homepage", () => { // we include it in our beforeEach function so that it runs before each test cy.visit("/"); }); - + it("has a hero image with priority loading", () => { + cy.get("[data-cy=hero] > img") + .invoke("attr", "src") + .should("have.length.gt", 0); + cy.get("[data-cy=hero] > img").should("have.attr", "loading", "eager"); + cy.get("[data-cy=hero] > img").should("have.attr", "decoding", "sync"); + }); it("Searching yields results", () => { cy.get(".c-search-bar__toggle").click(); cy.get("#headerSearchBar").should("be.visible").type("rubin{enter}"); diff --git a/types/css.d.ts b/types/css.d.ts new file mode 100644 index 00000000..e38354a4 --- /dev/null +++ b/types/css.d.ts @@ -0,0 +1,6 @@ +declare module "csstype" { + interface Properties { + // Allow any CSS Custom Properties + [index: `--${string}`]: any; + } +}