diff --git a/package-lock.json b/package-lock.json index a7daf7e30a..0481ca11d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,6 +37,7 @@ "styled-components": "^5.3.3" }, "devDependencies": { + "@dxc-technology/typescript-config": "*", "@types/node": "^20", "@types/react": "^18", "@types/react-color": "^3.0.6", diff --git a/packages/lib/src/accordion/Accordion.tsx b/packages/lib/src/accordion/Accordion.tsx index aa9fc18b0c..e65d0218f5 100644 --- a/packages/lib/src/accordion/Accordion.tsx +++ b/packages/lib/src/accordion/Accordion.tsx @@ -4,7 +4,6 @@ import { getMargin } from "../common/utils"; import { spaces } from "../common/variables"; import useTheme from "../useTheme"; import AccordionPropsType from "./types"; -import BaseTypography from "../utils/BaseTypography"; import DxcIcon from "../icon/Icon"; const DxcAccordion = ({ @@ -42,46 +41,15 @@ const DxcAccordion = ({ isExpanded={isExpanded ?? innerIsExpanded} > - + {icon && ( {typeof icon === "string" ? : icon} )} - - {label} - + {label} - {assistiveText && ( - - - {assistiveText} - - - )} + {assistiveText && {assistiveText}} @@ -165,12 +133,18 @@ const AccordionInfo = styled.span` width: 100%; `; -const AccordionLabel = styled.span` +const AccordionLabel = styled.span<{ disabled: AccordionPropsType["disabled"] }>` display: flex; padding-top: ${(props) => props.theme.titleLabelPaddingTop}; padding-bottom: ${(props) => props.theme.titleLabelPaddingBottom}; padding-right: ${(props) => props.theme.titleLabelPaddingRight}; padding-left: ${(props) => props.theme.titleLabelPaddingLeft}; + color: ${(props) => (props.disabled ? props.theme.disabledTitleLabelFontColor : props.theme.titleLabelFontColor)}; + font-family: ${(props) => props.theme.titleLabelFontFamily}; + font-size: ${(props) => props.theme.titleLabelFontSize}; + font-style: ${(props) => props.theme.titleLabelFontStyle}; + font-weight: ${(props) => props.theme.titleLabelFontWeight}; + line-height: 1.5em; `; const IconContainer = styled.span<{ disabled: AccordionPropsType["disabled"] }>` @@ -186,10 +160,18 @@ const IconContainer = styled.span<{ disabled: AccordionPropsType["disabled"] }>` } `; -const AccordionAssistiveText = styled.span` +const AccordionAssistiveText = styled.span<{ disabled: AccordionPropsType["disabled"] }>` min-width: ${(props) => props.theme.assistiveTextMinWidth}; padding-left: ${(props) => props.theme.assistiveTextPaddingLeft}; padding-right: ${(props) => props.theme.assistiveTextPaddingRight}; + color: ${(props) => + props.disabled ? props.theme.disabledAssistiveTextFontColor : props.theme.assistiveTextFontColor}; + font-family: ${(props) => props.theme.assistiveTextFontFamily}; + font-size: ${(props) => props.theme.assistiveTextFontSize}; + font-style: ${(props) => props.theme.assistiveTextFontStyle}; + font-weight: ${(props) => props.theme.assistiveTextFontWeight}; + letter-spacing: ${(props) => props.theme.assistiveTextLetterSpacing}; + line-height: 1.5em; `; const CollapseIndicator = styled.span<{ disabled: AccordionPropsType["disabled"] }>` diff --git a/packages/lib/src/image/Image.tsx b/packages/lib/src/image/Image.tsx index aedf700d5c..122d01f242 100644 --- a/packages/lib/src/image/Image.tsx +++ b/packages/lib/src/image/Image.tsx @@ -1,13 +1,30 @@ import styled, { ThemeProvider } from "styled-components"; import useTheme from "../useTheme"; -import BaseTypography from "../utils/BaseTypography"; import ImagePropsType, { CaptionWrapperProps } from "./types"; -const CaptionWrapper = ({ condition, wrapper, children }: CaptionWrapperProps): JSX.Element => ( +const Figure = styled.figure` + display: flex; + flex-direction: column; + gap: 1rem; + width: fit-content; + margin: 0; + padding: 0; +`; + +const CaptionContainer = styled.figcaption` + color: ${(props) => props.theme.captionFontColor}; + font-family: ${(props) => props.theme.captionFontFamily}; + font-size: ${(props) => props.theme.captionFontSize}; + font-style: ${(props) => props.theme.captionFontStyle}; + font-weight: ${(props) => props.theme.captionFontWeight}; + line-height: ${(props) => props.theme.captionLineHeight}; +`; + +const CaptionWrapper = ({ condition, wrapper, children }: CaptionWrapperProps) => ( <>{condition ? wrapper(children) : children} ); -const DxcImage = ({ +export default function DxcImage({ alt, caption, lazyLoading = false, @@ -20,7 +37,7 @@ const DxcImage = ({ objectPosition, onLoad, onError, -}: ImagePropsType) => { +}: ImagePropsType) { const colorsTheme = useTheme(); return ( @@ -30,17 +47,7 @@ const DxcImage = ({ wrapper={(children: React.ReactNode) => (
{children} - - {caption} - + {caption}
)} > @@ -62,15 +69,4 @@ const DxcImage = ({ ); -}; - -const Figure = styled.figure` - display: flex; - flex-direction: column; - gap: 1rem; - width: fit-content; - margin: 0; - padding: 0; -`; - -export default DxcImage; +} diff --git a/packages/lib/src/nav-tabs/Tab.tsx b/packages/lib/src/nav-tabs/Tab.tsx index 10082c17f3..2d094a09b2 100644 --- a/packages/lib/src/nav-tabs/Tab.tsx +++ b/packages/lib/src/nav-tabs/Tab.tsx @@ -3,8 +3,6 @@ import styled from "styled-components"; import DxcBadge from "../badge/Badge"; import DxcFlex from "../flex/Flex"; import DxcIcon from "../icon/Icon"; -import useTheme from "../useTheme"; -import BaseTypography from "../utils/BaseTypography"; import { NavTabsContext } from "./NavTabsContext"; import NavTabsPropsType, { TabProps } from "./types"; @@ -14,7 +12,6 @@ const DxcTab = forwardRef( ref: Ref ): JSX.Element => { const tabRef = useRef(); - const colorsTheme = useTheme(); const { iconPosition, tabIndex, focusedLabel } = useContext(NavTabsContext); useEffect(() => { @@ -60,24 +57,9 @@ const DxcTab = forwardRef( )} - + + {notificationNumber && !disabled && ( ` + display: inline; + color: ${(props) => + props.disabled + ? props.theme.disabledFontColor + : props.active + ? props.theme.selectedFontColor + : props.theme.unselectedFontColor}; + font-family: ${(props) => props.theme.fontFamily}; + font-size: ${(props) => props.theme.fontSize}; + font-style: ${(props) => props.theme.fontStyle}; + font-weight: ${(props) => props.theme.fontWeight}; + text-align: center; + letter-spacing: 0.025em; + line-height: 1.715em; + text-decoration: none; + text-overflow: unset; + white-space: normal; + margin: 0; +`; + const TabIconContainer = styled.div<{ iconPosition: NavTabsPropsType["iconPosition"]; active: TabProps["active"]; diff --git a/packages/lib/src/paragraph/Paragraph.tsx b/packages/lib/src/paragraph/Paragraph.tsx index 8a8066e1c8..dc811eeafa 100644 --- a/packages/lib/src/paragraph/Paragraph.tsx +++ b/packages/lib/src/paragraph/Paragraph.tsx @@ -1,20 +1,28 @@ +import styled, { ThemeProvider } from "styled-components"; import useTheme from "../useTheme"; -import BaseTypography from "../utils/BaseTypography"; -const DxcParagraph = ({ children }: { children: React.ReactNode }): JSX.Element => { +const Paragraph = styled.p` + display: ${(props) => props.theme.display}; + font-family: "Open Sans", sans-serif; + font-size: ${(props) => props.theme.fontSize}; + font-style: "normal"; + font-weight: ${(props) => props.theme.fontWeight}; + letter-spacing: 0em; + line-height: 1.5em; + text-align: "left"; + color: ${(props) => props.theme.fontColor}; + text-decoration: none; + text-overflow: unset; + white-space: normal; + margin: 0; +`; + +export default function DxcParagraph({ children }: { children: React.ReactNode }) { const colorsTheme = useTheme(); return ( - - {children} - + + {children} + ); -}; - -export default DxcParagraph; +} diff --git a/packages/lib/src/tabs/Tab.tsx b/packages/lib/src/tabs/Tab.tsx index a355e9565b..fb3fecd9b3 100644 --- a/packages/lib/src/tabs/Tab.tsx +++ b/packages/lib/src/tabs/Tab.tsx @@ -3,8 +3,6 @@ import styled from "styled-components"; import DxcBadge from "../badge/Badge"; import DxcIcon from "../icon/Icon"; import { Tooltip } from "../tooltip/Tooltip"; -import useTheme from "../useTheme"; -import BaseTypography from "../utils/BaseTypography"; import { TabsContext } from "./TabsContext"; import { TabProps, TabsContextProps } from "./types"; @@ -23,7 +21,7 @@ const DxcTab = forwardRef( ref: Ref ): JSX.Element => { const tabRef = useRef(); - const colorsTheme = useTheme(); + const { iconPosition, tabIndex, @@ -99,24 +97,9 @@ const DxcTab = forwardRef( {typeof icon === "string" ? : icon} )} - + + {notificationNumber && !disabled && ( @@ -228,6 +211,31 @@ const MainLabelContainer = styled.div<{ : "unset"}; `; +const Label = styled.span<{ + disabled: TabProps["disabled"]; + label: TabProps["label"]; + activeLabel: string; +}>` + display: inline; + color: ${(props) => + props.disabled + ? props.theme.disabledFontColor + : props.activeLabel === props.label + ? props.theme.selectedFontColor + : props.theme.unselectedFontColor}; + font-family: ${(props) => props.theme.fontFamily}; + font-size: ${(props) => props.theme.fontSize}; + font-style: ${(props) => (props.disabled ? props.theme.disabledFontStyle : props.theme.fontStyle)}; + font-weight: ${(props) => props.theme.fontWeight}; + text-align: center; + letter-spacing: 0.025em; + line-height: 1.715em; + text-decoration: none; + text-overflow: unset; + white-space: normal; + margin: 0; +`; + const TabIconContainer = styled.div<{ hasLabelAndIcon: boolean; iconPosition: TabsContextProps["iconPosition"]; diff --git a/packages/lib/src/tabs/TabLegacy.tsx b/packages/lib/src/tabs/TabLegacy.tsx index 11145bad5b..ec96d61392 100644 --- a/packages/lib/src/tabs/TabLegacy.tsx +++ b/packages/lib/src/tabs/TabLegacy.tsx @@ -2,79 +2,58 @@ import { forwardRef, memo } from "react"; import styled from "styled-components"; import DxcBadge from "../badge/Badge"; import DxcIcon from "../icon/Icon"; -import useTheme from "../useTheme"; -import BaseTypography from "../utils/BaseTypography"; import { TabPropsLegacy } from "./types"; const Tab = forwardRef( ( { active, tab, tabIndex, hasLabelAndIcon, iconPosition, onClick, onMouseEnter, onMouseLeave }: TabPropsLegacy, ref: React.Ref - ): JSX.Element => { - const colorsTheme = useTheme(); - - return ( - ( + { + onClick(); + }} + onMouseEnter={() => { + onMouseEnter(); + }} + onMouseLeave={() => { + onMouseLeave(); + }} + > + { - onClick(); - }} - onMouseEnter={() => { - onMouseEnter(); - }} - onMouseLeave={() => { - onMouseLeave(); - }} + disabled={tab.isDisabled} > - - {tab.icon && ( - - {typeof tab.icon === "string" ? : tab.icon} - - )} - - {tab.label} - - - {tab.notificationNumber && !tab.isDisabled && ( - - - + {tab.icon && ( + + {typeof tab.icon === "string" ? : tab.icon} + )} - - ); - } + + {tab.label} + + + {tab.notificationNumber && !tab.isDisabled && ( + + + + )} + + ) ); const TabContainer = styled.button<{ @@ -170,6 +149,30 @@ const MainLabelContainer = styled.div<{ : "unset"}; `; +const LabelContainer = styled.span<{ + disabled: TabPropsLegacy["tab"]["isDisabled"]; + active: TabPropsLegacy["active"]; +}>` + display: inline; + color: ${(props) => + props.disabled + ? props.theme.disabledFontColor + : props.active + ? props.theme.selectedFontColor + : props.theme.unselectedFontColor}; + font-family: ${(props) => props.theme.fontFamily}; + font-size: ${(props) => props.theme.fontSize}; + font-style: ${(props) => (props.disabled ? props.theme.disabledFontStyle : props.theme.fontStyle)}; + font-weight: ${(props) => (props.active ? props.theme.pressedFontWeight : props.theme.fontWeight)}; + text-align: center; + letter-spacing: 0.025em; + line-height: 1.715em; + text-decoration: none; + text-overflow: unset; + white-space: normal; + margin: 0; +`; + const TabIconContainer = styled.div<{ hasLabelAndIcon: TabPropsLegacy["hasLabelAndIcon"]; iconPosition: TabPropsLegacy["iconPosition"]; diff --git a/packages/lib/src/typography/Typography.test.tsx b/packages/lib/src/typography/Typography.test.tsx index 61e844dae5..d3574d737b 100644 --- a/packages/lib/src/typography/Typography.test.tsx +++ b/packages/lib/src/typography/Typography.test.tsx @@ -6,9 +6,4 @@ describe("Typography component tests", () => { const { container } = render(Test H1 Text); expect(container.querySelector("h1")).not.toBeNull(); }); - test("Renders as span if it receives invalid tag", () => { - const { container } = render(Test BR Text); - expect(container.querySelector("br")).toBeNull(); - expect(container.querySelector("span")).not.toBeNull(); - }); }); diff --git a/packages/lib/src/typography/Typography.tsx b/packages/lib/src/typography/Typography.tsx index 2d812b8ab1..3271ff698f 100644 --- a/packages/lib/src/typography/Typography.tsx +++ b/packages/lib/src/typography/Typography.tsx @@ -1,14 +1,81 @@ -import BaseTypography from "../utils/BaseTypography"; -import TypographyPropsTypes from "./types"; - -const DxcTypography = ({ textOverflow, whiteSpace, children, ...props }: TypographyPropsTypes): JSX.Element => ( - - {children} - -); - -export default DxcTypography; +import React, { useContext, useMemo } from "react"; +import styled from "styled-components"; +import TypographyPropsTypes, { TypographyContextProps } from "./types"; + +const Typography = styled.span` + margin: 0px; + display: ${({ display }) => display}; + color: ${({ color }) => color}; + font-family: ${({ fontFamily }) => fontFamily}; + font-size: ${({ fontSize }) => fontSize}; + font-style: ${({ fontStyle }) => fontStyle}; + font-weight: ${({ fontWeight }) => fontWeight}; + letter-spacing: ${({ letterSpacing }) => letterSpacing}; + text-align: ${({ textAlign }) => textAlign}; + line-height: ${({ lineHeight }) => lineHeight}; + text-decoration: ${({ textDecoration }) => textDecoration}; + text-overflow: ${({ textOverflow }) => textOverflow}; + white-space: ${({ whiteSpace, textOverflow }) => + whiteSpace !== "normal" ? whiteSpace : textOverflow !== "unset" ? "nowrap" : "normal"}; + overflow: ${({ textOverflow }) => (textOverflow !== "unset" ? "hidden" : "visible")}; +`; + +const TypographyContext = React.createContext(null); + +export default function DxcTypography({ + as, + color, + children, + display, + fontFamily, + fontSize, + fontStyle, + fontWeight, + letterSpacing, + lineHeight, + textAlign, + textDecoration, + textOverflow, + whiteSpace, +}: TypographyPropsTypes) { + const componentContext = useContext(TypographyContext); + + const contextValue = useMemo( + () => ({ + as: as ?? componentContext?.as ?? "span", + display: display ?? componentContext?.display ?? "inline", + fontFamily: fontFamily ?? componentContext?.fontFamily ?? "Open Sans, sans-serif", + fontSize: fontSize ?? componentContext?.fontSize ?? "1rem", + fontStyle: fontStyle ?? componentContext?.fontStyle ?? "normal", + fontWeight: fontWeight ?? componentContext?.fontWeight ?? "400", + letterSpacing: letterSpacing ?? componentContext?.letterSpacing ?? "0em", + lineHeight: lineHeight ?? componentContext?.lineHeight ?? "1.5em", + textAlign: textAlign ?? componentContext?.textAlign ?? "left", + color: color ?? componentContext?.color ?? "#000000", + textDecoration: textDecoration ?? componentContext?.textDecoration ?? "none", + textOverflow: textOverflow ?? componentContext?.textOverflow ?? "unset", + whiteSpace: whiteSpace ?? componentContext?.whiteSpace ?? "normal", + }), + [ + as, + color, + display, + fontFamily, + fontSize, + fontStyle, + fontWeight, + letterSpacing, + lineHeight, + textAlign, + textDecoration, + textOverflow, + whiteSpace, + ] + ); + + return ( + + {children} + + ); +} diff --git a/packages/lib/src/typography/types.ts b/packages/lib/src/typography/types.ts index b9e25fcce6..ca542e3f63 100644 --- a/packages/lib/src/typography/types.ts +++ b/packages/lib/src/typography/types.ts @@ -1,5 +1,7 @@ -type Props = { - as?: keyof HTMLElementTagNameMap; +export type Props = { + as?: "a" | "blockquote" | "cite" | "code" | "div" | "em" | "figcaption" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "pre" | "small" | "span" | "strong"; + children: React.ReactNode; + color?: string; display?: "inline" | "block"; fontFamily?: "Open Sans, sans-serif" | "Source Code Pro, monospace"; fontSize?: "0.75rem" | "0.875rem" | "1rem" | "1.25rem" | "1.5rem" | "2rem" | "3rem" | "3.75rem"; @@ -8,11 +10,11 @@ type Props = { letterSpacing?: "-0.025em" | "-0.0125em" | "0em" | "0.025em" | "0.05em" | "0.1em"; lineHeight?: "1em" | "1.25em" | "1.365em" | "1.5em" | "1.715em" | "2em"; textAlign?: "left" | "center" | "right"; - color?: string; textDecoration?: "none" | "underline" | "line-through"; textOverflow?: "clip" | "ellipsis" | "unset"; whiteSpace?: "normal" | "nowrap" | "pre" | "pre-line" | "pre-wrap"; - children: React.ReactNode; }; export default Props; + +export type TypographyContextProps = Omit; diff --git a/packages/lib/src/utils/BaseTypography.tsx b/packages/lib/src/utils/BaseTypography.tsx deleted file mode 100644 index 9671e979d3..0000000000 --- a/packages/lib/src/utils/BaseTypography.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import { createContext, useContext, useMemo } from "react"; -import styled from "styled-components"; - -type TypographyContextProps = { - as?: keyof HTMLElementTagNameMap; - display?: string; - fontFamily?: string; - fontSize?: string; - fontStyle?: string; - fontWeight?: string; - letterSpacing?: string; - lineHeight?: string; - textAlign?: string; - color?: string; - textDecoration?: string; - textOverflow?: string; - whiteSpace?: string; -}; - -const TypographyContext = createContext(null); - -type BaseTypographyProps = TypographyContextProps & { - children: React.ReactNode; -}; - -const ValidTypographyTags = [ - "a", - "blockquote", - "cite", - "code", - "div", - "em", - "figcaption", - "h1", - "h2", - "h3", - "h4", - "h5", - "h6", - "p", - "pre", - "small", - "span", - "strong", -]; - -const isValidTypography = (tag: keyof HTMLElementTagNameMap) => { - return ValidTypographyTags.includes(tag); -}; - -const BaseTypography = ({ - as, - display, - fontFamily, - fontSize, - fontStyle, - fontWeight, - letterSpacing, - lineHeight, - textAlign, - color, - textDecoration, - textOverflow, - whiteSpace, - children, -}: BaseTypographyProps): JSX.Element => { - const componentContext = useContext(TypographyContext); - const contextValue = useMemo( - () => ({ - as: isValidTypography(as) ? as : isValidTypography(componentContext?.as) ? componentContext?.as : "span", - display: display ?? componentContext?.display ?? "inline", - fontFamily: fontFamily ?? componentContext?.fontFamily ?? "Open Sans, sans-serif", - fontSize: fontSize ?? componentContext?.fontSize ?? "1rem", - fontStyle: fontStyle ?? componentContext?.fontStyle ?? "normal", - fontWeight: fontWeight ?? componentContext?.fontWeight ?? "400", - letterSpacing: letterSpacing ?? componentContext?.letterSpacing ?? "0em", - lineHeight: lineHeight ?? componentContext?.lineHeight ?? "1.5em", - textAlign: textAlign ?? componentContext?.textAlign ?? "left", - color: color ?? componentContext?.color ?? "#000000", - textDecoration: textDecoration ?? componentContext?.textDecoration ?? "none", - textOverflow: textOverflow ?? componentContext?.textOverflow ?? "unset", - whiteSpace: whiteSpace ?? componentContext?.whiteSpace ?? "normal", - }), - [ - as, - display, - fontFamily, - fontSize, - fontStyle, - fontWeight, - letterSpacing, - lineHeight, - textAlign, - color, - textDecoration, - textOverflow, - whiteSpace, - ] - ); - - return ( - - {children} - - ); -}; - -const StyledTypography = styled.span` - display: ${({ display }) => display}; - color: ${({ color }) => color}; - font-family: ${({ fontFamily }) => fontFamily}; - font-size: ${({ fontSize }) => fontSize}; - font-style: ${({ fontStyle }) => fontStyle}; - font-weight: ${({ fontWeight }) => fontWeight}; - letter-spacing: ${({ letterSpacing }) => letterSpacing}; - line-height: ${({ lineHeight }) => lineHeight}; - text-align: ${({ textAlign }) => textAlign}; - text-decoration: ${({ textDecoration }) => textDecoration}; - text-overflow: ${({ textOverflow }) => textOverflow}; - white-space: ${({ whiteSpace }) => whiteSpace}; - overflow: ${({ textOverflow }) => (textOverflow !== "unset" ? "hidden" : "visible")}; - margin: 0; -`; - -export default BaseTypography;