Skip to content

Commit

Permalink
fix(tabs): support for post-rebrand validation pattern
Browse files Browse the repository at this point in the history
added the necessary changes to support the new validation design update
  • Loading branch information
mihai-albu-sage committed Oct 29, 2024
1 parent 5c0ce5f commit 8ea011b
Show file tree
Hide file tree
Showing 6 changed files with 600 additions and 23 deletions.
57 changes: 48 additions & 9 deletions src/components/tabs/__internal__/tab-title/tab-title.component.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import React, { useRef, useState } from "react";
import React, { useRef, useState, useContext } from "react";
import {
StyledTabTitleButton,
StyledTabTitleLink,
StyledTitleContent,
StyledLayoutWrapper,
StyledSelectedIndicator,
StyledVerticalIndicator,
} from "./tab-title.style";
import tagComponent from "../../../../__internal__/utils/helpers/tags/tags";
import ValidationIcon from "../../../../__internal__/validations/validation-icon.component";
import Icon from "../../../icon";
import Events from "../../../../__internal__/utils/helpers/events";
import { TooltipProvider } from "../../../../__internal__/tooltip-provider";
import TabTitleContext from "./tab-title.context";
import Typography from "../../../typography";
import NewValidationContext from "../../../carbon-provider/__internal__/new-validation.context";

export interface TabTitleProps {
/** Identifier used for testing purposes */
Expand Down Expand Up @@ -77,6 +80,7 @@ const TabTitle = React.forwardRef(
onKeyDown,
align,
tabIndex,
id,
...tabTitleProps
}: TabTitleProps,
ref: React.ForwardedRef<HTMLElement>
Expand All @@ -86,6 +90,7 @@ const TabTitle = React.forwardRef(
const hasFailedValidation = error || warning || info;
const [shouldShowTooltip, setShouldShowTooltip] = useState(false);
const hasHover = useRef(false);
const { validationRedesignOptIn } = useContext(NewValidationContext);

const showTooltip = () => {
setShouldShowTooltip(true);
Expand Down Expand Up @@ -142,6 +147,11 @@ const TabTitle = React.forwardRef(
return (
<StyledLayoutWrapper hasCustomLayout>
{customLayout}
{validationRedesignOptIn && hasFailedValidation && (
<Typography screenReaderOnly id={`${id}-message`}>
{errorMessage || warningMessage}
</Typography>
)}
</StyledLayoutWrapper>
);
}
Expand All @@ -164,6 +174,11 @@ const TabTitle = React.forwardRef(
onClick: handleClick,
});
})}
{validationRedesignOptIn && hasFailedValidation && (
<Typography screenReaderOnly id={`${id}-message`}>
{errorMessage || warningMessage}
</Typography>
)}
</StyledLayoutWrapper>
);

