arrow-left

All pages
gitbookPowered by GitBook
1 of 2

Loading...

Loading...

DNT-2930 Hero Component

hashtag
Hero

Features a full-width image (light or dark) with superimposed text (light or dark contrasting). See a demo pagearrow-up-right with a site header.

hashtag
Usage Guidance

Do

  • Use on home pages and landing pages with multiple child pages.

  • When used on pages other than Home Pages or Section Landing Pages, the headline (H1) must be the page title.

  • Include a title/headline (required), a description (optional), and call-to-action link button(s) (optional).

Do Not

  • Use more than ONE Hero on a page.

Toggle Component Options

Theme Black to Gray-Darker Blue-Dark to Blue Blue to Teal-Darker Green-Dark to Green Blue-Dark to Green-Dark Green-Dark to Blue-Dark Gray-Light to white Gray-Light to Gray-Lighter Teal-Light to Teal-Lighter Image Business Solar Chef Family Landscape One Person Store Solar Solar Cell Two Person Store Content Content 1 Content 2 Content 3 Too Much Content Action No Actions Primary Action Primary and Secondary Action

hashtag
Say Yes to Renewables

Striving for sustainability is just smart business

hashtag
Accessibility

Labeling Expectations

  • Use a unique `id=""` on the title.

  • Use a unique `id=""` on the action link button(s).

  • Use `aria-labelledby=""` on the link buttons referencing the id of the link button(s) and the id of the title.

Keyboard Expectations

  • When you TAB into the `Hero` component, focus will go onto the link button(s).

Resources

Ensure that images clearly communicate the concept across all breakpoints and that critical information is not cropped out.

START NOWarrow-up-right
Web Accessibility: Linksarrow-up-right
<!--
  Hero Section wrapper
  - Component below hero is required to use a white background color
-->

<section class="relative 2xl:px-24 2xl:pt-24">

  <!--
    Hero Container
  -->

  <div class="relative container-5xl flex flex-col justify-center aspect-16/12 sm:aspect-16/9 md:aspect-16/7 lg:aspect-16/6 xl:aspect-16/5 px-24 sm:px-32 md:px-48 py-64 md:py-48">

    <!--
      - Leave alt attribute empty
      - Use 'srcset' and 'sizes' attributes to optimize the hero image
    -->

    <img
      class="absolute top-0 left-0 object-cover object-right w-full h-full 2xl:rounded-lg bg-gray-light"
      src="image.jpg?w=800&as=1&bc=ffffff"
      srcset="image.jpg?w=800&as=1&bc=ffffff 800w,
              image.jpg?w=1600&as=1&bc=ffffff 1600w"
      sizes="(min-width: 768px) 1600px, 800px"
      alt=""
      width="1600"
      height="500"
      loading="lazy"
    >

    <!--
      Overlay
      - Change background gradient colors based on theme of hero
      - Default - "from-blue-dark to-blue sm:via-blue"
    -->

    <div
      class="absolute top-0 left-0 h-full w-full 2xl:rounded-l-lg md:w-3/4 bg-gradient-to-tr md:bg-gradient-to-r md:to-transparent opacity-80"
      aria-hidden="true"
    ></div>

    <!--
      Content Container
    -->

    <div class="relative w-full container-xs md:container-4xl">

      <!--
        If dark theme/gradient, text is white
          - Use "text-white"
        If light theme/gradient, text can be gray or blue
          - Use "text-gray-dark" -or- "text-blue"
        Default
          - "text-white"
      -->

      <div class="w-full md:w-1/2 text-center md:text-left">

        <!-- Hero Title
          - If this is the page title, you should use an <h1> element
          - Use an <h2> element if you already have a page title on the page
        -->
        <h2
          class="text-3xl md:text-2xl-fixed xl:text-3xl"
          id="hero-title"
        >
          Hero Title
        </h2>

        <!-- Hero Short Description-->
        <p class="text-lg xl:text-xl mt-12 lg:mt-16">
          Description goes here.
        </p>

        <!-- Hero Actions -->
        <div class="flex justify-center md:justify-start gap-16 lg:gap-24 mt-16 lg:mt-24">
          <!--
            If dark theme/gradient
              - Use "btn-primary-reversed"
            If light theme/gradient
              - Use "btn-primary"
            Default
              - "btn-primary-reversed"
          -->
          <a
            class="btn btn-primary-reversed btn-md"
            href="#"
            id="hero-primary-action"
            aria-labelledby="hero-primary-action hero-title"
          >
            Primary Action
          </a>
          <!--
            If dark theme/gradient
              - Use "btn-secondary-reversed"
            If light theme/gradient
              - Use "btn-secondary"
            Default
              - "btn-secondary-reversed"
          -->
          <a
            class="btn btn-secondary-reversed btn-sm lg:btn-md"
            href="#"
            id="hero-secondary-action"
            aria-labelledby="hero-secondary-action hero-title"
          >
            Secondary Action
          </a>
        </div>
      </div>

    </div>

  </div>

