diff --git a/packages/shared/assets/img/named/index.d.ts b/packages/shared/assets/img/named/index.d.ts index 4eed822d6f..01b245825c 100644 --- a/packages/shared/assets/img/named/index.d.ts +++ b/packages/shared/assets/img/named/index.d.ts @@ -21,4 +21,5 @@ export namespace imageName { let poly1: string; let requestFormInformation: string; let ws2DefaultImagev01Final: string; + let moreGradsMoreInnovation: string; } diff --git a/packages/shared/assets/img/named/index.js b/packages/shared/assets/img/named/index.js index 774e78776f..7c827a071f 100644 --- a/packages/shared/assets/img/named/index.js +++ b/packages/shared/assets/img/named/index.js @@ -20,6 +20,7 @@ import * as intro01 from "./intro01.jpg"; import * as poly1 from "./poly01.jpg"; import * as requestFormInformation from "./request-form-information.jpeg"; import * as ws2DefaultImagev01Final from "./WS2-DefaultImagev01-Final.png"; +import * as moreGradsMoreInnovation from "./more-grads-more-innovation.png" export const imageName = { anon: anon.default, @@ -44,4 +45,5 @@ export const imageName = { poly1: poly1.default, requestFormInformation: requestFormInformation.default, ws2DefaultImagev01Final: ws2DefaultImagev01Final.default, + moreGradsMoreInnovation: moreGradsMoreInnovation.default, }; diff --git a/packages/shared/assets/img/named/more-grads-more-innovation.png b/packages/shared/assets/img/named/more-grads-more-innovation.png new file mode 100644 index 0000000000..88547b6f0f Binary files /dev/null and b/packages/shared/assets/img/named/more-grads-more-innovation.png differ diff --git a/packages/unity-bootstrap-theme/src/scss/extends/_cards.scss b/packages/unity-bootstrap-theme/src/scss/extends/_cards.scss index 8996f98688..398f345201 100644 --- a/packages/unity-bootstrap-theme/src/scss/extends/_cards.scss +++ b/packages/unity-bootstrap-theme/src/scss/extends/_cards.scss @@ -775,3 +775,115 @@ Cards - Table of Contents flex-direction: column; justify-content: center; } + +/*------------------------------------------------------------------ +12. Content Spotlight +--------------------------------------------------------------------*/ + +.content-spotlight { + position: relative; + background-color: #000; + overflow: hidden; + width: 100%; + display: flex; + flex-direction: column; + justify-content: center; + padding: 20rem $uds-size-spacing-4 $uds-size-spacing-6 $uds-size-spacing-4; + min-height: 600px; + + @include media-breakpoint-up(lg) { + padding: $uds-size-spacing-12 $uds-size-spacing-6; + min-height: auto; + } +} + +.content-spotlight-image-container { + position: absolute; + inset: 0; + pointer-events: none; +} + +.content-spotlight-image-wrapper { + position: relative; + width: 100%; + height: 100%; + left: 0; +} + +.content-spotlight-image { + width: 85%; + height: 100%; + object-fit: cover; + position: absolute; + top: 0; + left: 15%; + + @include media-breakpoint-down(lg) { + height: 55%; + width: 100%; + left: 0; + top: 0; + object-position: center; + } +} + +.content-spotlight-overlay { + position: absolute; + inset: 0; + background-image: linear-gradient(180deg, rgba(25,25,25,0) 0%, rgba(25,25,25,0) 25%, rgba(25,25,25,1) 45%); + z-index: 1; + + @include media-breakpoint-up(lg) { + background-image: linear-gradient(86.74deg, #000000 25%, rgba(0, 0, 0, 0) 55.34%); + } +} + +.content-spotlight-content { + position: relative; + z-index: 2; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 1rem; + width: 100%; + margin-top: auto; + + @include media-breakpoint-up(lg) { + gap: .75rem; + } + + & > *:last-child { + margin-top: 0.75rem; + } + + @include media-breakpoint-up(lg) { + max-width: 50%; + margin-top: 0; + } +} + +.content-spotlight-icon { + color: $uds-color-base-gold; + font-size: 25px; +} + +.content-spotlight-title { + color: $uds-color-base-white; + margin: 0; + + .highlight { + color: $uds-color-base-gold; + } +} + +.content-spotlight-description { + font-family: $uds-font-family-base; + font-size: $uds-size-font-large; + color: $uds-color-base-white; + margin: 0; + max-width: 100%; + + @include media-breakpoint-up(lg) { + max-width: 420px; + } +} diff --git a/packages/unity-react-core/src/components/ContentSpotlight/ContentSpotlight.jsx b/packages/unity-react-core/src/components/ContentSpotlight/ContentSpotlight.jsx new file mode 100644 index 0000000000..6b02ea5ae3 --- /dev/null +++ b/packages/unity-react-core/src/components/ContentSpotlight/ContentSpotlight.jsx @@ -0,0 +1,105 @@ +// @ts-check +import PropTypes from "prop-types"; +import React from "react"; +import { sanitizeDangerousMarkup } from "@asu/shared"; + +/** + * @typedef {Object} ContentSpotlightProps + * @property {string} backgroundImage - URL of the background image + * @property {string|string[]} [icon] - FontAwesome icon name (e.g. 'graduation-cap') or array ['fab', 'icon-name'] + * @property {string|React.ReactNode} title - Main title + * @property {string} [highlightText] - Text to highlight in gold within the title. + * @property {string} [description] - Body text + * @property {Object} [button] - Button config + * @property {string} button.label - Button text + * @property {string} button.href - Button URL + * @property {string} button.color - Button color + */ + +/** + * @param {ContentSpotlightProps} props + * @returns {JSX.Element} + */ +export const ContentSpotlight = ({ + backgroundImage, + icon, + title, + highlightText, + description, + button, +}) => { + // Icon rendering helper + const renderIcon = () => { + if (!icon) return null; + let iconClasses = ""; + if (Array.isArray(icon)) { + iconClasses = icon.join(" "); + } else { + iconClasses = icon.includes(" ") ? icon : `fas fa-${icon}`; + } + + return ; + }; + + return ( +