@windstream/react-shared-components 0.0.22 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/contentful/index.d.ts +13 -4
- package/dist/contentful/index.esm.js +1 -1
- package/dist/contentful/index.esm.js.map +1 -1
- package/dist/contentful/index.js +1 -1
- package/dist/contentful/index.js.map +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/components/alert-card/types.ts +9 -9
- package/src/components/button/types.ts +14 -14
- package/src/components/link/types.ts +25 -25
- package/src/components/list/index.tsx +88 -88
- package/src/components/list/list-item/index.tsx +38 -38
- package/src/components/list/list-item/types.ts +13 -13
- package/src/components/list/types.ts +29 -29
- package/src/components/material-icon/index.tsx +44 -44
- package/src/components/material-icon/types.ts +31 -31
- package/src/components/skeleton/index.tsx +61 -61
- package/src/components/text/types.ts +45 -45
- package/src/contentful/blocks/floating-banner/FloatingBanner.stories.tsx +34 -23
- package/src/contentful/blocks/floating-banner/index.tsx +99 -11
- package/src/contentful/blocks/floating-banner/types.ts +22 -1
- package/src/setupTests.ts +46 -46
- package/src/types/global.d.ts +9 -9
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import { CSSProperties, HTMLAttributes, ReactNode } from "react";
|
|
2
|
-
|
|
3
|
-
export type ListType = "ul" | "ol";
|
|
4
|
-
export type ListVariant = "default" | "unstyled";
|
|
5
|
-
|
|
6
|
-
export type ListItem = {
|
|
7
|
-
id: string | number;
|
|
8
|
-
content: ReactNode;
|
|
9
|
-
className?: string;
|
|
10
|
-
[key: string]: any;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export interface ListProps
|
|
14
|
-
extends Omit<HTMLAttributes<HTMLUListElement | HTMLOListElement>, "type"> {
|
|
15
|
-
/** List type - unordered (ul) or ordered (ol) */
|
|
16
|
-
type?: ListType;
|
|
17
|
-
/** Array of items to render */
|
|
18
|
-
items?: ListItem[];
|
|
19
|
-
/** Custom className for the list */
|
|
20
|
-
className?: string;
|
|
21
|
-
/** Custom item renderer function */
|
|
22
|
-
renderItem?: (item: ListItem, index: number) => ReactNode;
|
|
23
|
-
/** Children to render instead of items */
|
|
24
|
-
children?: ReactNode;
|
|
25
|
-
/** Additional styling options */
|
|
26
|
-
variant?: ListVariant;
|
|
27
|
-
/** Custom styles */
|
|
28
|
-
style?: CSSProperties;
|
|
29
|
-
}
|
|
1
|
+
import { CSSProperties, HTMLAttributes, ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
export type ListType = "ul" | "ol";
|
|
4
|
+
export type ListVariant = "default" | "unstyled";
|
|
5
|
+
|
|
6
|
+
export type ListItem = {
|
|
7
|
+
id: string | number;
|
|
8
|
+
content: ReactNode;
|
|
9
|
+
className?: string;
|
|
10
|
+
[key: string]: any;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export interface ListProps
|
|
14
|
+
extends Omit<HTMLAttributes<HTMLUListElement | HTMLOListElement>, "type"> {
|
|
15
|
+
/** List type - unordered (ul) or ordered (ol) */
|
|
16
|
+
type?: ListType;
|
|
17
|
+
/** Array of items to render */
|
|
18
|
+
items?: ListItem[];
|
|
19
|
+
/** Custom className for the list */
|
|
20
|
+
className?: string;
|
|
21
|
+
/** Custom item renderer function */
|
|
22
|
+
renderItem?: (item: ListItem, index: number) => ReactNode;
|
|
23
|
+
/** Children to render instead of items */
|
|
24
|
+
children?: ReactNode;
|
|
25
|
+
/** Additional styling options */
|
|
26
|
+
variant?: ListVariant;
|
|
27
|
+
/** Custom styles */
|
|
28
|
+
style?: CSSProperties;
|
|
29
|
+
}
|
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { cx } from "../../utils";
|
|
3
|
-
import type { IconProps } from "./types";
|
|
4
|
-
|
|
5
|
-
const MaterialIcon: React.FC<IconProps> = ({
|
|
6
|
-
name,
|
|
7
|
-
fill = 0,
|
|
8
|
-
opticalSize = "48dp",
|
|
9
|
-
weight = "200",
|
|
10
|
-
emphasis = 145,
|
|
11
|
-
size = 24,
|
|
12
|
-
color = "currentColor",
|
|
13
|
-
style = {},
|
|
14
|
-
className,
|
|
15
|
-
onClick,
|
|
16
|
-
dataTestId,
|
|
17
|
-
}) => {
|
|
18
|
-
const fontVariationSettings = `'FILL' ${fill}, 'wght' ${weight}, 'GRAD' ${emphasis}, 'opsz' ${opticalSize.substring(0, 2)}`;
|
|
19
|
-
|
|
20
|
-
const combinedStyle: React.CSSProperties = {
|
|
21
|
-
fontVariationSettings,
|
|
22
|
-
fontSize: `${size}px`,
|
|
23
|
-
fontFamily: "'Material Symbols Rounded'",
|
|
24
|
-
color: color || "currentColor",
|
|
25
|
-
...style,
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<span
|
|
30
|
-
style={combinedStyle}
|
|
31
|
-
className={cx("material-symbols-rounded", className)}
|
|
32
|
-
onClick={onClick}
|
|
33
|
-
data-testid={dataTestId}
|
|
34
|
-
>
|
|
35
|
-
{name}
|
|
36
|
-
</span>
|
|
37
|
-
);
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export { MaterialIcon };
|
|
41
|
-
|
|
42
|
-
MaterialIcon.displayName = "MaterialIcon";
|
|
43
|
-
|
|
44
|
-
export type { IconProps, IconName } from "./types";
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { cx } from "../../utils";
|
|
3
|
+
import type { IconProps } from "./types";
|
|
4
|
+
|
|
5
|
+
const MaterialIcon: React.FC<IconProps> = ({
|
|
6
|
+
name,
|
|
7
|
+
fill = 0,
|
|
8
|
+
opticalSize = "48dp",
|
|
9
|
+
weight = "200",
|
|
10
|
+
emphasis = 145,
|
|
11
|
+
size = 24,
|
|
12
|
+
color = "currentColor",
|
|
13
|
+
style = {},
|
|
14
|
+
className,
|
|
15
|
+
onClick,
|
|
16
|
+
dataTestId,
|
|
17
|
+
}) => {
|
|
18
|
+
const fontVariationSettings = `'FILL' ${fill}, 'wght' ${weight}, 'GRAD' ${emphasis}, 'opsz' ${opticalSize.substring(0, 2)}`;
|
|
19
|
+
|
|
20
|
+
const combinedStyle: React.CSSProperties = {
|
|
21
|
+
fontVariationSettings,
|
|
22
|
+
fontSize: `${size}px`,
|
|
23
|
+
fontFamily: "'Material Symbols Rounded'",
|
|
24
|
+
color: color || "currentColor",
|
|
25
|
+
...style,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<span
|
|
30
|
+
style={combinedStyle}
|
|
31
|
+
className={cx("material-symbols-rounded", className)}
|
|
32
|
+
onClick={onClick}
|
|
33
|
+
data-testid={dataTestId}
|
|
34
|
+
>
|
|
35
|
+
{name}
|
|
36
|
+
</span>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export { MaterialIcon };
|
|
41
|
+
|
|
42
|
+
MaterialIcon.displayName = "MaterialIcon";
|
|
43
|
+
|
|
44
|
+
export type { IconProps, IconName } from "./types";
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import type { CSSProperties } from "react";
|
|
2
|
-
import {
|
|
3
|
-
emphasis,
|
|
4
|
-
iconNameList,
|
|
5
|
-
OpticalSizes,
|
|
6
|
-
sizes,
|
|
7
|
-
weights,
|
|
8
|
-
} from "./constants";
|
|
9
|
-
|
|
10
|
-
export type Fill = 1 | 0;
|
|
11
|
-
|
|
12
|
-
export type IconName = (typeof iconNameList)[number];
|
|
13
|
-
|
|
14
|
-
export type OpticalSize = (typeof OpticalSizes)[number];
|
|
15
|
-
export type Weight = (typeof weights)[number];
|
|
16
|
-
export type Emphasis = (typeof emphasis)[number];
|
|
17
|
-
export type Size = (typeof sizes)[number];
|
|
18
|
-
|
|
19
|
-
export type IconProps = {
|
|
20
|
-
name: IconName;
|
|
21
|
-
fill?: Fill;
|
|
22
|
-
opticalSize?: OpticalSize;
|
|
23
|
-
weight?: Weight;
|
|
24
|
-
emphasis?: Emphasis;
|
|
25
|
-
size?: Size;
|
|
26
|
-
color?: string;
|
|
27
|
-
style?: CSSProperties;
|
|
28
|
-
className?: string;
|
|
29
|
-
onClick?: () => void;
|
|
30
|
-
dataTestId?: string;
|
|
31
|
-
};
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
2
|
+
import {
|
|
3
|
+
emphasis,
|
|
4
|
+
iconNameList,
|
|
5
|
+
OpticalSizes,
|
|
6
|
+
sizes,
|
|
7
|
+
weights,
|
|
8
|
+
} from "./constants";
|
|
9
|
+
|
|
10
|
+
export type Fill = 1 | 0;
|
|
11
|
+
|
|
12
|
+
export type IconName = (typeof iconNameList)[number];
|
|
13
|
+
|
|
14
|
+
export type OpticalSize = (typeof OpticalSizes)[number];
|
|
15
|
+
export type Weight = (typeof weights)[number];
|
|
16
|
+
export type Emphasis = (typeof emphasis)[number];
|
|
17
|
+
export type Size = (typeof sizes)[number];
|
|
18
|
+
|
|
19
|
+
export type IconProps = {
|
|
20
|
+
name: IconName;
|
|
21
|
+
fill?: Fill;
|
|
22
|
+
opticalSize?: OpticalSize;
|
|
23
|
+
weight?: Weight;
|
|
24
|
+
emphasis?: Emphasis;
|
|
25
|
+
size?: Size;
|
|
26
|
+
color?: string;
|
|
27
|
+
style?: CSSProperties;
|
|
28
|
+
className?: string;
|
|
29
|
+
onClick?: () => void;
|
|
30
|
+
dataTestId?: string;
|
|
31
|
+
};
|
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
import { FC } from "react";
|
|
2
|
-
import { SkeletonProps } from "./types";
|
|
3
|
-
|
|
4
|
-
export const Skeleton: FC<SkeletonProps> = ({ className = "", count = 1 }) => {
|
|
5
|
-
return (
|
|
6
|
-
<div className="animate-pulse space-y-4">
|
|
7
|
-
{Array.from({ length: count }).map((_, index) => (
|
|
8
|
-
<div
|
|
9
|
-
key={index}
|
|
10
|
-
className={`h-8 rounded bg-skeleton-bg-start ${className}`}
|
|
11
|
-
style={{ opacity: 1 - index * 0.1 }}
|
|
12
|
-
/>
|
|
13
|
-
))}
|
|
14
|
-
</div>
|
|
15
|
-
);
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
Skeleton.displayName = "Skeleton";
|
|
19
|
-
|
|
20
|
-
export type { SkeletonProps };
|
|
21
|
-
|
|
22
|
-
export const PageSkeleton: FC = () => {
|
|
23
|
-
return (
|
|
24
|
-
<div
|
|
25
|
-
className="item-center mx-auto mt-4 flex animate-pulse flex-col justify-center gap-10 px-1 md:max-w-[48.375rem] md:gap-16 md:px-0"
|
|
26
|
-
data-testid="generic-skeleton"
|
|
27
|
-
>
|
|
28
|
-
{/* Title */}
|
|
29
|
-
<div
|
|
30
|
-
className="h-12 w-full rounded-lg bg-skeleton-bg-start"
|
|
31
|
-
data-testid="title"
|
|
32
|
-
/>
|
|
33
|
-
|
|
34
|
-
{/* Subtitle */}
|
|
35
|
-
<div className="item-center flex flex-col gap-6" data-testid="subtitle">
|
|
36
|
-
<div className="h-5 w-full rounded-lg bg-skeleton-bg-start" />
|
|
37
|
-
<div className="h-5 w-full rounded-lg bg-skeleton-bg-start" />
|
|
38
|
-
</div>
|
|
39
|
-
|
|
40
|
-
{/* Content */}
|
|
41
|
-
<div className="item-center flex flex-col gap-3" data-testid="content">
|
|
42
|
-
<div className="h-12 w-full rounded-lg bg-skeleton-bg-start" />
|
|
43
|
-
<div className="h-12 w-full rounded-lg bg-skeleton-bg-start" />
|
|
44
|
-
</div>
|
|
45
|
-
|
|
46
|
-
{/* Additional Information */}
|
|
47
|
-
<div
|
|
48
|
-
className="item-center flex flex-col gap-6"
|
|
49
|
-
data-testid="additional-info"
|
|
50
|
-
>
|
|
51
|
-
<div className="h-5 w-full rounded-lg bg-skeleton-bg-end" />
|
|
52
|
-
<div className="h-5 w-full rounded-lg bg-skeleton-bg-end" />
|
|
53
|
-
</div>
|
|
54
|
-
|
|
55
|
-
{/* CTA button */}
|
|
56
|
-
<div className="item-center flex justify-center" data-testid="cta-button">
|
|
57
|
-
<div className="h-12 w-full rounded-lg bg-skeleton-bg-end md:w-[22.125rem]" />
|
|
58
|
-
</div>
|
|
59
|
-
</div>
|
|
60
|
-
);
|
|
61
|
-
};
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import { SkeletonProps } from "./types";
|
|
3
|
+
|
|
4
|
+
export const Skeleton: FC<SkeletonProps> = ({ className = "", count = 1 }) => {
|
|
5
|
+
return (
|
|
6
|
+
<div className="animate-pulse space-y-4">
|
|
7
|
+
{Array.from({ length: count }).map((_, index) => (
|
|
8
|
+
<div
|
|
9
|
+
key={index}
|
|
10
|
+
className={`h-8 rounded bg-skeleton-bg-start ${className}`}
|
|
11
|
+
style={{ opacity: 1 - index * 0.1 }}
|
|
12
|
+
/>
|
|
13
|
+
))}
|
|
14
|
+
</div>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
Skeleton.displayName = "Skeleton";
|
|
19
|
+
|
|
20
|
+
export type { SkeletonProps };
|
|
21
|
+
|
|
22
|
+
export const PageSkeleton: FC = () => {
|
|
23
|
+
return (
|
|
24
|
+
<div
|
|
25
|
+
className="item-center mx-auto mt-4 flex animate-pulse flex-col justify-center gap-10 px-1 md:max-w-[48.375rem] md:gap-16 md:px-0"
|
|
26
|
+
data-testid="generic-skeleton"
|
|
27
|
+
>
|
|
28
|
+
{/* Title */}
|
|
29
|
+
<div
|
|
30
|
+
className="h-12 w-full rounded-lg bg-skeleton-bg-start"
|
|
31
|
+
data-testid="title"
|
|
32
|
+
/>
|
|
33
|
+
|
|
34
|
+
{/* Subtitle */}
|
|
35
|
+
<div className="item-center flex flex-col gap-6" data-testid="subtitle">
|
|
36
|
+
<div className="h-5 w-full rounded-lg bg-skeleton-bg-start" />
|
|
37
|
+
<div className="h-5 w-full rounded-lg bg-skeleton-bg-start" />
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
{/* Content */}
|
|
41
|
+
<div className="item-center flex flex-col gap-3" data-testid="content">
|
|
42
|
+
<div className="h-12 w-full rounded-lg bg-skeleton-bg-start" />
|
|
43
|
+
<div className="h-12 w-full rounded-lg bg-skeleton-bg-start" />
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
{/* Additional Information */}
|
|
47
|
+
<div
|
|
48
|
+
className="item-center flex flex-col gap-6"
|
|
49
|
+
data-testid="additional-info"
|
|
50
|
+
>
|
|
51
|
+
<div className="h-5 w-full rounded-lg bg-skeleton-bg-end" />
|
|
52
|
+
<div className="h-5 w-full rounded-lg bg-skeleton-bg-end" />
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
{/* CTA button */}
|
|
56
|
+
<div className="item-center flex justify-center" data-testid="cta-button">
|
|
57
|
+
<div className="h-12 w-full rounded-lg bg-skeleton-bg-end md:w-[22.125rem]" />
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
import { type CSSProperties, type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
-
|
|
3
|
-
export type TextVariant =
|
|
4
|
-
| "heading1"
|
|
5
|
-
| "heading2"
|
|
6
|
-
| "heading3"
|
|
7
|
-
| "heading4"
|
|
8
|
-
| "heading5"
|
|
9
|
-
| "heading6"
|
|
10
|
-
| "subheading1"
|
|
11
|
-
| "subheading2"
|
|
12
|
-
| "subheading3"
|
|
13
|
-
| "subheading4"
|
|
14
|
-
| "subheading5"
|
|
15
|
-
| "subheading6"
|
|
16
|
-
| "body1"
|
|
17
|
-
| "body2"
|
|
18
|
-
| "body3"
|
|
19
|
-
| "footnote"
|
|
20
|
-
| "micro"
|
|
21
|
-
| "label1"
|
|
22
|
-
| "label2"
|
|
23
|
-
| "label3"
|
|
24
|
-
| "label4"
|
|
25
|
-
| "error"
|
|
26
|
-
| "unstyled";
|
|
27
|
-
export type TextWeight =
|
|
28
|
-
| "thin"
|
|
29
|
-
| "normal"
|
|
30
|
-
| "medium"
|
|
31
|
-
| "semibold"
|
|
32
|
-
| "bold"
|
|
33
|
-
| "extrabold"
|
|
34
|
-
| "black"
|
|
35
|
-
| undefined;
|
|
36
|
-
export interface TextProps extends HTMLAttributes<HTMLElement> {
|
|
37
|
-
/** Content to render inside the text element */
|
|
38
|
-
children?: ReactNode;
|
|
39
|
-
/** Custom HTML element to render as */
|
|
40
|
-
as?: keyof import("react").JSX.IntrinsicElements;
|
|
41
|
-
/** Custom className for the text */
|
|
42
|
-
className?: string;
|
|
43
|
-
/** Custom styles */
|
|
44
|
-
style?: CSSProperties;
|
|
45
|
-
}
|
|
1
|
+
import { type CSSProperties, type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
export type TextVariant =
|
|
4
|
+
| "heading1"
|
|
5
|
+
| "heading2"
|
|
6
|
+
| "heading3"
|
|
7
|
+
| "heading4"
|
|
8
|
+
| "heading5"
|
|
9
|
+
| "heading6"
|
|
10
|
+
| "subheading1"
|
|
11
|
+
| "subheading2"
|
|
12
|
+
| "subheading3"
|
|
13
|
+
| "subheading4"
|
|
14
|
+
| "subheading5"
|
|
15
|
+
| "subheading6"
|
|
16
|
+
| "body1"
|
|
17
|
+
| "body2"
|
|
18
|
+
| "body3"
|
|
19
|
+
| "footnote"
|
|
20
|
+
| "micro"
|
|
21
|
+
| "label1"
|
|
22
|
+
| "label2"
|
|
23
|
+
| "label3"
|
|
24
|
+
| "label4"
|
|
25
|
+
| "error"
|
|
26
|
+
| "unstyled";
|
|
27
|
+
export type TextWeight =
|
|
28
|
+
| "thin"
|
|
29
|
+
| "normal"
|
|
30
|
+
| "medium"
|
|
31
|
+
| "semibold"
|
|
32
|
+
| "bold"
|
|
33
|
+
| "extrabold"
|
|
34
|
+
| "black"
|
|
35
|
+
| undefined;
|
|
36
|
+
export interface TextProps extends HTMLAttributes<HTMLElement> {
|
|
37
|
+
/** Content to render inside the text element */
|
|
38
|
+
children?: ReactNode;
|
|
39
|
+
/** Custom HTML element to render as */
|
|
40
|
+
as?: keyof import("react").JSX.IntrinsicElements;
|
|
41
|
+
/** Custom className for the text */
|
|
42
|
+
className?: string;
|
|
43
|
+
/** Custom styles */
|
|
44
|
+
style?: CSSProperties;
|
|
45
|
+
}
|
|
@@ -1,23 +1,34 @@
|
|
|
1
|
-
import { FloatingBanner } from "./index";
|
|
2
|
-
|
|
3
|
-
import { DocsPage } from "@shared/stories/DocsTemplate";
|
|
4
|
-
import type { Meta, StoryObj } from "@storybook/react";
|
|
5
|
-
|
|
6
|
-
const meta: Meta<typeof FloatingBanner> = {
|
|
7
|
-
title: "Contentful Blocks/FloatingBanner",
|
|
8
|
-
component: FloatingBanner,
|
|
9
|
-
tags: ["autodocs"],
|
|
10
|
-
parameters: {
|
|
11
|
-
layout: "centered",
|
|
12
|
-
docs: {
|
|
13
|
-
page: DocsPage,
|
|
14
|
-
description: {
|
|
15
|
-
component: "Contentful floating banner block.",
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
args: {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
1
|
+
import { FloatingBanner } from "./index";
|
|
2
|
+
|
|
3
|
+
import { DocsPage } from "@shared/stories/DocsTemplate";
|
|
4
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof FloatingBanner> = {
|
|
7
|
+
title: "Contentful Blocks/FloatingBanner",
|
|
8
|
+
component: FloatingBanner,
|
|
9
|
+
tags: ["autodocs"],
|
|
10
|
+
parameters: {
|
|
11
|
+
layout: "centered",
|
|
12
|
+
docs: {
|
|
13
|
+
page: DocsPage,
|
|
14
|
+
description: {
|
|
15
|
+
component: "Contentful floating banner block.",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
args: {
|
|
20
|
+
title: "test",
|
|
21
|
+
enableHeading: false,
|
|
22
|
+
subtitle: "Test",
|
|
23
|
+
icon: "https://images.ctfassets.net/lefc0joykfg0/xt7XD2oCXK79H8pyMyMb8/18aead59bc97d624b5bd91b2f9f04352/banner_call_icon.svg",
|
|
24
|
+
description: <p>test</p>,
|
|
25
|
+
cta: null,
|
|
26
|
+
disclaimer: <p>test</p>,
|
|
27
|
+
background: "green",
|
|
28
|
+
color: "white",
|
|
29
|
+
maxWidth: true,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
export default meta;
|
|
33
|
+
type Story = StoryObj<typeof meta>;
|
|
34
|
+
export const Default: Story = {};
|
|
@@ -1,11 +1,99 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { FloatingBannerProps, ThemeKey } from "./types";
|
|
3
|
+
|
|
4
|
+
import { NextImage } from "@shared/components/next-image";
|
|
5
|
+
import { Text } from "@shared/components/text";
|
|
6
|
+
import { Button } from "@shared/contentful/blocks/button";
|
|
7
|
+
|
|
8
|
+
export const FloatingBanner: React.FC<FloatingBannerProps> = ({
|
|
9
|
+
title,
|
|
10
|
+
subtitle,
|
|
11
|
+
description,
|
|
12
|
+
disclaimer,
|
|
13
|
+
icon,
|
|
14
|
+
cta,
|
|
15
|
+
background = "navy",
|
|
16
|
+
color = "white",
|
|
17
|
+
enableHeading,
|
|
18
|
+
maxWidth = true,
|
|
19
|
+
}) => {
|
|
20
|
+
const textColorClasses: Record<ThemeKey, string> = {
|
|
21
|
+
blue: "text-[#07B2E2]",
|
|
22
|
+
green: "text-[#26B170]",
|
|
23
|
+
yellow: "text-[#F5FF1E]",
|
|
24
|
+
purple: "text-[#931D69]",
|
|
25
|
+
white: "text-white",
|
|
26
|
+
navy: "text-[#00002D]",
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const bgColorClasses: Record<ThemeKey, string> = {
|
|
30
|
+
blue: "bg-[#07B2E2]",
|
|
31
|
+
green: "bg-[#26B170]",
|
|
32
|
+
yellow: "bg-[#F5FF1E]",
|
|
33
|
+
purple: "bg-[#931D69]",
|
|
34
|
+
white: "bg-white",
|
|
35
|
+
navy: "bg-[#00002D]",
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div className="component-container">
|
|
40
|
+
<div
|
|
41
|
+
className={`mx-5 my-8 lg:mx-20 lg:my-12 lg:rounded-[40px] xl:mx-auto ${maxWidth ? "mx-auto max-w-120" : ""}`}
|
|
42
|
+
>
|
|
43
|
+
<div
|
|
44
|
+
className={`flex flex-col rounded-[28px] px-5 py-7 lg:flex-row lg:rounded-[40px] lg:px-16 lg:py-9 ${bgColorClasses[background]} ${textColorClasses[color]} `}
|
|
45
|
+
>
|
|
46
|
+
{icon && (
|
|
47
|
+
<div className="floating-banner-icon mb-5 flex justify-center lg:mb-0 lg:items-center">
|
|
48
|
+
<div className="h-[80px] w-[80px] overflow-hidden">
|
|
49
|
+
<NextImage
|
|
50
|
+
width={80}
|
|
51
|
+
height={80}
|
|
52
|
+
alt="icon"
|
|
53
|
+
src={icon}
|
|
54
|
+
></NextImage>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
)}
|
|
58
|
+
<div className="flex flex-col justify-center lg:mx-5">
|
|
59
|
+
{title && (
|
|
60
|
+
<Text
|
|
61
|
+
as={enableHeading ? "h1" : "h2"}
|
|
62
|
+
className={`heading2 mb-3 w-[90%] text-center lg:text-left`}
|
|
63
|
+
>
|
|
64
|
+
{title}
|
|
65
|
+
</Text>
|
|
66
|
+
)}
|
|
67
|
+
{subtitle && (
|
|
68
|
+
<Text
|
|
69
|
+
as={"h3"}
|
|
70
|
+
className={`heading3 mb-3 text-center lg:text-left`}
|
|
71
|
+
>
|
|
72
|
+
{subtitle}
|
|
73
|
+
</Text>
|
|
74
|
+
)}
|
|
75
|
+
{description && (
|
|
76
|
+
<Text as="div" className="body1 w-[90%] text-center lg:text-left">
|
|
77
|
+
{description}
|
|
78
|
+
</Text>
|
|
79
|
+
)}
|
|
80
|
+
</div>
|
|
81
|
+
{cta && (
|
|
82
|
+
<div className="mt-5 flex justify-center lg:mt-0 lg:w-[500px] lg:items-center">
|
|
83
|
+
<Button {...cta}></Button>
|
|
84
|
+
</div>
|
|
85
|
+
)}
|
|
86
|
+
</div>
|
|
87
|
+
{disclaimer && (
|
|
88
|
+
<div>
|
|
89
|
+
<Text as="div" className="body3 mt-3 text-center">
|
|
90
|
+
{disclaimer}
|
|
91
|
+
</Text>
|
|
92
|
+
</div>
|
|
93
|
+
)}
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export default FloatingBanner;
|
|
@@ -1 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
export type FloatingBannerProps = {
|
|
4
|
+
title?: string;
|
|
5
|
+
enableHeading?: boolean;
|
|
6
|
+
subtitle?: string;
|
|
7
|
+
icon?: string;
|
|
8
|
+
description?: React.ReactNode;
|
|
9
|
+
cta?: any | null;
|
|
10
|
+
disclaimer?: React.ReactNode;
|
|
11
|
+
background?: "green" | "navy" | "white";
|
|
12
|
+
color?: "navy" | "white";
|
|
13
|
+
maxWidth?: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type ThemeKey =
|
|
17
|
+
| "blue"
|
|
18
|
+
| "green"
|
|
19
|
+
| "yellow"
|
|
20
|
+
| "purple"
|
|
21
|
+
| "white"
|
|
22
|
+
| "navy";
|