Skip to content

Commit

Permalink
Merge pull request #7023 from Sage/FE-6780-inline-switch
Browse files Browse the repository at this point in the history
feat(switch): enhances Switch component to allow inline variant in new validation redesign
  • Loading branch information
damienrobson-sage authored Nov 7, 2024
2 parents be6d9f1 + 7b9bb7e commit 8ae08ac
Show file tree
Hide file tree
Showing 17 changed files with 663 additions and 75 deletions.
8 changes: 6 additions & 2 deletions src/__internal__/checkable-input/checkable-input.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import styled, { css } from "styled-components";

import FieldHelpStyle from "../field-help/field-help.style";
import { FieldLineStyle } from "../form-field/form-field.style";
import HiddenCheckableInputStyle from "./hidden-checkable-input.style";
import LabelStyle, { StyledLabelContainer } from "../label/label.style";
import StyledHelp from "../../components/help/help.style";
import StyledValidationIcon from "../validations/validation-icon.style";
import StyledHelp from "../../components/help/help.style";

import HiddenCheckableInputStyle from "./hidden-checkable-input.style";

const StyledCheckableInput = styled.div`
display: inline-block;
Expand All @@ -30,6 +31,8 @@ const StyledCheckableInputWrapper = styled.div<StyledCheckableInputWrapperProps>
labelInline,
reverse,
}) => css`
width: 100% !important;
${FieldLineStyle} {
display: flex;
}
Expand Down Expand Up @@ -105,6 +108,7 @@ const StyledCheckableInputWrapper = styled.div<StyledCheckableInputWrapperProps>
css`
${StyledCheckableInput} {
width: ${inputWidth}% !important;
min-width: 67px;
}
`}
Expand Down
4 changes: 4 additions & 0 deletions src/__internal__/label/label.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export interface LabelProps
className?: string;
/** Sets aria-label for label element */
"aria-label"?: string;
/** Whether this component is shown against a dark background */
isDarkBackground?: boolean;
}

