diff --git a/packages/orbit-components/cypress/integration/index.tsx b/packages/orbit-components/cypress/integration/index.tsx index 0be043c4ce..479385547d 100644 --- a/packages/orbit-components/cypress/integration/index.tsx +++ b/packages/orbit-components/cypress/integration/index.tsx @@ -9,6 +9,7 @@ import MediaQueries from "./pages/media-queries"; import ModalFooter from "./pages/modal-footer"; import BoxMediaProps from "./pages/box-mediaquery-props"; import StackMediaProps from "./pages/stack-mediaquery-props"; +import TextStyles from "./pages/text-styles"; const router = createRouter({ lockScrolling: "/lock-scrolling", @@ -16,6 +17,7 @@ const router = createRouter({ modalFooter: "/modal-footer", boxMediaProps: "/box-media-props", stackMediaProps: "/stack-media-props", + textStyles: "/text-styles", }); function PageNotFound() { @@ -68,6 +70,12 @@ function App() { ); + case "textStyles": + return ( + + + + ); default: return ; } diff --git a/packages/orbit-components/cypress/integration/pages/text-styles.test.ts b/packages/orbit-components/cypress/integration/pages/text-styles.test.ts new file mode 100644 index 0000000000..6f7ddeb005 --- /dev/null +++ b/packages/orbit-components/cypress/integration/pages/text-styles.test.ts @@ -0,0 +1,185 @@ +import { defaultFoundation } from "@kiwicom/orbit-design-tokens"; +import color from "onecolor"; + +const rgbaRegex = /rgb\((.{1,3}),(.{1,3}),(.{1,3})\)/; +const formatAlpha = (alpha: string) => (_, p1: string, p2: string, p3: string) => + `rgba(${p1}, ${p2}, ${p3}, ${alpha})`; + +describe("Text colors", () => { + it("should have correct colors", () => { + cy.visit("/text-styles"); + + cy.findByText("Primary").should( + "have.css", + "color", + color(defaultFoundation.palette.ink.dark).css().replaceAll(",", ", "), + ); + + cy.findByText("Secondary").should( + "have.css", + "color", + color(defaultFoundation.palette.ink.normal).css().replaceAll(",", ", "), + ); + + cy.findByText("Info").should( + "have.css", + "color", + color(defaultFoundation.palette.blue.normal).css().replaceAll(",", ", "), + ); + + cy.findByText("Success").should( + "have.css", + "color", + color(defaultFoundation.palette.green.normal).css().replaceAll(",", ", "), + ); + + cy.findByText("Warning").should( + "have.css", + "color", + color(defaultFoundation.palette.orange.normal).css().replaceAll(",", ", "), + ); + + cy.findByText("Critical").should( + "have.css", + "color", + color(defaultFoundation.palette.red.normal).css().replaceAll(",", ", "), + ); + + cy.findByText("White").should( + "have.css", + "color", + color(defaultFoundation.palette.white.normal).css().replaceAll(",", ", "), + ); + }); + + it("should have correct background colors", () => { + cy.visit("/text-styles"); + + cy.findByText("Primary").should( + "have.css", + "background-color", + color(defaultFoundation.palette.ink.dark).css().replace(rgbaRegex, formatAlpha("0.1")), + ); + + cy.findByText("Secondary").should( + "have.css", + "background-color", + color(defaultFoundation.palette.ink.normal).css().replace(rgbaRegex, formatAlpha("0.1")), + ); + + cy.findByText("Info").should( + "have.css", + "background-color", + color(defaultFoundation.palette.blue.normal).css().replace(rgbaRegex, formatAlpha("0.1")), + ); + + cy.findByText("Success").should( + "have.css", + "background-color", + color(defaultFoundation.palette.green.normal).css().replace(rgbaRegex, formatAlpha("0.1")), + ); + + cy.findByText("Warning").should( + "have.css", + "background-color", + color(defaultFoundation.palette.orange.normal).css().replace(rgbaRegex, formatAlpha("0.1")), + ); + + cy.findByText("Critical").should( + "have.css", + "background-color", + color(defaultFoundation.palette.red.normal).css().replace(rgbaRegex, formatAlpha("0.1")), + ); + + cy.findByText("White").should( + "have.css", + "background-color", + color(defaultFoundation.palette.white.normal).css().replace(rgbaRegex, formatAlpha("0.1")), + ); + }); +}); + +describe("Text with margins", () => { + it("should have correct margins from object", () => { + cy.visit("/text-styles"); + + cy.findByText("Object margin").should("have.css", "margin", "2px 4px 0px -1px"); + }); + + it("should have correct margins from string", () => { + cy.visit("/text-styles"); + + cy.findByText("String margin").should("have.css", "margin", "0px 1px -2px 0px"); + }); +}); + +describe("Links inside Text", () => { + it("should have correct common styles", () => { + cy.visit("/text-styles"); + + cy.findByText("Primary") + .get("a") + .should("have.css", "font-weight", defaultFoundation.fontWeight.medium) + .should("have.css", "text-decoration-line", "underline"); + }); + + it("should have correct colors", () => { + cy.visit("/text-styles"); + + cy.findByText("Primary") + .find("a") + .should( + "have.css", + "color", + color(defaultFoundation.palette.product.dark).css().replaceAll(",", ", "), + ); + + cy.findByText("Secondary") + .find("a") + .should( + "have.css", + "color", + color(defaultFoundation.palette.ink.dark).css().replaceAll(",", ", "), + ); + + cy.findByText("Info") + .find("a") + .should( + "have.css", + "color", + color(defaultFoundation.palette.blue.dark).css().replaceAll(",", ", "), + ); + + cy.findByText("Success") + .find("a") + .should( + "have.css", + "color", + color(defaultFoundation.palette.green.dark).css().replaceAll(",", ", "), + ); + + cy.findByText("Warning") + .find("a") + .should( + "have.css", + "color", + color(defaultFoundation.palette.orange.dark).css().replaceAll(",", ", "), + ); + + cy.findByText("Critical") + .find("a") + .should( + "have.css", + "color", + color(defaultFoundation.palette.red.dark).css().replaceAll(",", ", "), + ); + + cy.findByText("White") + .find("a") + .should( + "have.css", + "color", + color(defaultFoundation.palette.white.normal).css().replaceAll(",", ", "), + ); + }); +}); diff --git a/packages/orbit-components/cypress/integration/pages/text-styles.tsx b/packages/orbit-components/cypress/integration/pages/text-styles.tsx new file mode 100644 index 0000000000..aae78e7eb6 --- /dev/null +++ b/packages/orbit-components/cypress/integration/pages/text-styles.tsx @@ -0,0 +1,32 @@ +import React from "react"; +import { Text } from "@kiwicom/orbit-components"; + +export default function TextStyles() { + return ( + <> + + Primary link + + + Secondary link + + + Info link + + + Success link + + + Warning link + + + Critical link + + + White link + + Object margin + String margin + + ); +} diff --git a/packages/orbit-components/src/Text/__tests__/index.test.tsx b/packages/orbit-components/src/Text/__tests__/index.test.tsx index 9780e7ab87..6b6be421cf 100644 --- a/packages/orbit-components/src/Text/__tests__/index.test.tsx +++ b/packages/orbit-components/src/Text/__tests__/index.test.tsx @@ -1,59 +1,145 @@ import * as React from "react"; import { screen, render } from "../../test-utils"; +import theme from "../../defaultTheme"; +import { TEXT_ALIGN } from "../../common/tailwind/textAlign"; +import type { Props } from "../types"; +import type { SIZE_OPTIONS, WEIGHT_OPTIONS } from "../consts"; import Text from ".."; -import { SIZE_OPTIONS, TYPE_OPTIONS } from "../consts"; -import defaultTheme from "../../defaultTheme"; + +const SIZE_STYLES: { [K in SIZE_OPTIONS]: Record<"font-size" | "line-height", string> } = { + small: { + "font-size": theme.orbit.fontSizeTextSmall, + "line-height": theme.orbit.lineHeightTextSmall, + }, + normal: { + "font-size": theme.orbit.fontSizeTextNormal, + "line-height": theme.orbit.lineHeightTextNormal, + }, + large: { + "font-size": theme.orbit.fontSizeTextLarge, + "line-height": theme.orbit.lineHeightTextLarge, + }, + extraLarge: { + "font-size": theme.orbit.fontSizeTextExtraLarge, + "line-height": theme.orbit.lineHeightTextExtraLarge, + }, +}; + +const WEIGHT_STYLES: { [K in WEIGHT_OPTIONS]: Record<"font-weight", string> } = { + normal: { + "font-weight": theme.orbit.fontWeightNormal, + }, + bold: { + "font-weight": theme.orbit.fontWeightBold, + }, + medium: { + "font-weight": theme.orbit.fontWeightMedium, + }, +}; describe("Text", () => { - it("should have expected DOM output", () => { - const dataTest = "test"; - const text = "Children text"; - const type = TYPE_OPTIONS.PRIMARY; - const size = SIZE_OPTIONS.SMALL; - const id = "id"; + const dataTest = "test"; + const text = "Children text"; + const id = "id"; + it("should have expected DOM output", () => { render( - + {text} , ); - expect(screen.getByTestId(dataTest)).toHaveAttribute("id", id); - expect(screen.getByTestId(dataTest)).toBeInTheDocument(); + const textElement = screen.getByTestId(dataTest); + + expect(textElement.tagName).toBe("P"); + expect(textElement).toHaveAttribute("id", id); + expect(textElement).toBeInTheDocument(); expect(screen.getByText(text)).toBeInTheDocument(); + expect(textElement).toHaveStyle({ + margin: 0, + "font-family": theme.orbit.fontFamily, + "font-size": theme.orbit.fontSizeTextNormal, + "line-height": theme.orbit.lineHeightTextNormal, + "text-align": "left", + }); + }); + + it.each(Object.keys(SIZE_STYLES))("should have size %s", size => { + render( + + {text} + , + ); + + expect(screen.getByTestId(dataTest)).toHaveStyle(SIZE_STYLES[size]); + }); + + it.each(Object.keys(WEIGHT_STYLES))("should have weight %s", weight => { + render( + + {text} + , + ); + + expect(screen.getByTestId(dataTest)).toHaveStyle(WEIGHT_STYLES[weight]); + }); + + it.each(Object.values(TEXT_ALIGN))("should have align %s", align => { + render( + + {text} + , + ); + expect(screen.getByTestId(dataTest)).toHaveStyle({ - fontSize: defaultTheme.orbit.fontSizeTextSmall, - color: defaultTheme.orbit.colorTextPrimary, - marginBottom: defaultTheme.orbit.spaceSmall, + "text-align": align, }); }); - it("should have object margin", () => { - const dataTest = "test"; + it("should render according to the passed `as` prop", () => { + render( + + {text} + , + ); + + expect(screen.getByTestId(dataTest).tagName).toBe("DIV"); + }); + it("should render uppercase", () => { render( - - Chuck Norris can divide by zero. + + {text} , ); expect(screen.getByTestId(dataTest)).toHaveStyle({ - marginBottom: "0", + "text-transform": "uppercase", }); }); - it("should have string margin", () => { - const dataTest = "test"; + it("should render italic", () => { + render( + + {text} + , + ); + + expect(screen.getByTestId(dataTest)).toHaveStyle({ + "font-style": "italic", + }); + }); + it("should render strikethrough", () => { render( - - Chuck Norris can divide by zero. + + {text} , ); expect(screen.getByTestId(dataTest)).toHaveStyle({ - marginRight: "12px", + "text-decoration-line": "line-through", }); }); }); diff --git a/packages/orbit-components/src/Text/deprecated/index.tsx b/packages/orbit-components/src/Text/deprecated/index.tsx new file mode 100644 index 0000000000..ca27994401 --- /dev/null +++ b/packages/orbit-components/src/Text/deprecated/index.tsx @@ -0,0 +1,117 @@ +import * as React from "react"; +import styled, { css } from "styled-components"; +import { convertHexToRgba } from "@kiwicom/orbit-design-tokens"; + +import type * as Common from "../../common/types"; +import type { Theme } from "../../defaultTheme"; +import defaultTheme from "../../defaultTheme"; +import { TYPE_OPTIONS, WEIGHT_OPTIONS, ELEMENT_OPTIONS, SIZE_OPTIONS } from "../consts"; +import { textAlign } from "../../utils/rtl"; +import { getLinkStyle } from "../../TextLink/deprecated"; +import { spacingUtility } from "../../utils/common"; +import type { Type, Weight } from "../types"; + +const getTypeToken = ({ theme, type }: { theme: Theme; type: Type }): string => { + const typeTokens = { + [TYPE_OPTIONS.PRIMARY]: theme.orbit.colorTextPrimary, + [TYPE_OPTIONS.SECONDARY]: theme.orbit.colorTextSecondary, + [TYPE_OPTIONS.INFO]: theme.orbit.colorTextInfo, + [TYPE_OPTIONS.SUCCESS]: theme.orbit.colorTextSuccess, + [TYPE_OPTIONS.WARNING]: theme.orbit.colorTextWarning, + [TYPE_OPTIONS.CRITICAL]: theme.orbit.colorTextCritical, + [TYPE_OPTIONS.WHITE]: theme.orbit.colorTextWhite, + }; + + return typeTokens[type]; +}; + +const getWeightToken = ({ theme, weight }: { theme: Theme; weight: Weight }): string | null => { + const weightTokens = { + [WEIGHT_OPTIONS.NORMAL]: theme.orbit.fontWeightNormal, + [WEIGHT_OPTIONS.MEDIUM]: theme.orbit.fontWeightMedium, + [WEIGHT_OPTIONS.BOLD]: theme.orbit.fontWeightBold, + }; + + if (!weight) return null; + + return weightTokens[weight]; +}; + +const getSizeToken = ({ theme, size }: { theme: Theme; size: Common.Size }): string | null => { + const sizeTokens = { + [SIZE_OPTIONS.EXTRA_LARGE]: theme.orbit.fontSizeTextExtraLarge, + [SIZE_OPTIONS.LARGE]: theme.orbit.fontSizeTextLarge, + [SIZE_OPTIONS.NORMAL]: theme.orbit.fontSizeTextNormal, + [SIZE_OPTIONS.SMALL]: theme.orbit.fontSizeTextSmall, + }; + + if (!size) return null; + + return sizeTokens[size]; +}; + +const getLineHeightToken = ({ + theme, + size, +}: { + theme: Theme; + size?: Common.Size | null; +}): string | null => { + const lineHeightTokens = { + [SIZE_OPTIONS.EXTRA_LARGE]: theme.orbit.lineHeightTextExtraLarge, + [SIZE_OPTIONS.LARGE]: theme.orbit.lineHeightTextLarge, + [SIZE_OPTIONS.NORMAL]: theme.orbit.lineHeightTextNormal, + [SIZE_OPTIONS.SMALL]: theme.orbit.lineHeightTextSmall, + }; + + if (!size) return null; + + return lineHeightTokens[size]; +}; + +/** + * @deprecated use .orbit-text selector instead + */ +export const StyledText = styled( + ({ element: TextElement = ELEMENT_OPTIONS.P, children, className, dataTest, id }) => ( + + {children} + + ), +)` + ${({ + theme, + align, + uppercase, + size, + weight, + strikeThrough, + $type, + italic, + withBackground, + margin, + }) => css` + font-family: ${theme.orbit.fontFamily}; + background: ${withBackground && convertHexToRgba(getTypeToken({ theme, type: $type }), 10)}; + font-size: ${getSizeToken({ theme, size })}; + font-weight: ${getWeightToken({ theme, weight })}; + color: ${getTypeToken({ theme, type: $type })}; + line-height: ${getLineHeightToken({ theme, size })}; + text-align: ${textAlign(align)}; + text-transform: ${uppercase && `uppercase`}; + text-decoration: ${strikeThrough && `line-through`}; + font-style: ${italic && `italic`}; + margin: 0; + ${spacingUtility(margin)}; + + a:not(.orbit-text-link) { + ${getLinkStyle({ theme, $type })}; + } + `} +`; + +StyledText.defaultProps = { + theme: defaultTheme, +}; + +export default StyledText; diff --git a/packages/orbit-components/src/Text/helpers/getMargin.ts b/packages/orbit-components/src/Text/helpers/getMargin.ts new file mode 100644 index 0000000000..695c8605d9 --- /dev/null +++ b/packages/orbit-components/src/Text/helpers/getMargin.ts @@ -0,0 +1,37 @@ +import type { Props } from "../types"; + +const getMarginValue = (margin: string | number): string => + typeof margin === "number" ? `${margin}px` : margin; + +const getMargin = (margin: Props["margin"]): { vars: object; classes: string[] } => { + if (typeof margin === "number" || typeof margin === "string") + return { + vars: { "--text-margin": getMarginValue(margin) }, + classes: ["m-[var(--text-margin)]"], + }; + + const { top, bottom, left, right } = margin || {}; + const cssVar = {}; + const marginClasses: string[] = ["m-0"]; + + if (top) { + marginClasses.push("mt-[var(--text-margin-top)]"); + cssVar["--text-margin-top"] = getMarginValue(top); + } + if (bottom) { + marginClasses.push("mb-[var(--text-margin-bottom)]"); + cssVar["--text-margin-bottom"] = getMarginValue(bottom); + } + if (left) { + marginClasses.push("ml-[var(--text-margin-left)]"); + cssVar["--text-margin-left"] = getMarginValue(left); + } + if (right) { + marginClasses.push("mr-[var(--text-margin-right)]"); + cssVar["--text-margin-right"] = getMarginValue(right); + } + + return { vars: cssVar, classes: marginClasses }; +}; + +export default getMargin; diff --git a/packages/orbit-components/src/Text/helpers/twClasses.ts b/packages/orbit-components/src/Text/helpers/twClasses.ts new file mode 100644 index 0000000000..185aeb7e7a --- /dev/null +++ b/packages/orbit-components/src/Text/helpers/twClasses.ts @@ -0,0 +1,50 @@ +import { SIZE_OPTIONS, TYPE_OPTIONS, WEIGHT_OPTIONS } from "../consts"; + +export const typeClasses: Record = { + [TYPE_OPTIONS.PRIMARY]: + "text-primary-foreground [&_a:not(.orbit-text-link)]:text-link-primary-foreground hover:[&_a:not(.orbit-text-link)]:text-link-primary-foreground-hover active:[&_a:not(.orbit-text-link)]:text-link-primary-foreground-active", + [TYPE_OPTIONS.SECONDARY]: + "text-secondary-foreground [&_a:not(.orbit-text-link)]:text-link-secondary-foreground hover:[&_a:not(.orbit-text-link)]:text-link-secondary-foreground-hover active:[&_a:not(.orbit-text-link)]:text-link-secondary-foreground-active", + [TYPE_OPTIONS.SUCCESS]: + "text-success-foreground [&_a:not(.orbit-text-link)]:text-link-success-foreground hover:[&_a:not(.orbit-text-link)]:text-link-success-foreground-hover active:[&_a:not(.orbit-text-link)]:text-link-success-foreground-active", + [TYPE_OPTIONS.INFO]: + "text-info-foreground [&_a:not(.orbit-text-link)]:text-link-info-foreground hover:[&_a:not(.orbit-text-link)]:text-link-info-foreground-hover active:[&_a:not(.orbit-text-link)]:text-link-info-foreground-active", + [TYPE_OPTIONS.WARNING]: + "text-warning-foreground [&_a:not(.orbit-text-link)]:text-link-warning-foreground hover:[&_a:not(.orbit-text-link)]:text-link-warning-foreground-hover active:[&_a:not(.orbit-text-link)]:text-link-warning-foreground-active", + [TYPE_OPTIONS.CRITICAL]: + "text-critical-foreground [&_a:not(.orbit-text-link)]:text-link-critical-foreground hover:[&_a:not(.orbit-text-link)]:text-link-critical-foreground-hover active:[&_a:not(.orbit-text-link)]:text-link-critical-foreground-active", + [TYPE_OPTIONS.WHITE]: + "text-white-foreground [&_a:not(.orbit-text-link)]:text-link-white-foreground hover:[&_a:not(.orbit-text-link)]:text-link-white-foreground-hover active:[&_a:not(.orbit-text-link)]:text-link-white-foreground-active", +}; + +export const backgroundClasses: Record = { + [TYPE_OPTIONS.PRIMARY]: "bg-text-primary-background", + [TYPE_OPTIONS.SECONDARY]: "bg-text-secondary-background", + [TYPE_OPTIONS.INFO]: "bg-text-info-background", + [TYPE_OPTIONS.SUCCESS]: "bg-text-success-background", + [TYPE_OPTIONS.WARNING]: "bg-text-warning-background", + [TYPE_OPTIONS.CRITICAL]: "bg-text-critical-background", + [TYPE_OPTIONS.WHITE]: "bg-text-white-background", +}; + +export const sizeClasses: Record = { + [SIZE_OPTIONS.SMALL]: "text-small leading-small", + [SIZE_OPTIONS.NORMAL]: "text-normal leading-normal", + [SIZE_OPTIONS.LARGE]: "text-large leading-large", + [SIZE_OPTIONS.EXTRA_LARGE]: "text-extra-large leading-extra-large", +}; + +export const weightClasses: Record = { + [WEIGHT_OPTIONS.NORMAL]: "font-normal", + [WEIGHT_OPTIONS.MEDIUM]: "font-medium", + [WEIGHT_OPTIONS.BOLD]: "font-bold", +}; + +export const textLinkCommonClasses = [ + "[&_a:not(.orbit-text-link)]:font-medium", + "[&_a:not(.orbit-text-link)]:underline", + "hover:[&_a:not(.orbit-text-link)]:no-underline", + "active:[&_a:not(.orbit-text-link)]:no-underline", + "hover:[&_a:not(.orbit-text-link)]:outline-none", + "active:[&_a:not(.orbit-text-link)]:outline-none", +]; diff --git a/packages/orbit-components/src/Text/index.js.flow b/packages/orbit-components/src/Text/index.js.flow index 23576b0ae8..f3f9be0b70 100644 --- a/packages/orbit-components/src/Text/index.js.flow +++ b/packages/orbit-components/src/Text/index.js.flow @@ -3,7 +3,6 @@ DOCUMENTATION: https://orbit.kiwi/components/text/ */ import * as React from "react"; -import type { StyledComponent } from "styled-components"; import type { spaceAfter } from "../common/getSpacingToken/index.js.flow"; import type { Globals, ObjectProperty } from "../common/common.js.flow"; @@ -32,5 +31,3 @@ export type Props = {| |}; declare export default React.ComponentType; - -declare export var StyledText: StyledComponent; diff --git a/packages/orbit-components/src/Text/index.tsx b/packages/orbit-components/src/Text/index.tsx index df075d4de0..b7a847bd52 100644 --- a/packages/orbit-components/src/Text/index.tsx +++ b/packages/orbit-components/src/Text/index.tsx @@ -1,12 +1,8 @@ "use client"; import * as React from "react"; -import styled, { css } from "styled-components"; -import { convertHexToRgba } from "@kiwicom/orbit-design-tokens"; +import cx from "clsx"; -import type * as Common from "../common/types"; -import type { Theme } from "../defaultTheme"; -import defaultTheme from "../defaultTheme"; import { TYPE_OPTIONS, WEIGHT_OPTIONS, @@ -14,112 +10,17 @@ import { ALIGN_OPTIONS, SIZE_OPTIONS, } from "./consts"; -import getSpacingToken from "../common/getSpacingToken"; -import { textAlign } from "../utils/rtl"; -import { getLinkStyle, StyledTextLink } from "../TextLink"; -import { spacingUtility } from "../utils/common"; -import useTheme from "../hooks/useTheme"; -import type { Props, Type, Weight } from "./types"; - -const getTypeToken = ({ theme, type }: { theme: Theme; type: Type }): string => { - const typeTokens = { - [TYPE_OPTIONS.PRIMARY]: theme.orbit.colorTextPrimary, - [TYPE_OPTIONS.SECONDARY]: theme.orbit.colorTextSecondary, - [TYPE_OPTIONS.INFO]: theme.orbit.colorTextInfo, - [TYPE_OPTIONS.SUCCESS]: theme.orbit.colorTextSuccess, - [TYPE_OPTIONS.WARNING]: theme.orbit.colorTextWarning, - [TYPE_OPTIONS.CRITICAL]: theme.orbit.colorTextCritical, - [TYPE_OPTIONS.WHITE]: theme.orbit.colorTextWhite, - }; - - return typeTokens[type]; -}; - -const getWeightToken = ({ theme, weight }: { theme: Theme; weight: Weight }): string | null => { - const weightTokens = { - [WEIGHT_OPTIONS.NORMAL]: theme.orbit.fontWeightNormal, - [WEIGHT_OPTIONS.MEDIUM]: theme.orbit.fontWeightMedium, - [WEIGHT_OPTIONS.BOLD]: theme.orbit.fontWeightBold, - }; - - if (!weight) return null; - - return weightTokens[weight]; -}; - -const getSizeToken = ({ theme, size }: { theme: Theme; size: Common.Size }): string | null => { - const sizeTokens = { - [SIZE_OPTIONS.EXTRA_LARGE]: theme.orbit.fontSizeTextExtraLarge, - [SIZE_OPTIONS.LARGE]: theme.orbit.fontSizeTextLarge, - [SIZE_OPTIONS.NORMAL]: theme.orbit.fontSizeTextNormal, - [SIZE_OPTIONS.SMALL]: theme.orbit.fontSizeTextSmall, - }; - - if (!size) return null; - - return sizeTokens[size]; -}; - -const getLineHeightToken = ({ - theme, - size, -}: { - theme: Theme; - size?: Common.Size | null; -}): string | null => { - const lineHeightTokens = { - [SIZE_OPTIONS.EXTRA_LARGE]: theme.orbit.lineHeightTextExtraLarge, - [SIZE_OPTIONS.LARGE]: theme.orbit.lineHeightTextLarge, - [SIZE_OPTIONS.NORMAL]: theme.orbit.lineHeightTextNormal, - [SIZE_OPTIONS.SMALL]: theme.orbit.lineHeightTextSmall, - }; - - if (!size) return null; - - return lineHeightTokens[size]; -}; - -export const StyledText = styled( - ({ element: TextElement = ELEMENT_OPTIONS.P, children, className, dataTest, id }) => ( - - {children} - - ), -)` - ${({ - theme, - align, - uppercase, - size, - weight, - strikeThrough, - $type, - italic, - withBackground, - margin, - }) => css` - font-family: ${theme.orbit.fontFamily}; - background: ${withBackground && convertHexToRgba(getTypeToken({ theme, type: $type }), 10)}; - font-size: ${getSizeToken({ theme, size })}; - font-weight: ${getWeightToken({ theme, weight })}; - color: ${getTypeToken({ theme, type: $type })}; - line-height: ${getLineHeightToken({ theme, size })}; - text-align: ${textAlign(align)}; - text-transform: ${uppercase && `uppercase`}; - text-decoration: ${strikeThrough && `line-through`}; - font-style: ${italic && `italic`}; - margin: 0; - ${spacingUtility(margin)}; - - a:not(${StyledTextLink}) { - ${getLinkStyle({ theme, $type })}; - } - `} -`; - -StyledText.defaultProps = { - theme: defaultTheme, -}; +import type { Props } from "./types"; +import { spaceAfterClasses } from "../common/tailwind/spaceAfter"; +import { + backgroundClasses, + sizeClasses, + textLinkCommonClasses, + typeClasses, + weightClasses, +} from "./helpers/twClasses"; +import { textAlignClasses } from "../common/tailwind/textAlign"; +import getMargin from "./helpers/getMargin"; const Text = ({ type = TYPE_OPTIONS.PRIMARY, @@ -127,7 +28,7 @@ const Text = ({ weight = WEIGHT_OPTIONS.NORMAL, align = ALIGN_OPTIONS.LEFT, margin, - as = ELEMENT_OPTIONS.P, + as: Component = ELEMENT_OPTIONS.P, uppercase, italic, strikeThrough, @@ -137,26 +38,30 @@ const Text = ({ withBackground, id, }: Props) => { - const theme = useTheme(); + const { vars: cssVar, classes: marginClasses } = getMargin(margin); return ( - {children} - + ); };