Skip to content

Commit

Permalink
Merge pull request #88 from fourkitchens/develop
Browse files Browse the repository at this point in the history
Release - 05/27/2024 -1
  • Loading branch information
mcortes19 authored May 27, 2024
2 parents 68276ef + 3cb02ee commit 9147cad
Show file tree
Hide file tree
Showing 6 changed files with 328 additions and 0 deletions.
58 changes: 58 additions & 0 deletions docs/api/ctaBanner.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# CTA Banner Component API

The CTA (Call to Action) Banner component is designed to create prominent and customizable calls to action. Below is the documentation for the CTA Banner component.

## Import

```javascript
import { CtaBanner } from 'forcepoint-shared-components';
```

## Props

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| eyebrow | `string` | `-` | The eyebrow text of the call to action. |
| title | `string` | `-` | The main text of the call to action. |
| theme | `azure` \| `black` \| `navy` \| `white` | `-` | Additional theme for the CTA component. |
| renderedTitleComponent | `ReactNode` | - | Renders the title using and external component. |
| primaryButton | `CtaButtonDetails` | `-` | Details of the primary button associated with the call to action. See the `CtaButtonDetails` type for details. |
| buttonComponent | `ElementType` | `a` | Specifies the root node's element type for the primary button. It accepts a string for a standard HTML element or a custom component. Defaults to a (link). |
| image | `CtaImageDetails` | `-` | Details of the image to be displayed within the call to action. See the `CtaImageDetails` type for details. |
| renderedImageComponent | `ReactNode` | - | Renders the image using and external component. |
| backgroundImage | `CtaImageDetails` | `-` | Details of the background image to be displayed within the call to action. See the `CtaImageDetails` type for details. |
| imageComponent | `ElementType` | `img` | Specifies the root node's element type for the image. It accepts a string for a standard HTML element or a custom component. Defaults to `img`. |


### CtaButtonDetails

| Name | Type | Description |
| --- | --- | --- |
| title | `string` | Required. The title of the link. |
| url | `string` | Required. The URL the link directs to. |

### CtaImageDetails

| Name | Type | Description |
| --- | --- | --- |
| src | `string` | Required. The source URL of the image. |
| alt | `string` | Required. Alternative text for the image. |
| height | `string\|number` | Optional. The height of the image. If provided, it sets the `height` attribute on the image tag. |
| width | `string\|number` | Optional. The width of the image. If provided, it sets the `width` attribute on the image tag. |

### Usage

```javascript
import { CtaBanner } from 'forcepoint-shared-components';

<CtaBanner
eyebrow={bannerEyebrow}
renderedTitleComponent={renderedContent}
primaryButton={buttonDetails}
buttonComponent={Link}
image={imageDetails}
imageComponent={Image}
backgroundImage={backgroundImageDetails}
theme={ctaBannerStyle as CtaBannerTheme}
/>
```
23 changes: 23 additions & 0 deletions src/lib/components/02-components/cta-banner/cta-banner.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { Meta, StoryObj } from '@storybook/react';
import CtaBanner from './cta-banner';

const meta = {
title: 'Components/CTA Banner',
component: CtaBanner,
} satisfies Meta<typeof CtaBanner>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
args: {
title:
'Find it hard to keep pace with modern network demands? Read the Four Steps to Future-Ready Network Security.',
eyebrow: 'Independent Report',
primaryButton: {
title: 'Read Now',
url: '#',
},
theme: 'azure',
},
};
158 changes: 158 additions & 0 deletions src/lib/components/02-components/cta-banner/cta-banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import {
CSSProperties,
ComponentPropsWithoutRef,
ElementType,
ReactNode,
} from 'react';
import { cn } from '../../../utils/tailwind-merge';
import Button, { ButtonColorVariant } from '../../01-elements/button/button';
import Typography from '../../01-elements/typography/typography';

export interface CtaBannerProps extends ComponentPropsWithoutRef<'div'> {
eyebrow?: string;
title?: string;
renderedTitleComponent?: ReactNode;
primaryButton?: CtaButtonDetails;
buttonComponent?: ElementType;
image?: CtaBannerImageDetails;
renderedImageComponent?: ReactNode;
backgroundImage?: CtaBannerImageDetails;
imageComponent?: ElementType;
theme: CtaBannerTheme;
}

export type CtaButtonDetails = {
title: string;
url: string;
};

export type CtaBannerImageDetails = {
alt: string;
height?: string | number;
src: string;
width?: string | number;
};

export type CtaBannerTheme = 'azure' | 'black' | 'violette' | 'navy';

type CtaBannerColorSchema = {
button: ButtonColorVariant;
eyebrow: string;
title: string;
wrapper: string;
};

const colorSchema: { [key in CtaBannerTheme]: CtaBannerColorSchema } = {
azure: {
button: 'blue',
eyebrow: 'text-violette',
title: 'text-navy',
wrapper: 'bg-azure',
},
black: {
button: 'sandwisp',
eyebrow: 'text-sandwisp',
title: 'text-white',
wrapper: 'bg-black',
},
violette: {
button: 'sandwisp',
eyebrow: 'text-sandwisp',
title: 'text-white',
wrapper: 'bg-violette',
},
navy: {
button: 'white',
eyebrow: 'text-sandwisp',
title: 'text-white',
wrapper: 'bg-navy',
},
};