const shouldDisplayValidationIcon = ({
Expand Down Expand Up @@ -70,6 +72,7 @@ export const Label = ({
htmlFor,
info,
inline,
isDarkBackground = false,
isRequired,
labelId,
optional,
Expand Down Expand Up @@ -165,6 +168,7 @@ export const Label = ({
isRequired={isRequired}
as={as}
aria-label={ariaLabel}
isDarkBackground={isDarkBackground}
>
{children}
</StyledLabel>
Expand Down
8 changes: 7 additions & 1 deletion src/__internal__/label/label.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@ export interface StyledLabelProps {
disabled?: boolean;
/** Flag to configure component as mandatory */
isRequired?: boolean;
/** Flag to determine whether to use colours for dark backgrounds */
isDarkBackground?: boolean;
}

const StyledLabel = styled.label<StyledLabelProps>`
color: var(--colorsUtilityYin090);
${({ isDarkBackground }) => css`
color: ${isDarkBackground
? "var(--colorsUtilityYang100)"
: "var(--colorsUtilityYin090)"};
`}
display: block;
font-weight: var(--fontWeights500);
Expand Down
18 changes: 18 additions & 0 deletions src/__internal__/label/label.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,21 @@ test("renders with expected styles when `inline` is true and `align` is 'left'",
justifyContent: "flex-start",
});
});

// coverage
test("renders with dark background styles when `isDarkBackground` is true", () => {
render(<Label isDarkBackground>foo</Label>);

expect(screen.getByTestId("label-container").childNodes[0]).toHaveStyle({
color: "var(--colorsUtilityYang100)",
});
});

// coverage
test("renders with normal styles when `isDarkBackground` is false", () => {
render(<Label isDarkBackground={false}>foo</Label>);

expect(screen.getByTestId("label-container").childNodes[0]).toHaveStyle({
color: "var(--colorsUtilityYin090)",
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ export interface ValidationMessageProps {
/** Indicate that warning has occurred
Pass string to display hint with warning */
warning?: boolean | string;
/** Whether this component resides on a dark background */
isDarkBackground?: boolean;
}

const ValidationMessage = ({
error,
validationId,
warning,
isDarkBackground,
}: ValidationMessageProps) => {
const validation = error || warning;
const isStringValidation = typeof validation === "string";
Expand All @@ -25,6 +28,7 @@ const ValidationMessage = ({
id={validationId}
isWarning={!!(!error && warning)}
data-role="validation-message"
isDarkBackground={isDarkBackground}
>
{validation}
</StyledValidationMessage>
Expand Down
20 changes: 12 additions & 8 deletions src/__internal__/validation-message/validation-message.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@ import styled, { css } from "styled-components";

interface StyledValidationMessageProps {
isWarning?: boolean;
isDarkBackground?: boolean;
}

const StyledValidationMessage = styled.p<StyledValidationMessageProps>`
${({ isWarning }) => css`
color: ${isWarning
? "var(--colorsSemanticCaution600)"
: "var(--colorsSemanticNegative500)"};
font-weight: ${isWarning ? "normal" : "500"};
margin-top: 0px;
margin-bottom: 8px;
`}
${({ isWarning, isDarkBackground }) => {
const darkBgColour = isDarkBackground
? "var(--colorsSemanticNegative450)"
: "var(--colorsSemanticNegative500)";
return css`
color: ${isWarning ? "var(--colorsSemanticCaution600)" : darkBgColour};
font-weight: ${isWarning ? "normal" : "500"};
margin-top: 0px;
margin-bottom: 8px;
`;
}}
`;

export default StyledValidationMessage;
18 changes: 18 additions & 0 deletions src/__internal__/validation-message/validation-message.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,21 @@ test("sets the 'id' attribute to the value of the `validationId` prop", () => {
const validationMessage = screen.getByTestId("validation-message");
expect(validationMessage).toHaveAttribute("id", "foo");
});

// coverage
test("renders with the correct colour when `isDarkBackground` is true", () => {
render(<ValidationMessage error="error" isDarkBackground />);

expect(screen.getByTestId("validation-message")).toHaveStyle({
color: "var(--colorsSemanticNegative450)",
});
});

// coverage
test("renders with the correct colour when `isDarkBackground` is false", () => {
render(<ValidationMessage error="error" isDarkBackground={false} />);

expect(screen.getByTestId("validation-message")).toHaveStyle({
color: "var(--colorsSemanticNegative500)",
});
});
18 changes: 13 additions & 5 deletions src/components/switch/__internal__/switch-slider-panel.style.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,37 @@
import styled, { css } from "styled-components";

import StyledLoader from "../../loader/loader.style";
import StyledLoaderSquare from "../../loader/loader-square.style";
import { SwitchProps } from "../switch.component";
import StyledLoaderSquare from "../../loader/loader-square.style";
import StyledLoader from "../../loader/loader.style";

export interface SwitchSliderPanelProps {
isLoading?: boolean;
size?: SwitchProps["size"];
isDarkBackground?: boolean;
}

const SwitchSliderPanel = styled.div`
${({ isLoading, size }: SwitchSliderPanelProps) => css`
${({ isLoading, size, isDarkBackground }: SwitchSliderPanelProps) => css`
border: 0;
color: var(--colorsActionMinorYang100);
color: ${isDarkBackground
? "var(--colorsUtilityYin100)"
: "var(--colorsActionMinorYang100)"};
margin: auto;
position: absolute;
left: 0;
&[type="on"] {
color: ${isDarkBackground
? "var(--colorsUtilityYin100)"
: "var(--colorsUtilityYang100)"};
margin-left: 9px;
padding-right: ${size === "large" ? "43px" : "27px"};
}
&[type="off"] {
color: var(--colorsActionMinor500);
color: ${isDarkBackground
? "var(--colorsUtilityYang100)"
: "var(--colorsActionMinor500)"};
margin-right: 9px;
padding-left: ${size === "large" ? "43px" : "27px"};
}
Expand Down
18 changes: 18 additions & 0 deletions src/components/switch/__internal__/switch-slider-panel.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,21 @@ describe("when the theme is set to sageTheme", () => {
);
});
});

// coverage
test("renders with normal styles when `isDarkBackground` is false", () => {
render(<Switch onChange={() => {}} isDarkBackground={false} />);

const switchPanel = screen.getByTestId("slider-panel");

expect(switchPanel).toHaveStyleRule("color: var(--colorsActionMinorYang100)");
});

// coverage
test("renders with dark background styles when `isDarkBackground` is true", () => {
render(<Switch onChange={() => {}} isDarkBackground />);

const switchPanel = screen.getByTestId("slider-panel");

expect(switchPanel).toHaveStyleRule("color: var(--colorsUtilityYin100)");
});
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface SwitchSliderProps extends ValidationProps {
loading?: boolean;
size?: "small" | "large";
useValidationIcon?: boolean;
isDarkBackground?: boolean;
}

const SwitchSlider = ({
Expand All @@ -24,6 +25,7 @@ const SwitchSlider = ({
warning,
info,
useValidationIcon,
isDarkBackground,
}: SwitchSliderProps) => {
const locale = useLocale();
const onText = locale.switch.on();
Expand All @@ -45,13 +47,15 @@ const SwitchSlider = ({
error,
warning,
info,
isDarkBackground,
};

const sliderPanelStyleProps = {
isLoading: loading,
size,
type: checked ? "on" : "off",
disabled,
isDarkBackground,
};

const loaderProps = {
Expand Down
27 changes: 21 additions & 6 deletions src/components/switch/__internal__/switch-slider.style.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import styled, { css } from "styled-components";

import SwitchSliderPanel from "./switch-slider-panel.style";
import StyledValidationIcon from "../../../__internal__/validations/validation-icon.style";
import { SwitchSliderProps } from "./switch-slider.component";
import baseTheme, { ThemeObject } from "../../../style/themes/base";

import SwitchSliderPanel from "./switch-slider-panel.style";
import { SwitchSliderProps } from "./switch-slider.component";

interface StyledSwitchSliderProps
extends Pick<
SwitchSliderProps,
"checked" | "disabled" | "size" | "error" | "warning"
> {
isLoading?: boolean;
theme?: Partial<ThemeObject>;
isDarkBackground?: boolean;
}

const StyledSwitchSlider = styled.div`
Expand All @@ -23,6 +25,7 @@ const StyledSwitchSlider = styled.div`
error,
warning,
theme,
isDarkBackground,
}: StyledSwitchSliderProps) => css`
display: flex;
font-size: 12px;
Expand All @@ -39,14 +42,22 @@ const StyledSwitchSlider = styled.div`
theme?.roundedCornersOptOut ? "90px" : "var(--borderRadius400)"
};
border-style: solid;
border-color: var(--colorsActionMinor400);
border-color: ${
isDarkBackground
? "var(--colorsUtilityYang100)"
: "var(--colorsActionMinor400)"
};
border-width: var(--borderWidth200);
box-sizing: border-box;
margin-top: ${size === "large" ? "-47px" : "-28px"};
align-items: center;
&::before {
background-color: var(--colorsActionMinor400);
background-color: ${
isDarkBackground
? "var(--colorsUtilityYang100)"
: "var(--colorsActionMinor400)"
};
bottom: 4px;
content: "";
height: ${size === "large" ? "var(--spacing400)" : "var(--spacing200)"};
Expand All @@ -61,15 +72,19 @@ const StyledSwitchSlider = styled.div`
${
checked &&
css`
background-color: var(--colorsActionMinor500);
background-color: ${isDarkBackground
? "var(--colorsUtilityYang100)"
: "var(--colorsActionMinor500)"};
border-color: var(--colorsActionMinorTransparent);
&::before {
margin-left: calc(
100% -
${size === "large" ? "var(--spacing500)" : "var(--spacing300)"}
);
background-color: var(--colorsActionMinorYang100);
background-color: ${isDarkBackground
? "var(--colorsUtilityYin100)"
: "var(--colorsActionMinorYang100)"};
}
`
}
Expand Down
27 changes: 27 additions & 0 deletions src/components/switch/__internal__/switch-slider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,30 @@ test("when `size` is large and the consumer has opted out of rounded corners sty

expect(switchPanel).toHaveStyle("border-radius: 30px");
});

// coverage
test("renders with normal styles when `isDarkBackground` is false", () => {
render(<SwitchSlider isDarkBackground={false} />);

const switchPanel = screen.getByTestId("slider");

expect(switchPanel).toHaveStyleRule("color: var(--colorsActionMinorYang100)");
});

// coverage
test("renders with dark background styles when `isDarkBackground` is true", () => {
render(<SwitchSlider isDarkBackground />);

const switchPanel = screen.getByTestId("slider");

expect(switchPanel).toHaveStyleRule("color: var(--colorsUtilityYin100)");
});

// coverage
test("renders with dark background styles when `isDarkBackground` is true and checked is true", () => {
render(<SwitchSlider isDarkBackground checked />);

const switchPanel = screen.getByTestId("slider");

expect(switchPanel).toHaveStyleRule("color: var(--colorsUtilityYang100)");
});
Loading

0 comments on commit 8ae08ac

Please sign in to comment.