</section>

DNT-2785

/info/unindexed/dpa-conversion-business

The Image Slideshow component seems to have shrunk after JSS conversion. See it here: https://scprod-cms.duke-energy.com/info/unindexed/dpa-conversion-businessarrow-up-right, compared to pre-JSS: https://scdev28.duke-energy.com/info/unindexed/dpa-conversion-businessarrow-up-right. As you can see, it cuts off some of the image space and the description underneath is completely gone.

chevron-rightModal.tsxhashtag
import React, { useRef, PropsWithChildren } from 'react';
import { createPortal } from 'react-dom';
import { a11yAction } from 'src/lib/helpers';
import { Placeholder } from '@sitecore-jss/sitecore-jss-react';
import SvgLoader from 'src/components/SvgLoader';
import Transition from 'src/lib/Transition';
import { useBodyContext } from 'src/components/ContentWrapper/context';
import { useExperienceEditor } from 'src/lib/useExperienceEditor';
import useMediaQuery from 'src/lib/useMediaQuery';
import usePreventBodyScroll from 'src/lib/usePreventBodyScroll';
import { ModalComponentTypes, ModalTypes } from './types';
import { useFocusTrap } from 'src/lib/useFocusTrap';
const Portal = ({ children }: PropsWithChildren<{}>) => {
if (typeof window === 'undefined') return null;
// Create the root element that content is rendered into
// Used for "Portal" or other functionality that querySelectors for the '#root'
let portalRoot = document.getElementById('root');
if (!portalRoot) {
portalRoot = document.createElement('div');
portalRoot.setAttribute('id', 'root');
portalRoot = document.body.appendChild(portalRoot);
}
return createPortal(children, portalRoot);
};
const Modal = ({ id, rendering }: ModalTypes) => {
const { dispatch, state } = useBodyContext();
const { activeId, isOpen } = state.modal;
const { isEEActive } = useExperienceEditor();
const shouldDisplayModal = activeId === id && isOpen;
return isEEActive ? (
<div className="border">
The Modal Container
<Placeholder name="jss-public-modal-container" rendering={rendering} />
</div>
) : (
<ModalComponent
isActive={shouldDisplayModal}
onCloseHandler={() => dispatch({ type: 'modalClose' })}
{...{ id }}
>
<Placeholder name="jss-public-modal-container" rendering={rendering} />
</ModalComponent>
);
};
const ModalComponent = ({
children,
controls,
isActive,
onCloseHandler = () => {},
}: React.PropsWithChildren<ModalComponentTypes>) => {
const modalBackgroundRef = useRef<HTMLDivElement>(null);
const modalContainerRef = useRef<HTMLDivElement>(null);
const isMobile = !useMediaQuery('md');
// when the modal is active, do not allow the body to scroll
usePreventBodyScroll(isActive);
// classes for the modal 'background' div
const activeClass = isActive ? 'bg-black bg-opacity-80 pointer-events-auto z-modal' : '';
// classes for the modal 'container' div
const containerBackgroundClass = controls?.isTransparent ? '' : 'border border-gray bg-white';
const containerScrollClass = controls?.preventScroll ? '' : 'overflow-auto';
const containerClass = `${containerBackgroundClass} ${containerScrollClass}`;
// closes the modal when clicking outside of the modal
const handleClose = (event: React.MouseEvent<HTMLDivElement>) => {
if (
event &&
event.target &&
event.target instanceof Element &&
event.target.contains(modalBackgroundRef.current) &&
isActive
) {
onCloseHandler();
}
};
useFocusTrap({
shouldTrap: isActive,
container: modalBackgroundRef.current,
onExit: () => onCloseHandler(),
onEnter: ([first]) => first?.focus(),
});
return (
<Portal>
<div
className={`js-modal fixed h-screen w-full top-0 left-0 flex flex-col items-center p-12 pointer-events-none ${activeClass}`}
ref={modalBackgroundRef}
{...a11yAction(handleClose)}
role="dialog"
aria-hidden={!isActive}
tabIndex={-1}
>
<Transition.RevealDown
active={isActive}
className={`relative px-24 pt-32 pb-24 m-auto w-full max-w-3xl ${containerClass}`}
>
<div ref={modalContainerRef}>
<button
aria-label="close"
className="visible absolute right-0 top-0 mr-24 md:mt-16 mt-0 z-overlay"
onClick={onCloseHandler}
>
<SvgLoader
aria-hidden={true}
focusable={false}
color={controls?.isTransparent ? 'text-white' : 'text-teal-dark'}
name="X"
size={isMobile ? 20 : 24}
/>
</button>
{children}
</div>
</Transition.RevealDown>
</div>
</Portal>
);
};
export { Modal as default, ModalComponent };
https://electron.duke-energy.com/components/hero/electron.duke-energy.comchevron-right
https://jiraprod.duke-energy.com/browse/DNT-2930jiraprod.duke-energy.comchevron-right