export default function CtaBanner({
eyebrow,
title,
renderedTitleComponent,
primaryButton,
buttonComponent: ButtonElement = 'a',
image,
renderedImageComponent,
backgroundImage,
imageComponent: ImageElement = 'img',
theme,
className,
}: CtaBannerProps) {
const renderedTitle = renderedTitleComponent ? (
renderedTitleComponent
) : title ? (
<Typography className={colorSchema[theme].title} variant="h3">
{title}
</Typography>
) : null;

const renderedPrimaryButton = primaryButton && (
<Button
animated
as="link"
href={primaryButton.url}
component={ButtonElement}
color={colorSchema[theme].button}
className="mt-md w-full justify-center px-14 py-4 text-h4 md:ml-10 md:mt-0 md:min-w-[230px] lg:w-60">
{primaryButton.title}
</Button>
);

const renderedImage = renderedImageComponent ? (
renderedImageComponent
) : image ? (
<ImageElement
className="mx-auto h-full w-full object-contain"
src={image.src}
alt={image.alt}
{...(image.width && { width: image.width })}
{...(image.height && { height: image.height })}
/>
) : null;

const bgImageStyles: CSSProperties = {};
if (backgroundImage) {
bgImageStyles.backgroundImage = `url(${backgroundImage.src})`;
}

return (
<div
style={bgImageStyles}
className={cn(
'bg-cover bg-center p-10',
colorSchema[theme].wrapper,
className,
)}>
<div
className={cn('flex w-full flex-col md:flex-row', {
'max-w-screen-lg md:mx-auto md:my-0 md:justify-center':
renderedImage === null,
})}>
{renderedImage && (
<div className="relative mb-5 aspect-[16/9] w-auto md:mb-0 md:mr-10 md:aspect-[1/1] md:w-[350px]">
{renderedImage}
</div>
)}
<div className="flex flex-col md:flex-row md:items-center">
<div className="max-w-screen-sm">
{eyebrow && (
<span
className={cn(
'mb-3 block text-h5 font-semibold uppercase',
colorSchema[theme].eyebrow,
)}>
{eyebrow}
</span>
)}
{renderedTitle}
</div>
{renderedPrimaryButton}
</div>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { Meta, StoryObj } from '@storybook/react';
import SocialShare from './social-share';

const meta = {
title: 'Components/Social Share',
component: SocialShare,
} satisfies Meta<typeof SocialShare>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
args: {
url: 'https://www.example.com',
title: 'Example Title',
shareText: 'Share on',
ariaNavLabel: 'Social media sharing',
},
};
63 changes: 63 additions & 0 deletions src/lib/components/02-components/social-share/social-share.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { cn } from '../../../utils/tailwind-merge';
import { FacebookIcon, LinkedinIcon, TwitterIcon } from '../../00-tokens/icons';

export type SocialShareProps = {
url: string;
title: string;
shareText?: string;
className?: string;
ariaNavLabel?: string;
};

function genericSocialShare(url: string, socialNetwork: string) {
window.open(url, socialNetwork, 'toolbar=0,status=0,width=648,height=420');
}

export default function SocialShare({
url,
title,
className,
shareText = 'Share on',
ariaNavLabel = 'Social media sharing',
}: SocialShareProps) {
const socialButtons = [
{
platform: 'LinkedIn',
shareUrl: `https://www.linkedin.com/shareArticle?mini=true&url=${encodeURIComponent(url)}&title=${encodeURIComponent(title)}`,
icon: <LinkedinIcon className="h-[20px] w-[20px] text-grey" />,
ariaLabel: `${shareText} LinkedIn`,
},
{
platform: 'Twitter',
shareUrl: `http://twitter.com/share?text=${title}&url=${encodeURIComponent(url)}`,
icon: <TwitterIcon className="h-[20px] w-[20px] text-grey" />,
ariaLabel: `${shareText} Twitter`,
},
{
platform: 'Facebook',
shareUrl: `http://www.facebook.com/sharer.php?u=${encodeURIComponent(url)}`,
icon: <FacebookIcon className="h-[20px] w-[20px] text-grey" />,
ariaLabel: `${shareText} Facebook`,
},
];

return (
<nav aria-label={ariaNavLabel} className={className}>
<ul className={cn('flex gap-sm md:flex-col')}>
{socialButtons.map(({ platform, shareUrl, icon, ariaLabel }) => (
<li key={platform}>
<button
title={ariaLabel}
aria-label={ariaLabel}
onClick={() => genericSocialShare(shareUrl, ariaLabel)}
className={cn(
'flex h-[40px] w-[40px] items-center justify-center rounded-[10px] bg-azure hover:bg-mercury',
)}>
{icon}
</button>
</li>
))}
</ul>
</nav>
);
}
7 changes: 7 additions & 0 deletions src/lib/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,10 @@ export {
type TableRowProps,
} from './02-components/table/table-row';
export { default as Table } from './02-components/table/table-wrapper';
export {
default as CtaBanner,
type CtaBannerProps,
type CtaBannerTheme,
type CtaButtonDetails,
type CtaBannerImageDetails,
} from './02-components/cta-banner/cta-banner';

0 comments on commit 9147cad

Please sign in to comment.