@thecb/components 11.2.2-beta.0 → 11.2.3-beta.0
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/index.cjs.js +150 -4
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +150 -5
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/atoms/icons/ExternalLinkIcon.js +1 -1
- package/src/components/molecules/contact-card/ContactCard.js +125 -0
- package/src/components/molecules/contact-card/ContactCard.stories.js +76 -0
- package/src/components/molecules/contact-card/ContactCard.styled.js +47 -0
- package/src/components/molecules/contact-card/index.d.ts +16 -0
- package/src/components/molecules/contact-card/index.js +3 -0
- package/src/components/molecules/index.js +1 -0
- package/src/components/molecules/registration-banner/RegistrationBanner.js +111 -0
- package/src/components/molecules/registration-banner/RegistrationBanner.mdx +22 -0
- package/src/components/molecules/registration-banner/RegistrationBanner.stories.js +90 -0
- package/src/components/molecules/registration-banner/RegistrationBanner.styled.js +43 -0
- package/src/components/molecules/registration-banner/RegistrationBanner.theme.js +11 -0
- package/src/components/molecules/registration-banner/index.d.ts +16 -0
- package/src/components/molecules/registration-banner/index.js +3 -0
- package/src/components/molecules/tab-sidebar/TabSidebar.js +2 -2
- package/src/util/general.js +36 -0
package/package.json
CHANGED
|
@@ -31,7 +31,7 @@ const ExternalLinkIcon = ({ linkColor, text }) => (
|
|
|
31
31
|
/>
|
|
32
32
|
</mask>
|
|
33
33
|
<g mask={`url(#mask0_902_435-${text})`}>
|
|
34
|
-
<rect x="-0.0864258" width="14" height="14" fill=
|
|
34
|
+
<rect x="-0.0864258" width="14" height="14" fill="none" />
|
|
35
35
|
</g>
|
|
36
36
|
</svg>
|
|
37
37
|
);
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import React, { useContext } from "react";
|
|
2
|
+
import { Box, Stack } from "../../atoms/layouts";
|
|
3
|
+
import { ExternalLink } from "../../atoms";
|
|
4
|
+
import { ThemeContext } from "styled-components";
|
|
5
|
+
import * as Styled from "./ContactCard.styled";
|
|
6
|
+
import { createIdFromString } from "../../../util/general";
|
|
7
|
+
import { FONT_SIZE } from "../../../constants/style_constants";
|
|
8
|
+
import ExternalLinkIcon from "../../atoms/icons/ExternalLinkIcon";
|
|
9
|
+
import SolidDivider from "../../atoms/solid-divider";
|
|
10
|
+
import { ROYAL_BLUE_VIVID } from "../../../constants/colors";
|
|
11
|
+
import { createThemeValues } from "../../../util/themeUtils";
|
|
12
|
+
|
|
13
|
+
const ContactCard = ({
|
|
14
|
+
title,
|
|
15
|
+
secondTitle = "Helpful Links",
|
|
16
|
+
content = "",
|
|
17
|
+
links = [],
|
|
18
|
+
extraStyles = "",
|
|
19
|
+
titleVariant = "h3",
|
|
20
|
+
ariaLabel = "Contact Information",
|
|
21
|
+
linkVariant = "primary"
|
|
22
|
+
}) => {
|
|
23
|
+
const themeContext = useContext(ThemeContext);
|
|
24
|
+
const { isMobile } = themeContext;
|
|
25
|
+
const linkFallbackValues = { externalLinkColor: ROYAL_BLUE_VIVID };
|
|
26
|
+
const linkThemeValues = createThemeValues(
|
|
27
|
+
themeContext,
|
|
28
|
+
linkFallbackValues,
|
|
29
|
+
"Link",
|
|
30
|
+
linkVariant
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<Styled.Container
|
|
35
|
+
borderRadius="8px"
|
|
36
|
+
boxShadow="0px 2px 4px rgba(0, 0, 0, 0.25)"
|
|
37
|
+
dataQa={createIdFromString(title, "contact-card")}
|
|
38
|
+
maxWidth={isMobile ? "100%" : "208px"}
|
|
39
|
+
minWidth={isMobile ? "240px" : "208px"}
|
|
40
|
+
minHeight="141px"
|
|
41
|
+
padding="1.5rem"
|
|
42
|
+
extraStyles={extraStyles}
|
|
43
|
+
role="complementary"
|
|
44
|
+
aria-label={ariaLabel}
|
|
45
|
+
>
|
|
46
|
+
<Stack
|
|
47
|
+
childGap="8px"
|
|
48
|
+
bottomItem={3}
|
|
49
|
+
justify="space-between"
|
|
50
|
+
style={{ width: "100%" }}
|
|
51
|
+
fullHeight
|
|
52
|
+
>
|
|
53
|
+
<Box padding={0} width="100%">
|
|
54
|
+
<Styled.Title
|
|
55
|
+
variant={titleVariant}
|
|
56
|
+
margin={0}
|
|
57
|
+
fontSize={FONT_SIZE.MD}
|
|
58
|
+
>
|
|
59
|
+
{title}
|
|
60
|
+
</Styled.Title>
|
|
61
|
+
</Box>
|
|
62
|
+
<Box padding={"0"} width="100%">
|
|
63
|
+
<Styled.Content>{content}</Styled.Content>
|
|
64
|
+
</Box>
|
|
65
|
+
</Stack>
|
|
66
|
+
{links.length > 0 && (
|
|
67
|
+
<>
|
|
68
|
+
<SolidDivider aria-hidden={true} />
|
|
69
|
+
<Stack
|
|
70
|
+
childGap={"8px"}
|
|
71
|
+
bottomItem={3}
|
|
72
|
+
justify="space-between"
|
|
73
|
+
style={{ width: "100%" }}
|
|
74
|
+
fullHeight
|
|
75
|
+
>
|
|
76
|
+
<Styled.Title
|
|
77
|
+
variant={titleVariant}
|
|
78
|
+
margin={0}
|
|
79
|
+
fontSize={FONT_SIZE.MD}
|
|
80
|
+
>
|
|
81
|
+
{secondTitle}
|
|
82
|
+
</Styled.Title>
|
|
83
|
+
<Stack
|
|
84
|
+
childGap={"4px"}
|
|
85
|
+
justify="space-between"
|
|
86
|
+
style={{ width: "100%" }}
|
|
87
|
+
fullHeight
|
|
88
|
+
>
|
|
89
|
+
{links.map(link => {
|
|
90
|
+
const linkID = createIdFromString(
|
|
91
|
+
link.text,
|
|
92
|
+
"contact-card-link"
|
|
93
|
+
);
|
|
94
|
+
return (
|
|
95
|
+
<ExternalLink
|
|
96
|
+
key={linkID}
|
|
97
|
+
dataQa={linkID}
|
|
98
|
+
href={link.link}
|
|
99
|
+
newTab={true}
|
|
100
|
+
extraStyles={`
|
|
101
|
+
flex-direction: row;
|
|
102
|
+
align-items: center;
|
|
103
|
+
align-content: flex-start;
|
|
104
|
+
justify-content: space-between;
|
|
105
|
+
`}
|
|
106
|
+
size={FONT_SIZE.SM}
|
|
107
|
+
lineHeight="1.313rem"
|
|
108
|
+
>
|
|
109
|
+
{link.text}
|
|
110
|
+
<ExternalLinkIcon
|
|
111
|
+
linkColor={linkThemeValues.externalLinkColor}
|
|
112
|
+
text={link.text}
|
|
113
|
+
/>
|
|
114
|
+
</ExternalLink>
|
|
115
|
+
);
|
|
116
|
+
})}
|
|
117
|
+
</Stack>
|
|
118
|
+
</Stack>
|
|
119
|
+
</>
|
|
120
|
+
)}
|
|
121
|
+
</Styled.Container>
|
|
122
|
+
);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export default ContactCard;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import ContactCard from "./ContactCard";
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: "Molecules/ContactCard",
|
|
6
|
+
component: ContactCard,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: "centered"
|
|
9
|
+
},
|
|
10
|
+
tags: ["!autodocs"],
|
|
11
|
+
args: {
|
|
12
|
+
title: "City Hall Payment Center",
|
|
13
|
+
extraStyles: "",
|
|
14
|
+
titleVariant: "h3"
|
|
15
|
+
},
|
|
16
|
+
argTypes: {
|
|
17
|
+
title: {
|
|
18
|
+
description: "Text to display in the ContactCard's heading area",
|
|
19
|
+
table: {
|
|
20
|
+
type: { summary: "string" },
|
|
21
|
+
defaultValue: { summary: "City Hall Payment Center" }
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
content: {
|
|
25
|
+
description: "Text to display in the ContactCard's content area",
|
|
26
|
+
table: {
|
|
27
|
+
type: { summary: "string" },
|
|
28
|
+
defaultValue: { summary: "" }
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
links: {
|
|
32
|
+
description: "Array of links to display in the ContactCard",
|
|
33
|
+
table: {
|
|
34
|
+
type: { summary: "array" },
|
|
35
|
+
defaultValue: { summary: "[]" }
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
extraStyles: {
|
|
39
|
+
description: "Extra styles to apply to the ContactCard",
|
|
40
|
+
table: {
|
|
41
|
+
type: { summary: "string" },
|
|
42
|
+
defaultValue: { summary: undefined }
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
titleVariant: {
|
|
46
|
+
description: "HTML element to use for heading element, default is h3",
|
|
47
|
+
table: {
|
|
48
|
+
type: { summary: "string" },
|
|
49
|
+
defaultValue: { summary: "h3" }
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default meta;
|
|
56
|
+
|
|
57
|
+
export const BasicContactCard = {
|
|
58
|
+
args: {
|
|
59
|
+
title: "City Hall Payment Center",
|
|
60
|
+
content:
|
|
61
|
+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod",
|
|
62
|
+
links: [
|
|
63
|
+
{
|
|
64
|
+
text: "Cityville Home",
|
|
65
|
+
link: "https://cityville-demos.uat.cityba.se/"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
text: "Contact Us",
|
|
69
|
+
link: "https://eunasolutions.com/contact-us/"
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
render: args => {
|
|
74
|
+
return <ContactCard {...args} key="contact-card-basic" extraStyles={``} />;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
import Heading from "../../atoms/heading";
|
|
3
|
+
import Stack from "../../atoms/layouts/Stack";
|
|
4
|
+
import { Box } from "../../atoms/layouts";
|
|
5
|
+
import {
|
|
6
|
+
FONT_SIZE,
|
|
7
|
+
FONT_WEIGHT_SEMIBOLD
|
|
8
|
+
} from "../../../constants/style_constants";
|
|
9
|
+
|
|
10
|
+
export const Container = styled(Box)`
|
|
11
|
+
height: fit-content;
|
|
12
|
+
display: flex;
|
|
13
|
+
padding: 1rem;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
align-items: flex-start;
|
|
16
|
+
gap: 1.5rem;
|
|
17
|
+
border-radius: 8px;
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
export const Title = styled(Heading)`
|
|
21
|
+
display: -webkit-box;
|
|
22
|
+
-webkit-box-orient: vertical;
|
|
23
|
+
-webkit-line-clamp: 2;
|
|
24
|
+
align-self: stretch;
|
|
25
|
+
overflow: hidden;
|
|
26
|
+
text-overflow: ellipsis;
|
|
27
|
+
background-color: transparent;
|
|
28
|
+
font-weight: ${FONT_WEIGHT_SEMIBOLD};
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
export const Content = styled(Box)`
|
|
32
|
+
padding: 0;
|
|
33
|
+
font-size: ${FONT_SIZE.SM};
|
|
34
|
+
line-height: 1.313rem;
|
|
35
|
+
overflow-wrap: normal;
|
|
36
|
+
letter-spacing: 0.14px;
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
export const Footer = styled(Stack)`
|
|
40
|
+
width: 100%;
|
|
41
|
+
`;
|
|
42
|
+
|
|
43
|
+
export const Divider = styled(Box)`
|
|
44
|
+
padding: 0;
|
|
45
|
+
height: 1px;
|
|
46
|
+
width: 100%;
|
|
47
|
+
`;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React, { HTMLAttributes } from "react";
|
|
2
|
+
import Expand from "../../../util/expand";
|
|
3
|
+
|
|
4
|
+
export interface ContactCardProps {
|
|
5
|
+
title?: string; // title 1
|
|
6
|
+
secondTitle?: string; // title 2
|
|
7
|
+
content?: any; // content
|
|
8
|
+
links?: any; // list of links
|
|
9
|
+
extraStyles?: string; // extra styles
|
|
10
|
+
titleVariant?: string; // title variant
|
|
11
|
+
ariaLabel?: string; // aria label
|
|
12
|
+
linkVariant?: string; // link variant
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const ContactCard: React.FC<Expand<ContactCardProps> &
|
|
16
|
+
HTMLAttributes<HTMLElement>>;
|
|
@@ -43,3 +43,4 @@ export { default as WelcomeModule } from "./welcome-module";
|
|
|
43
43
|
export { default as WorkflowTile } from "./workflow-tile";
|
|
44
44
|
export { default as PopupMenu } from "./popup-menu";
|
|
45
45
|
export { default as MultipleSelectFilter } from "./multiple-select-filter";
|
|
46
|
+
export { default as ContactCard } from "./contact-card";
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import React, { useContext } from "react";
|
|
2
|
+
import { themeComponent } from "../../../util/themeUtils";
|
|
3
|
+
import { fallbackValues } from "./RegistrationBanner.theme";
|
|
4
|
+
import * as Styled from "./RegistrationBanner.styled";
|
|
5
|
+
import ArrowRightIcon from "../../atoms/icons/ArrowRightIcon";
|
|
6
|
+
import { Box, Cluster } from "../../atoms/layouts";
|
|
7
|
+
import Text from "../../atoms/text";
|
|
8
|
+
import { ThemeContext } from "styled-components";
|
|
9
|
+
import {
|
|
10
|
+
FONT_SIZE,
|
|
11
|
+
FONT_WEIGHT_SEMIBOLD
|
|
12
|
+
} from "../../../constants/style_constants";
|
|
13
|
+
import withWindowSize from "../../withWindowSize";
|
|
14
|
+
import Heading from "../../atoms/heading";
|
|
15
|
+
|
|
16
|
+
const RegistrationBanner = ({
|
|
17
|
+
description,
|
|
18
|
+
extraStyles,
|
|
19
|
+
loginLink = "/login",
|
|
20
|
+
registrationLink = "/registration",
|
|
21
|
+
themeValues,
|
|
22
|
+
title,
|
|
23
|
+
titleAs,
|
|
24
|
+
titleVariant
|
|
25
|
+
}) => {
|
|
26
|
+
const themeContext = useContext(ThemeContext);
|
|
27
|
+
const { isMobile } = themeContext;
|
|
28
|
+
return (
|
|
29
|
+
<Styled.BannerContainer
|
|
30
|
+
extraStyles={extraStyles}
|
|
31
|
+
themeValues={themeValues}
|
|
32
|
+
isMobile={isMobile}
|
|
33
|
+
role="banner"
|
|
34
|
+
aria-label="Registration Banner"
|
|
35
|
+
>
|
|
36
|
+
<Styled.ContentContainer
|
|
37
|
+
role="main"
|
|
38
|
+
align="center"
|
|
39
|
+
justify="space-between"
|
|
40
|
+
overflow="visible"
|
|
41
|
+
isMobile={isMobile}
|
|
42
|
+
>
|
|
43
|
+
<Box padding="0" textAlign="left">
|
|
44
|
+
<Heading
|
|
45
|
+
as={titleAs}
|
|
46
|
+
color={themeValues.primaryColor}
|
|
47
|
+
fontSize={isMobile ? FONT_SIZE.XL : "1.5rem"}
|
|
48
|
+
variant={titleVariant}
|
|
49
|
+
weight={FONT_WEIGHT_SEMIBOLD}
|
|
50
|
+
>
|
|
51
|
+
{title}
|
|
52
|
+
</Heading>
|
|
53
|
+
<Text
|
|
54
|
+
extraStyles={`
|
|
55
|
+
display: block;
|
|
56
|
+
padding: ${isMobile ? ".125rem 0 1rem" : "0"}
|
|
57
|
+
`}
|
|
58
|
+
fontSize={isMobile ? FONT_SIZE.SM : FONT_SIZE.LG}
|
|
59
|
+
color={themeValues.secondaryColor}
|
|
60
|
+
>
|
|
61
|
+
{description}
|
|
62
|
+
</Text>
|
|
63
|
+
</Box>
|
|
64
|
+
<Styled.ButtonContainer
|
|
65
|
+
justify="space-between"
|
|
66
|
+
fullHeight
|
|
67
|
+
childGap="0.5rem"
|
|
68
|
+
isMobile={isMobile}
|
|
69
|
+
>
|
|
70
|
+
<Styled.RegisterLink
|
|
71
|
+
variant="secondary"
|
|
72
|
+
color={themeValues.primaryColor}
|
|
73
|
+
contentOverride
|
|
74
|
+
fontWeight={FONT_WEIGHT_SEMIBOLD}
|
|
75
|
+
url={registrationLink}
|
|
76
|
+
>
|
|
77
|
+
<Cluster justify="center" align="center">
|
|
78
|
+
<Text
|
|
79
|
+
extraStyles="margin-right: 0.5rem"
|
|
80
|
+
fontSize={isMobile ? FONT_SIZE.MD : FONT_SIZE.LG}
|
|
81
|
+
color={themeValues.primaryColor}
|
|
82
|
+
weight={FONT_WEIGHT_SEMIBOLD}
|
|
83
|
+
>
|
|
84
|
+
Register Now
|
|
85
|
+
</Text>
|
|
86
|
+
<ArrowRightIcon />
|
|
87
|
+
</Cluster>
|
|
88
|
+
</Styled.RegisterLink>
|
|
89
|
+
<Styled.LoginLink
|
|
90
|
+
text="Log In"
|
|
91
|
+
variant="secondary"
|
|
92
|
+
contentOverride
|
|
93
|
+
url={loginLink}
|
|
94
|
+
>
|
|
95
|
+
<Text
|
|
96
|
+
fontSize={isMobile ? FONT_SIZE.SM : FONT_SIZE.MD}
|
|
97
|
+
color={themeValues.primaryColor}
|
|
98
|
+
weight={FONT_WEIGHT_SEMIBOLD}
|
|
99
|
+
>
|
|
100
|
+
or Log In
|
|
101
|
+
</Text>
|
|
102
|
+
</Styled.LoginLink>
|
|
103
|
+
</Styled.ButtonContainer>
|
|
104
|
+
</Styled.ContentContainer>
|
|
105
|
+
</Styled.BannerContainer>
|
|
106
|
+
);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export default withWindowSize(
|
|
110
|
+
themeComponent(RegistrationBanner, "RegistrationBanner", fallbackValues)
|
|
111
|
+
);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Canvas, Meta, Title, Story, Controls } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
import * as RegistrationBannerStories from './RegistrationBanner.stories.js';
|
|
4
|
+
|
|
5
|
+
<Meta of={RegistrationBannerStories} />
|
|
6
|
+
|
|
7
|
+
<Title />
|
|
8
|
+
|
|
9
|
+
Originally used in the PayDot project, `RegistrationBanner` displays a promotional banner for user registration. It includes the following features:
|
|
10
|
+
|
|
11
|
+
- **Title and Description**: Displays a title and description text, which can be customized via props.
|
|
12
|
+
- **Responsive Design**: Adjusts its layout and font sizes based on whether the user is on a mobile device, using the `isMobile` value from the theme context.
|
|
13
|
+
- **Styled Components**: Utilizes styled-components for styling, ensuring consistent theming and styling across the application.
|
|
14
|
+
- **Action Links**: Provides two main action links - one for registration ("Register Now") and another for logging in ("Log In"), each styled appropriately and including an icon for the registration link.
|
|
15
|
+
- **Accessibility**: Includes ARIA roles and labels to improve accessibility for users with disabilities.
|
|
16
|
+
- **Customizable Links**: Accepts `registrationLink` and `loginLink` props to customize the URLs for the registration and login links, defaulting to `/registration` and `/login` respectively.
|
|
17
|
+
|
|
18
|
+
<Controls />
|
|
19
|
+
|
|
20
|
+
<div style={{ marginBottom: "2em"}}>
|
|
21
|
+
<Story />
|
|
22
|
+
</div>
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import RegistrationBanner from "./RegistrationBanner";
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: "Molecules/RegistrationBanner",
|
|
6
|
+
component: RegistrationBanner,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: "centered"
|
|
9
|
+
},
|
|
10
|
+
tags: ["!autodocs"],
|
|
11
|
+
args: {
|
|
12
|
+
description:
|
|
13
|
+
"Save payment methods and accounts to make interacting with Cityville fast, safe, and easy.",
|
|
14
|
+
extraStyles: "",
|
|
15
|
+
title: "Register for a Cityville Wallet Account",
|
|
16
|
+
titleAs: "h1",
|
|
17
|
+
titleVariant: "h1",
|
|
18
|
+
registrationLink: "/registration",
|
|
19
|
+
loginLink: "/login"
|
|
20
|
+
},
|
|
21
|
+
argTypes: {
|
|
22
|
+
title: {
|
|
23
|
+
description: "Text to display in the RegistrationBanner's heading area",
|
|
24
|
+
table: {
|
|
25
|
+
type: { summary: "string" },
|
|
26
|
+
defaultValue: { summary: "Register for a Cityville Wallet Account" }
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
description: {
|
|
30
|
+
description:
|
|
31
|
+
"Text to display in the RegistrationBanner's description area",
|
|
32
|
+
table: {
|
|
33
|
+
type: { summary: "string" },
|
|
34
|
+
defaultValue: {
|
|
35
|
+
summary:
|
|
36
|
+
"Save payment methods and accounts to make interacting with Cityville fast, safe, and easy."
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
extraStyles: {
|
|
41
|
+
description: "Additional styles for the RegistrationBanner",
|
|
42
|
+
table: {
|
|
43
|
+
type: { summary: "string" },
|
|
44
|
+
defaultValue: { summary: "" }
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
titleAs: {
|
|
48
|
+
description: "HTML tag to use for the title",
|
|
49
|
+
table: {
|
|
50
|
+
type: { summary: "string" },
|
|
51
|
+
defaultValue: { summary: "h1" }
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
titleVariant: {
|
|
55
|
+
description: "Variant of the title",
|
|
56
|
+
table: {
|
|
57
|
+
type: { summary: "string" },
|
|
58
|
+
defaultValue: { summary: "h1" }
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
registrationLink: {
|
|
62
|
+
description: "URL for the registration link",
|
|
63
|
+
table: {
|
|
64
|
+
type: { summary: "string" },
|
|
65
|
+
defaultValue: { summary: "/registration" }
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
loginLink: {
|
|
69
|
+
description: "URL for the login link",
|
|
70
|
+
table: {
|
|
71
|
+
type: { summary: "string" },
|
|
72
|
+
defaultValue: { summary: "/login" }
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export default meta;
|
|
79
|
+
|
|
80
|
+
export const StandardRegistrationBanner = {
|
|
81
|
+
args: {},
|
|
82
|
+
parameters: {
|
|
83
|
+
viewport: {
|
|
84
|
+
defaultViewport: "responsive"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
render: args => {
|
|
88
|
+
return <RegistrationBanner {...args} key="registration-banner-standard" />;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
import { Box, Cluster, Stack } from "../../atoms/layouts";
|
|
3
|
+
import ButtonWithLink from "../../atoms/button-with-link/ButtonWithLink";
|
|
4
|
+
import { hexToRGBA } from "../../../util/general";
|
|
5
|
+
|
|
6
|
+
export const BannerContainer = styled(Box)`
|
|
7
|
+
background: ${({ themeValues }) => hexToRGBA(themeValues.background, 0.9)};
|
|
8
|
+
padding: ${({ isMobile }) => (isMobile ? "1rem 2rem" : " 2rem 8.25rem")};
|
|
9
|
+
`;
|
|
10
|
+
|
|
11
|
+
export const ContentContainer = styled(Cluster)`
|
|
12
|
+
padding: 0;
|
|
13
|
+
width: ${({ isMobile }) => (isMobile ? "296px" : " 1176px")};
|
|
14
|
+
> div {
|
|
15
|
+
flex-direction: ${({ isMobile }) => (isMobile ? "column" : "row")};
|
|
16
|
+
}
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
export const ButtonContainer = styled(Stack)`
|
|
20
|
+
align-items: center;
|
|
21
|
+
> a {
|
|
22
|
+
width: ${({ isMobile }) => (isMobile ? "296px" : "222px")};
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
25
|
+
|
|
26
|
+
export const RegisterLink = styled(ButtonWithLink)`
|
|
27
|
+
border-radius: 100px;
|
|
28
|
+
margin: 0;
|
|
29
|
+
width: 100%;
|
|
30
|
+
`;
|
|
31
|
+
|
|
32
|
+
export const LoginLink = styled(ButtonWithLink)`
|
|
33
|
+
border-radius: 100px;
|
|
34
|
+
padding: 0;
|
|
35
|
+
margin: 0;
|
|
36
|
+
width: 100%;
|
|
37
|
+
min-height: 2rem;
|
|
38
|
+
margin-top: 0px;
|
|
39
|
+
border: none;
|
|
40
|
+
&:hover {
|
|
41
|
+
text-decoration: none;
|
|
42
|
+
}
|
|
43
|
+
`;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import Expand from "../../../util/expand";
|
|
3
|
+
import RegistrationBanner from "./index";
|
|
4
|
+
|
|
5
|
+
export interface RegistrationBannerProps {
|
|
6
|
+
description?: string;
|
|
7
|
+
extraStyles?: string;
|
|
8
|
+
loginLink?: string;
|
|
9
|
+
registrationLink?: string;
|
|
10
|
+
title?: string;
|
|
11
|
+
titleAs?: string;
|
|
12
|
+
titleVariant?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const RegistrationBanner: React.FC<Expand<RegistrationBannerProps> &
|
|
16
|
+
React.HTMLAttributes<HTMLElement>>;
|
|
@@ -16,11 +16,11 @@ import {
|
|
|
16
16
|
import { themeComponent } from "../../../util/themeUtils";
|
|
17
17
|
import { fallbackValues } from "./TabSidebar.theme";
|
|
18
18
|
|
|
19
|
-
const TabSidebar = ({ links, isMobile, themeValues }) => (
|
|
19
|
+
const TabSidebar = ({ links, isMobile, themeValues, minHeight = "100%" }) => (
|
|
20
20
|
<Box
|
|
21
21
|
padding="0"
|
|
22
22
|
background={COOL_GREY_05}
|
|
23
|
-
minHeight=
|
|
23
|
+
minHeight={minHeight}
|
|
24
24
|
role="region"
|
|
25
25
|
aria-label="Profile tabs"
|
|
26
26
|
boxShadow={isMobile && `inset 0px -1px 0px 0px rgb(202, 206, 216)`}
|
package/src/util/general.js
CHANGED
|
@@ -213,3 +213,39 @@ export const adjustHexColor = (hex, percent, action) => {
|
|
|
213
213
|
.slice(1)
|
|
214
214
|
.padStart(6, "0")}`;
|
|
215
215
|
};
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Converts a hex color code to an RGBA color string with the specified alpha value.
|
|
219
|
+
*
|
|
220
|
+
* @param {string} hex - The hex color code (e.g., "#3498db" or "3498db").
|
|
221
|
+
* @param {number} alpha - The alpha value (opacity) between 0 and 1.
|
|
222
|
+
* @returns {string} - The RGBA color string (e.g., "rgba(52, 152, 219, 0.5)").
|
|
223
|
+
* @throws {Error} - Throws an error if the hex code is not a valid 3 or 6-digit hex color.
|
|
224
|
+
*/
|
|
225
|
+
export const hexToRGBA = (hex, alpha) => {
|
|
226
|
+
// Remove hash at the start if present
|
|
227
|
+
hex = hex.replace(/^\s*#/, "");
|
|
228
|
+
|
|
229
|
+
// If hex is 3 characters, convert it to 6 characters.
|
|
230
|
+
if (hex.length === 3) {
|
|
231
|
+
hex = hex
|
|
232
|
+
.split("")
|
|
233
|
+
.map(char => char + char)
|
|
234
|
+
.join("");
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Validate hex length
|
|
238
|
+
if (hex.length !== 6) {
|
|
239
|
+
throw new Error(
|
|
240
|
+
"Invalid hex color provided. Expected a 3 or 6-digit hex color."
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Parse the hex color components
|
|
245
|
+
const bigint = parseInt(hex, 16);
|
|
246
|
+
const r = (bigint >> 16) & 255;
|
|
247
|
+
const g = (bigint >> 8) & 255;
|
|
248
|
+
const b = bigint & 255;
|
|
249
|
+
|
|
250
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
251
|
+
};
|