Expand All @@ -190,6 +205,7 @@ const TabTitle = React.forwardRef(
alternateStyling={hasAlternateStyling}
align={align}
hasHref={!!href}
validationRedesignOptIn={validationRedesignOptIn}
>
{renderContent()}
{isHref && <Icon type="link" />}
Expand All @@ -198,6 +214,7 @@ const TabTitle = React.forwardRef(
<StyledLayoutWrapper
position={position}
hasCustomSibling={!!customLayout}
validationRedesignOptIn={validationRedesignOptIn}
>
{error && (
<ValidationIcon tooltipPosition="top" error={errorMessage} />
Expand All @@ -213,16 +230,28 @@ const TabTitle = React.forwardRef(
{!warning && !error && info && (
<ValidationIcon tooltipPosition="top" info={infoMessage} />
)}
{validationRedesignOptIn && hasFailedValidation && (
<Typography screenReaderOnly id={`${id}-message`}>
{errorMessage || warningMessage}
</Typography>
)}
</StyledLayoutWrapper>
)}
</StyledTitleContent>
{!(hasFailedValidation || hasAlternateStyling) && isTabSelected && (
<StyledSelectedIndicator
data-element="tab-selected-indicator"
data-role="tab-selected-indicator"
position={position}
/>
{validationRedesignOptIn && position === "left" && (
<StyledVerticalIndicator />
)}
{(!(hasFailedValidation || hasAlternateStyling) ||
validationRedesignOptIn) &&
isTabSelected && (
<StyledSelectedIndicator
warning={warning}
error={error}
data-element="tab-selected-indicator"
data-role="tab-selected-indicator"
position={position}
/>
)}
</>
);

Expand All @@ -243,8 +272,9 @@ const TabTitle = React.forwardRef(
borders,
isInSidebar,
tabIndex,
id,
...tabTitleProps,
...tagComponent("tab-header", tabTitleProps),
...tagComponent("tab-header", { id, ...tabTitleProps }),
onKeyDown: handleKeyDown,
onClick: handleClick,
size,
Expand All @@ -258,6 +288,13 @@ const TabTitle = React.forwardRef(
},
onFocus: showTooltip,
onBlur: hideTooltip,
...(validationRedesignOptIn &&
hasFailedValidation && {
"aria-invalid": true,
"aria-errormessage": `${id}-message`,
"aria-describedby": `${id}-message`,
}),
validationRedesignOptIn,
};

const tabTitle = isHref ? (
Expand All @@ -280,7 +317,9 @@ const TabTitle = React.forwardRef(
);

return (
<TooltipProvider tooltipVisible={shouldShowTooltip}>
<TooltipProvider
tooltipVisible={validationRedesignOptIn ? false : shouldShowTooltip}
>
<TabTitleContext.Provider value={{ isInTab: true }}>
{tabTitle}
</TabTitleContext.Provider>
Expand Down
90 changes: 79 additions & 11 deletions src/components/tabs/__internal__/tab-title/tab-title.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ interface StyledTitleContentProps
hasCustomLayout?: boolean;
hasHref?: boolean;
hasSiblings?: boolean;
validationRedesignOptIn?: boolean;
}

const oldFocusStyling = `
Expand Down Expand Up @@ -51,6 +52,7 @@ const StyledTitleContent = styled.span<StyledTitleContentProps>`
hasHref,
alternateStyling,
align,
validationRedesignOptIn,
}) => css`
text-align: ${align};
Expand All @@ -65,6 +67,12 @@ const StyledTitleContent = styled.span<StyledTitleContentProps>`
border-top-right-radius: var(--borderRadius000);
`}
${position === "left" &&
validationRedesignOptIn &&
css`
justify-content: space-between;
`}
${position === "top" &&
css`
border-top-left-radius: var(--borderRadius100);
Expand Down Expand Up @@ -149,7 +157,7 @@ const StyledTitleContent = styled.span<StyledTitleContentProps>`
css`
outline: 1px solid;
outline-offset: -1px;
z-index: 2;
z-index: ${validationRedesignOptIn ? 1 : 2};
${info &&
!warning &&
Expand Down Expand Up @@ -210,7 +218,7 @@ const StyledTitleContent = styled.span<StyledTitleContentProps>`
css`
outline: 2px solid var(--colorsSemanticNegative500);
outline-offset: -2px;
z-index: 2;
z-index: ${validationRedesignOptIn ? 1 : 2};
${position === "top" &&
css`
Expand Down Expand Up @@ -289,7 +297,9 @@ const StyledTitleContent = styled.span<StyledTitleContentProps>`
`}
`;

const tabTitleStyles = css<TabTitleProps>`
const tabTitleStyles = css<
TabTitleProps & { validationRedesignOptIn?: boolean }
>`
background-color: transparent;
display: inline-block;
border-top-left-radius: var(--borderRadius100);
Expand Down Expand Up @@ -328,6 +338,7 @@ const tabTitleStyles = css<TabTitleProps>`
warning,
info,
isInSidebar,
validationRedesignOptIn,
}) => css`
height: ${size === "large" ? "var(--sizing600)" : "var(--sizing500)"};
Expand Down Expand Up @@ -360,9 +371,17 @@ const tabTitleStyles = css<TabTitleProps>`
${!isTabSelected &&
css`
color: var(--colorsActionMinorYin090);
${validationRedesignOptIn &&
css`
background: transparent;
`}
&:hover {
background: var(--colorsActionMinor100);
${validationRedesignOptIn &&
css`
background: var(--colorsUtilityMajor100);
`}
color: var(--colorsActionMinorYin090);
outline: none;
}
Expand Down Expand Up @@ -415,7 +434,11 @@ const tabTitleStyles = css<TabTitleProps>`
${!isInSidebar &&
!error &&
css`
border-right: ${alternateStyling ? "1px" : "2px"} solid
--border-right-value: ${validationRedesignOptIn ? "0px" : "2px"}
border-right: ${
alternateStyling ? "1px" : "var(--border-right-value)"
} solid
var(--colorsActionMinor100);
`}
Expand Down Expand Up @@ -443,6 +466,11 @@ const tabTitleStyles = css<TabTitleProps>`
border-right: none;
`}
${!isTabSelected &&
css`
border-right-color: var(--colorsActionMinor100);
`}
${isTabSelected &&
css`
${alternateStyling &&
Expand All @@ -456,7 +484,9 @@ const tabTitleStyles = css<TabTitleProps>`
padding-bottom: 0px;
${StyledTitleContent} {
${!(error || warning || info) && "margin-right: 2px;"}
${!(error || warning || info) &&
!validationRedesignOptIn &&
"margin-right: 2px;"}
border-right: none;
}
`}
Expand Down Expand Up @@ -510,6 +540,7 @@ interface StyledLayoutWrapperProps
extends Pick<TabTitleProps, "titlePosition" | "position"> {
hasCustomLayout?: boolean;
hasCustomSibling?: boolean;
validationRedesignOptIn?: boolean;
}

const StyledLayoutWrapper = styled.div<StyledLayoutWrapperProps>`
Expand All @@ -518,6 +549,7 @@ const StyledLayoutWrapper = styled.div<StyledLayoutWrapperProps>`
titlePosition = "before",
hasCustomSibling,
position,
validationRedesignOptIn,
}) => css`
${hasCustomLayout &&
css`
Expand Down Expand Up @@ -547,29 +579,64 @@ const StyledLayoutWrapper = styled.div<StyledLayoutWrapperProps>`
z-index: 10;
${StyledIcon} {
height: 16px;
--top-position-value: ${validationRedesignOptIn ? "6px" : "3px"};
height: ${validationRedesignOptIn ? "8px" : "16px"};
left: -2px;
top: ${position === "left" ? "1px" : "3px"};
top: ${position === "left" ? "1px" : "var(--top-position-value)"};
}
}
`}
`}
`;

type StyledSelectedIndicatorProps = Pick<TabTitleProps, "position">;
const StyledVerticalIndicator = styled.div`
position: absolute;
top: 0px;
bottom: 0px;
right: 0px;
box-shadow: inset calc(-1 * var(--sizing050)) 0px 0px 0px
var(--colorsActionMinor100);
width: 2px;
z-index: 1;
`;

type StyledSelectedIndicatorProps = Pick<
TabTitleProps,
"position" | "error" | "warning"
> & {
validationRedesignOptIn?: boolean;
};

const StyledSelectedIndicator = styled.div<StyledSelectedIndicatorProps>`
position: absolute;
z-index: 1;
${(validationRedesignOptIn) => css`
${validationRedesignOptIn &&
css`
z-index: 3;
`}
`}
${({ position = "top" }) => css`
${({ position = "top", warning, error }) => css`
--selected-indicator-color: var(--colorsActionMajor500);
${warning &&
css`
--selected-indicator-color: var(--colorsSemanticCaution500);
`}
${error &&
css`
--selected-indicator-color: var(--colorsSemanticNegative500);
`}
${position === "top" &&
css`
bottom: 0px;
left: 0px;
right: 0px;
box-shadow: inset 0px calc(-1 * var(--sizing050)) 0px
var(--colorsActionMajor500);
var(--selected-indicator-color);
height: var(--sizing050);
`}
Expand All @@ -579,7 +646,7 @@ const StyledSelectedIndicator = styled.div<StyledSelectedIndicatorProps>`
bottom: 0px;
right: 0px;
box-shadow: inset calc(-1 * var(--sizing050)) 0px 0px 0px
var(--colorsActionMajor500);
var(--selected-indicator-color);
width: var(--sizing050);
`}
`}
Expand All @@ -591,4 +658,5 @@ export {
StyledTitleContent,
StyledLayoutWrapper,
StyledSelectedIndicator,
StyledVerticalIndicator,
};
Loading

0 comments on commit 8ea011b

Please sign in to comment.