Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
import { Data } from "./data";
import Composition from "src/lib/Composition";
import NewsBanner from "./index";
const { compositionFunction, component } = Composition(NewsBanner)(
({ fields, rendering }) => {
const link = fields?.["CTA URL"];
return {
icon: fields?.["Icon Path"]?.value,
rounded: fields?.Rounded?.value,
title: fields?.Title,
body: fields?.Body,
bgColorClass: fields?.["BG Color"]?.fields?.Value?.value,
cta: {
href: fields?.["CTA URL"]?.value?.href,
target: fields?.["CTA URL"]?.value?.target,
text: fields?.["CTA URL"]?.value?.text,
},
};
}
);
export { compositionFunction };
export default component;
end of code
This is a full-width component.
It includes a visual, a title, a description, a CTA button and a background.
A title is required
Text that exceeds the available content space will be truncated.
The visual is required. An icon or image may be used as the supporting visual.
The height for the banner should be determined by the height of the content plus the top and bottom spacing. Therefore, banners including icons and images will vary in height.
On desktop, the max height of the banner with an icon is 140px. The max height of the banner with an image is 170px on desktop.
On mobile, the max height of the banner with an icon is 296px. The max height of the banner with an image is 324px on mobile.
The description and CTA button are optional.
The content area should be centered horizontally when when the CTA is not displayed.
There are predefined background options.
import { Text } from "@sitecore-jss/sitecore-jss-react";
import React from "react";
import LazyImage from "src/components/LazyImage";
import { NewsBannerProps } from "./types";
import RichText from "src/components/RichText";
import Button from "src/components/Button";
const NewsBanner = ({
icon,
rounded,
title,
body,
bgColorClass,
cta,
}: NewsBannerProps) => {
const ctaExists = cta?.href && cta?.text;
const iconRounded = rounded ? "rounded-full" : "";
const iconSize = icon?.value?.src?.includes(".svg")
? "icon-48 sm:icon-76"
: "icon-76 sm:icon-122";
return (
<section className={`px-16 md:px-24 py-24 md:py-32 ${bgColorClass}`}>
<div
className={`lg:flex-row container-3xl lg:space-x-32 flex flex-col items-center lg:justify-center text-center lg:text-left`}
>
<div className={` py-24 lg:px-24 flex-shrink-0 }`}>
<LazyImage
{...icon}
className={`mx-auto lg:mx-0 w-full ${iconSize} ${iconRounded}`}
/>
</div>
<div>
<Text className="text-xl" field={title} tag="h3" />
<RichText className="mt-10 lg:line-clamp-3" field={body} tag="p" />
</div>
<div className="flex-shrink-0 mt-12 md:mt-16 lg:mt-0">
{ctaExists && (
<Button
className="flex-shrink-0 block mt-16 lg:mt-0 lg:ml-24 xl:ml-32"
target={cta?.target}
variant="secondary"
{...cta}
>
{cta?.text}
</Button>
)}
</div>
</div>
</section>
);
};
export default NewsBanner;
/*
This is a full-width component.
It includes a visual, a title, a description, a CTA button and a background.
A title is required
Text that exceeds the available content space will be truncated.
The visual is required. An icon or image may be used as the supporting visual.
The height for the banner should be determined by the height of the content plus the top and bottom spacing. Therefore, banners including icons and images will vary in height.
On desktop, the max height of the banner with an icon is 140px. The max height of the banner with an image is 170px on desktop.
On mobile, the max height of the banner with an icon is 296px. The max height of the banner with an image is 324px on mobile.
The description and CTA button are optional.
The content area should be centered horizontally when when the CTA is not displayed.
There are predefined background options.
Explanation for the correlating marker
*/
import { render, screen } from "@testing-library/react";
import { renderWithContext } from "src/lib/testWrappers";
import NewsBanner from "./index";
import { compositionFunction } from "./composition";
import { Data } from "./data";
import "@testing-library/jest-dom";
jest.mock("src/lib/useIntersection");
const props = compositionFunction(Data);
//## Describe: Newsbar Component
// #### it:
// #### it: should render a cta button if the data CTA URL filed exists else: do not render cta
// #### it: should render the body text if the field exists in the data file. else: do not render text
//------------------------------
describe("News Banner", () => {
const props = compositionFunction(Data);
it("should render NewsBanner component with Title & Image", () => {
//look up memory router...
renderWithContext(<NewsBanner {...props} />);
screen.logTestingPlaygroundURL();
// to launch browser based playground... needs to gafter a render has been called.
const title = screen.getByRole("heading", {
name: /here to help during this difficult time\./i,
});
const img = screen.getByRole("img", {
name: /image alt text/i,
});
expect(title).toBeInTheDocument();
expect(img).toBeInTheDocument();
});
it("renders body text if the data exists on the object", () => {
const { rerender } = renderWithContext(<NewsBanner {...props} />);
const body = screen.getByText(
/customers who need additional time to pay any outstanding balance may qualify for financial assistance\. learn how we are taking action to help in response to covid\-19\./i
);
expect(body).toBeInTheDocument();
rerender(<NewsBanner {...props} body={undefined} />);
//querry by text will not throw an error if it does not find the element it is looking for.
const noBodyText = screen.queryByText(
/customers who need additional time to pay any outstanding balance may qualify for financial assistance\. learn how we are taking action to help in response to covid\-19\./i
);
expect(noBodyText).not.toBeInTheDocument();
});
it("renders a cta button if the data is present on the object, and does not render a button otherwise.", () => {
const { rerender } = renderWithContext(<NewsBanner {...props} />);
//in each it block scope
const ctaButton = screen.getByRole("link", {
name: /view resources/i,
});
expect(ctaButton).toBeInTheDocument();
rerender(<NewsBanner {...props} cta={undefined} />);
const noCTAButton = screen.queryByRole("link", {
name: /view resources/i,
});
expect(noCTAButton).not.toBeInTheDocument();
});
});
import React from "react";
import { Data } from "./data";
import { compositionFunction } from "./composition";
import NewsBanner from "./index";
const props = compositionFunction(Data);
// props has desired shape of data as storybook substitute for composition function.
export default {
title: "components/NewsBanner",
component: NewsBanner,
};
const Template = (args) => {
return <NewsBanner {...args} />;
};
export const Primary = Template.bind({});
Primary.args = {
...props,
};
export const Data = {
fields: {
"Icon Path": {
value: {
src: "https:
//scdev13.duke-energy.com/_/media/images/flipboard/flipboard-electric-vehicle.jpg",
alt: "Image Alt Text",
},
},
Rounded: {
value: true,
},
Title: {
value: "Here to help during this difficult time.",
},
Body: {
value:
"Customers who need additional time to pay any outstanding balance may qualify for financial assistance. Learn how we are taking action to help in response to COVID-19.",
},
"BG Color": {
fields: {
Value: {
value: "bg-teal-lighter",
},
Setting: {
value: "Teal",
},
},
},
"CTA URL": {
value: {
href: "/test/newsbanner/cta",
target: "_self",
text: "View Resources",
},
},
},
};
interface ctaTypes {
//https:
//stackoverflow.com/questions/67494696/typescript-require-at-least-one-property
target?: string;
href?: string;
text?: string;
}
//how do I make the namespace errors go away?
interface NewsBannerProps {
title: JSS.TextField;
icon: JSS.ImageField;
rounded?: boolean;
cta?: ctaTypes;
body?: JSS.TextField;
bgColorClass?: string;
color?: string;
}
export type { NewsBannerProps };