Skip to content

Commit 11583d3

Browse files
🪟 🎨 Add Text component (#15570)
* Add Text component * Fix regexp for heading matching in Text component Co-authored-by: Krishna Glick <[email protected]> * Reset margin and padding on text elements * Update default text element to p * Split scss for heading and text * Split types between Text and Heading * Rename text scss * Rename text scsss module * Remove font-weight from FormTitle * Split Text md size out of default style, fix typing issues * Update line heights on headings and remove override from SignupPage * Remove default heading type assignment when destructuring props since `as` is required to infer heading Co-authored-by: Krishna Glick <[email protected]>
1 parent 9730908 commit 11583d3

File tree

10 files changed

+174
-14
lines changed

10 files changed

+174
-14
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import classNames from "classnames";
2+
import React from "react";
3+
4+
import headingStyles from "./heading.module.scss";
5+
import textStyles from "./text.module.scss";
6+
7+
type TextSize = "sm" | "md" | "lg";
8+
type HeadingSize = TextSize | "xl";
9+
type TextElementType = "p" | "span" | "div";
10+
type HeadingElementType = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
11+
12+
interface BaseProps {
13+
className?: string;
14+
centered?: boolean;
15+
}
16+
17+
interface TextProps extends BaseProps {
18+
as?: TextElementType;
19+
size?: TextSize;
20+
bold?: boolean;
21+
}
22+
23+
interface HeadingProps extends BaseProps {
24+
as: HeadingElementType;
25+
size?: HeadingSize;
26+
}
27+
28+
const getTextClassNames = ({ size, centered, bold }: Required<Pick<TextProps, "size" | "centered" | "bold">>) => {
29+
const sizes: Record<TextSize, string> = {
30+
sm: textStyles.sm,
31+
md: textStyles.md,
32+
lg: textStyles.lg,
33+
};
34+
35+
return classNames(textStyles.text, sizes[size], centered && textStyles.centered, bold && textStyles.bold);
36+
};
37+
38+
const getHeadingClassNames = ({ size, centered }: Required<Pick<HeadingProps, "size" | "centered">>) => {
39+
const sizes: Record<HeadingSize, string> = {
40+
sm: headingStyles.sm,
41+
md: headingStyles.md,
42+
lg: headingStyles.lg,
43+
xl: headingStyles.xl,
44+
};
45+
46+
return classNames(headingStyles.heading, sizes[size], centered && headingStyles.centered);
47+
};
48+
49+
const isHeadingType = (props: TextProps | HeadingProps): props is HeadingProps => {
50+
return props.as ? /^h[0-6]$/.test(props.as) : false;
51+
};
52+
53+
export const Text: React.FC<TextProps | HeadingProps> = React.memo((props) => {
54+
const isHeading = isHeadingType(props);
55+
const { as = "p", centered = false, children } = props;
56+
57+
const className = classNames(
58+
isHeading
59+
? getHeadingClassNames({ centered, size: props.size ?? "md" })
60+
: getTextClassNames({ centered, size: props.size ?? "md", bold: props.bold ?? false }),
61+
props.className
62+
);
63+
64+
return React.createElement(as, {
65+
className,
66+
children,
67+
});
68+
});
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
@use "../../../scss/colors";
2+
3+
.heading {
4+
font-weight: 700;
5+
6+
color: colors.$dark-blue;
7+
margin: 0;
8+
padding: 0;
9+
}
10+
11+
.sm {
12+
font-size: 16px;
13+
line-height: 1.2em;
14+
}
15+
16+
.md,
17+
.lg,
18+
.xl {
19+
line-height: 1.3em;
20+
}
21+
22+
.md {
23+
font-size: 20px;
24+
}
25+
26+
.lg {
27+
font-size: 24px;
28+
}
29+
30+
.xl {
31+
font-size: 32px;
32+
}
33+
34+
.centered {
35+
text-align: center;
36+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { ComponentStory, ComponentMeta } from "@storybook/react";
2+
3+
import { Text } from "./Text";
4+
5+
export default {
6+
title: "Ui/Text",
7+
component: Text,
8+
} as ComponentMeta<typeof Text>;
9+
10+
const Template: ComponentStory<typeof Text> = (args) => <Text {...args} />;
11+
12+
export const Primary = Template.bind({});
13+
Primary.args = {
14+
size: "md",
15+
children:
16+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
17+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { Text } from "./Text";
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
@use "../../../scss/colors";
2+
3+
.text {
4+
color: colors.$dark-blue;
5+
margin: 0;
6+
padding: 0;
7+
}
8+
9+
.sm,
10+
.md {
11+
font-weight: 400;
12+
line-height: 1.2em;
13+
}
14+
15+
.sm {
16+
font-size: 12px;
17+
}
18+
19+
.md {
20+
font-size: 13px;
21+
}
22+
23+
.lg {
24+
font-size: 14px;
25+
font-weight: 500;
26+
line-height: 1.3em;
27+
}
28+
29+
.centered {
30+
text-align: center;
31+
}
32+
33+
.bold,
34+
.text > strong {
35+
font-weight: 600;
36+
}
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
@use "../../../../../scss/colors";
2+
@use "../../../../../scss/variables";
23

34
.title {
4-
font-weight: 700;
5-
font-size: 32px;
6-
line-height: 39px;
75
width: 250px;
8-
color: colors.$dark-blue-900;
6+
margin-bottom: variables.$spacing-md;
97
}
108

119
.highlight {
12-
color: colors.$blue-400;
10+
color: colors.$blue;
1311
}

airbyte-webapp/src/packages/cloud/views/auth/SignupPage/SignupPage.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from "react";
22
import { FormattedMessage } from "react-intl";
33

4+
import { Text } from "components/base/Text";
45
import HeadTitle from "components/HeadTitle";
56

67
import { OAuthLogin } from "../OAuthLogin";
@@ -16,7 +17,7 @@ const SignupPage: React.FC<SignupPageProps> = ({ highlightStyle }) => {
1617
return (
1718
<div>
1819
<HeadTitle titles={[{ id: "login.signup" }]} />
19-
<h1 className={styles.title}>
20+
<Text as="h1" size="xl" className={styles.title}>
2021
<FormattedMessage
2122
id="login.activateAccess"
2223
values={{
@@ -27,7 +28,7 @@ const SignupPage: React.FC<SignupPageProps> = ({ highlightStyle }) => {
2728
),
2829
}}
2930
/>
30-
</h1>
31+
</Text>
3132
<SpecialBlock />
3233
<SignupForm />
3334
<OAuthLogin isSignUpPage />

airbyte-webapp/src/packages/cloud/views/auth/components/FormComponents.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Form as FormikForm } from "formik";
22
import styled from "styled-components";
33

44
export const Form = styled(FormikForm)`
5-
margin-top: 42px;
5+
margin-top: 40px;
66
`;
77

88
export const FieldItem = styled.div`
@@ -28,7 +28,7 @@ export const BottomBlock = styled.div`
2828
flex-direction: row;
2929
justify-content: space-between;
3030
align-items: center;
31-
margin-top: 38px;
31+
margin-top: 40px;
3232
font-size: 11px;
3333
`;
3434

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
@use "../../../../../../scss/colors";
22

33
.title {
4-
font-weight: 700;
5-
font-size: 32px;
6-
line-height: 39px;
7-
color: colors.$blue-400;
4+
color: colors.$blue;
85
}
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import React from "react";
22

3+
import { Text } from "components/base/Text";
4+
35
import styles from "./FormTitle.module.scss";
46

5-
export const FormTitle: React.FC = ({ children }) => <h1 className={styles.title}>{children}</h1>;
7+
export const FormTitle: React.FC = ({ children }) => (
8+
<Text as="h1" size="xl" className={styles.title}>
9+
{children}
10+
</Text>
11+
);

0 commit comments

Comments
 (0)