Skip to content

Commit

Permalink
Merge pull request #6445 from Sage/FE-6228_the-toast-and-message-divorce
Browse files Browse the repository at this point in the history
refactor(toast): Decouple Toast component from Message component - FE-6228
  • Loading branch information
DipperTheDan authored Dec 7, 2023
2 parents 9a4b95a + 311a301 commit 0bd4a42
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,6 @@ const MessageContentStyle = styled.div<
20px;
white-space: pre-wrap;
flex: 1;
.carbon-content__title {
margin-bottom: 2px;
}
.carbon-content__body {
margin-top: 0px;
}
`;

export default MessageContentStyle;
14 changes: 7 additions & 7 deletions src/components/toast/toast.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { TransitionGroup, CSSTransition } from "react-transition-group";
import Icon from "../icon";
import tagComponent from "../../__internal__/utils/helpers/tags/tags";
import {
ToastStyle,
StyledToast,
TypeIcon,
ToastContentStyle,
StyledToastContent,
ToastWrapper,
StyledPortal,
} from "./toast.style";
Expand Down Expand Up @@ -202,7 +202,7 @@ export const Toast = React.forwardRef<HTMLDivElement, ToastProps>(
function renderToastContent() {
if (!open) return null;

let toastVariant;
let toastVariant: ToastVariants = "success";

if (!isNotice && !isNotification) {
toastVariant = variant;
Expand All @@ -215,7 +215,7 @@ export const Toast = React.forwardRef<HTMLDivElement, ToastProps>(
timeout={{ appear: 1600, enter: 1500, exit: 500 }}
nodeRef={toastContentNodeRef}
>
<ToastStyle
<StyledToast
align={align}
alignY={alignY}
isNotice={isNotice}
Expand All @@ -237,11 +237,11 @@ export const Toast = React.forwardRef<HTMLDivElement, ToastProps>(
<Icon type={toastIcon} />
</TypeIcon>
)}
<ToastContentStyle isNotice={isNotice} isDismiss={!!onDismiss}>
<StyledToastContent isNotice={isNotice} isDismiss={!!onDismiss}>
{children}
</ToastContentStyle>
</StyledToastContent>
{renderCloseIcon()}
</ToastStyle>
</StyledToast>
</CSSTransition>
);
}
Expand Down
34 changes: 17 additions & 17 deletions src/components/toast/toast.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import Logger from "../../__internal__/utils/logger";
import guid from "../../__internal__/utils/helpers/guid";
import Toast, { ToastProps } from "./toast.component";
import {
ToastStyle,
ToastContentStyle,
StyledToast,
StyledToastContent,
ToastWrapper,
StyledPortal,
TypeIcon,
Expand Down Expand Up @@ -205,14 +205,14 @@ describe("Toast", () => {
});

it("auto focuses the toast component", () => {
const toast = wrapper.find(ToastStyle);
const toast = wrapper.find(StyledToast);
jest.runAllTimers();

expect(toast).toBeFocused();
});

it("sets a tabIndex on the toast component and removes onBlur", () => {
const toast = wrapper.find(ToastStyle);
const toast = wrapper.find(StyledToast);

expect(toast.getDOMNode().hasAttribute("tabIndex")).toBe(true);

Expand Down Expand Up @@ -325,7 +325,7 @@ describe("Toast", () => {
Child
</Toast>
);
const toast = wrapper.find(ToastStyle);
const toast = wrapper.find(StyledToast);
expect(toast.getDOMNode().hasAttribute("tabIndex")).toBe(false);
jest.runAllTimers();
expect(toast).not.toBeFocused();
Expand Down Expand Up @@ -401,9 +401,9 @@ describe("Toast", () => {
wrapper.unmount();
});

it("should render ToastStyle with correct maxWidth", () => {
it("should render StyledToast with correct maxWidth", () => {
wrapper = mount(<Toast maxWidth="200px">Child</Toast>);
assertStyleMatch({ maxWidth: "200px" }, wrapper.find(ToastStyle));
assertStyleMatch({ maxWidth: "200px" }, wrapper.find(StyledToast));
});
});

Expand All @@ -419,8 +419,8 @@ describe("Toast", () => {
);
});

it("then the prop should be passed to ToastStyle", () => {
expect(wrapper.find(ToastStyle).props().isNotice).toBe(true);
it("then the prop should be passed to StyledToast", () => {
expect(wrapper.find(StyledToast).props().isNotice).toBe(true);
});

it("then the prop should be passed to StyledPortal", () => {
Expand All @@ -431,8 +431,8 @@ describe("Toast", () => {
expect(wrapper.find(ToastWrapper).props().isNotice).toBe(true);
});

it("then the prop should be passed to ToastContentStyle", () => {
expect(wrapper.find(ToastContentStyle).props().isNotice).toBe(true);
it("then the prop should be passed to StyledToastContent", () => {
expect(wrapper.find(StyledToastContent).props().isNotice).toBe(true);
});

it("then the TypeIcon should not be rendered", () => {
Expand Down Expand Up @@ -479,20 +479,20 @@ describe("Toast", () => {
});
});

describe("ToastStyle", () => {
describe("StyledToast", () => {
let wrapper: ReactWrapper;

afterEach(() => {
wrapper.unmount();
});

it("should render with correct style based on default theme", () => {
wrapper = mount(<ToastStyle variant="success" />);
wrapper = mount(<StyledToast variant="success" />);

assertStyleMatch(
{
boxShadow:
"0 10px 30px 0 rgba(0,20,29,0.1), 0 30px 60px 0 rgba(0,20,29,0.1)",
"0 10px 30px 0 rgba(0,20,29,0.1),0 30px 60px 0 rgba(0,20,29,0.1)",
lineHeight: "22px",
marginTop: "30px",
maxWidth: "300px",
Expand All @@ -506,7 +506,7 @@ describe("ToastStyle", () => {
{
borderRadius: "var(--borderRadius100)",
},
wrapper.find(ToastStyle)
wrapper.find(StyledToast)
);
});

Expand Down Expand Up @@ -563,7 +563,7 @@ describe("TestContentStyle", () => {
});

it("should render with correct style based on default theme", () => {
wrapper = mount(<ToastContentStyle />);
wrapper = mount(<StyledToastContent />);

assertStyleMatch(
{
Expand Down Expand Up @@ -622,7 +622,7 @@ describe("Align vertical", () => {
Foo
</Toast>
);
assertStyleMatch({ marginTop: "0" }, wrapper.find(ToastStyle));
assertStyleMatch({ marginTop: "0" }, wrapper.find(StyledToast));
});
});

Expand Down
8 changes: 8 additions & 0 deletions src/components/toast/toast.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ import * as stories from "./toast.stories";
Toast is part of Carbon's Flashes components.
Its purpose is to present quick confirmation of success or failure, relating to the task the user has just performed. Alternatively, use Toast messages for a longer, timely message that the user must dismiss.

Various types are available:

- **Error** - Shows an error or failed action or task. Includes next steps.
- **Info** - Shows additional information when a task is completed.
- **Success** - Shows a successful action or completion of a task.
- **Warning** - Shows information about external factors that impact a task. For example, the user does not have access rights.
- **Neutral** - Shows information or advice, or provides context.

## Contents

- [Quick Start](#quick-start)
Expand Down
83 changes: 67 additions & 16 deletions src/components/toast/toast.style.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import styled, { css } from "styled-components";

import MessageStyle from "../message/message.style";
import MessageContentStyle from "../message/message-content/message-content.style";
import TypeIcon from "../message/type-icon/type-icon.style";
import StyledIconButton from "../icon-button/icon-button.style";
import Portal from "../portal/portal";
import baseTheme from "../../style/themes/base";
import StyledIcon from "../icon/icon.style";
import { MessageVariant } from "../message/message.component";

const StyledPortal = styled(Portal)<{
align?: "left" | "center" | "right";
Expand All @@ -17,7 +15,6 @@ const StyledPortal = styled(Portal)<{
${({ theme, isCenter, isNotice, align, alignY }) => css`
position: fixed;
top: 0;
z-index: ${theme.zIndex.notification};
${isCenter &&
Expand Down Expand Up @@ -49,7 +46,7 @@ const StyledPortal = styled(Portal)<{
bottom: 0;
top: auto;
width: 100%;
`}
`}
${alignY === "top" &&
css`
Expand Down Expand Up @@ -79,17 +76,66 @@ StyledPortal.defaultProps = {

const animationName = ".toast";
const alternativeAnimationName = ".toast-alternative";
const ToastStyle = styled(MessageStyle)<{

const ToastColourVariants = {
error: "var(--colorsSemanticNegative500)",
info: "var(--colorsSemanticInfo500)",
success: "var(--colorsSemanticPositive500)",
warning: "var(--colorsSemanticCaution500)",
neutral: "var(--colorsSemanticNeutral500)",
};

type ToastVariants = MessageVariant;

type ToastStyleProps = {
align?: "left" | "center" | "right";
alignY?: "top" | "center" | "bottom";
maxWidth?: string;
isCenter?: boolean;
isNotice?: boolean;
isNotification?: boolean;
}>`
${({ maxWidth, isCenter, align, isNotification, alignY, isNotice }) => css`
box-shadow: 0 10px 30px 0 rgba(0, 20, 29, 0.1),
0 30px 60px 0 rgba(0, 20, 29, 0.1);
variant: ToastVariants;
};

const boxShadow =
"0 10px 30px 0 rgba(0, 20, 29, 0.1), 0 30px 60px 0 rgba(0, 20, 29, 0.1)";

const iconPositionStyles = css`
position: absolute;
right: 15px;
top: 50%;
transform: translateY(-50%);
`;

const StyledToast = styled.div<ToastStyleProps>`
${({
maxWidth,
isCenter,
align,
isNotification,
alignY,
isNotice,
variant,
}) => css`
position: relative;
display: flex;
justify-content: flex-start;
align-content: center;
border-radius: var(--borderRadius100);
overflow: hidden;
border: 1px solid ${ToastColourVariants[variant]};
background-color: var(--colorsUtilityYang100);
min-height: 38px;
:focus {
outline: none;
}
${StyledIconButton} {
${iconPositionStyles}
}
box-shadow: ${boxShadow};
line-height: 22px;
margin-top: ${(alignY === "top" && isNotice) || alignY === "center"
? "0"
Expand Down Expand Up @@ -132,10 +178,7 @@ const ToastStyle = styled(MessageStyle)<{
}
${StyledIconButton} {
position: absolute;
right: 15px;
top: 50%;
transform: translateY(-50%);
${iconPositionStyles}
}
${({ isNotice, alignY }) =>
Expand Down Expand Up @@ -180,11 +223,13 @@ const ToastStyle = styled(MessageStyle)<{
`}
`;

const ToastContentStyle = styled(MessageContentStyle)<{
const StyledToastContent = styled.div<{
isNotice?: boolean;
isDismiss?: boolean;
}>`
padding: 8px 16px 8px 16px;
white-space: pre-wrap;
flex: 1;
${({ isNotice }) =>
isNotice &&
Expand Down Expand Up @@ -233,4 +278,10 @@ const ToastWrapper = styled.div<{
`}
`;

export { ToastStyle, TypeIcon, ToastContentStyle, ToastWrapper, StyledPortal };
export {
StyledPortal,
StyledToast,
TypeIcon,
StyledToastContent,
ToastWrapper,
};

0 comments on commit 0bd4a42

Please sign in to comment.