Skip to content

Commit

Permalink
Added NotificationAlert component (#929)
Browse files Browse the repository at this point in the history
  • Loading branch information
bexsoft authored Aug 15, 2024
1 parent 3782ed0 commit a2d6100
Show file tree
Hide file tree
Showing 10 changed files with 714 additions and 3 deletions.
141 changes: 141 additions & 0 deletions src/components/NotificationAlert/NotificationAlert.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// This file is part of MinIO Design System
// Copyright (c) 2024 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

import React from "react";
import { Meta, Story } from "@storybook/react";

import NotificationAlert from "./NotificationAlert";
import { NotificationAlertPrp } from "./NotificationAlert.types";

import StoryThemeProvider from "../../utils/StoryThemeProvider";
import { GlobalStyles } from "../index";

export default {
title: "MDS/Information/NotificationAlert",
component: NotificationAlert,
argTypes: {},
} as Meta<typeof NotificationAlert>;

const Template: Story<NotificationAlertPrp> = ({ ...props }) => {
return (
<StoryThemeProvider>
<GlobalStyles />
<NotificationAlert {...props} designMode={"card"} />
<br />
<NotificationAlert {...props} designMode={"banner"} />
<br />
<NotificationAlert
{...props}
designMode={"card"}
emphasisMode={"minimal"}
/>
<br />
<NotificationAlert
{...props}
designMode={"banner"}
emphasisMode={"minimal"}
/>
<br />
<NotificationAlert {...props} designMode={"card"} onClose={() => {}} />
<br />
<NotificationAlert {...props} designMode={"banner"} onClose={() => {}} />
<br />
<NotificationAlert
{...props}
designMode={"card"}
onClose={() => {}}
action={<a>Action</a>}
/>
<br />
<NotificationAlert
{...props}
designMode={"banner"}
onClose={() => {}}
action={<a>Action</a>}
/>
<br />
<NotificationAlert
{...props}
designMode={"card"}
onClose={() => {}}
action={<a>Action</a>}
shadow
/>
<br />
<NotificationAlert
{...props}
designMode={"banner"}
onClose={() => {}}
action={<a>Action</a>}
shadow
/>
<br />
<NotificationAlert
{...props}
designMode={"card"}
onClose={() => {}}
action={<a>Action</a>}
emphasisMode={"minimal"}
shadow
/>
<br />
<NotificationAlert
{...props}
designMode={"banner"}
onClose={() => {}}
action={<a>Action</a>}
emphasisMode={"minimal"}
shadow
/>
<br />
</StoryThemeProvider>
);
};

export const Neutral = Template.bind({});
Neutral.args = {
variant: "neutral",
title: "This is the title for a message",
children: "This is the content for an informative message",
};

export const Success = Template.bind({});
Success.args = {
variant: "success",
title: "This is the title for a message",
children: "This is the content for a success message",
};

export const Warning = Template.bind({});
Warning.args = {
variant: "warning",
title: "This is the title for a message",
children: "This is the content for an warning message",
};

export const Danger = Template.bind({});
Danger.args = {
variant: "danger",
title: "This is the title for a message",
children: "This is the content for an error message",
};

export const Information = Template.bind({});
Information.args = {
variant: "information",
title: "This is the title for a message",
children: "This is the content for an error message",
};
219 changes: 219 additions & 0 deletions src/components/NotificationAlert/NotificationAlert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
// This file is part of MinIO Design System
// Copyright (c) 2024 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

import React, { FC, Fragment, useMemo } from "react";
import get from "lodash/get";
import {
NotificationAlertConstruct,
NotificationAlertPrp,
} from "./NotificationAlert.types";
import XIcon from "../Icons/NewDesignIcons/XIcon";
import styled from "styled-components";
import CircleSlashIcon from "../Icons/NewDesignIcons/CircleSlashIcon";
import InfoIcon from "../Icons/NewDesignIcons/InfoIcon";
import CircleCheckIcon from "../Icons/NewDesignIcons/CircleCheckIcon";
import CircleAlertIcon from "../Icons/NewDesignIcons/CircleAlertIcon";
import CircleXIcon from "../Icons/NewDesignIcons/CircleXIcon";
import { themeColors, themeShadows } from "../../global/themeColors";
import { paddingSizeVariants } from "../../global/utils";

const NotificationContainer = styled.div.attrs(() => ({
className: "notification-alert",
}))<NotificationAlertConstruct>(
({ theme, emphasisMode, shadow, variant, designMode }) => {
const backgroundColor =
emphasisMode === "subtle"
? get(
theme,
`notificationAlert.${variant}.highContrastBG`,
themeColors["Color/Brand/Error/colorPrimaryBg"].lightMode,
)
: get(
theme,
`notificationAlert.${variant}.minimalContrastBG`,
themeColors["Color/Neutral/Bg/colorBgElevated"].lightMode,
);
const borderColor =
emphasisMode === "subtle"
? get(
theme,
`notificationAlert.${variant}.highContrastBorder`,
themeColors["Color/Brand/Error/colorPrimaryBg"].lightMode,
)
: get(
theme,
`notificationAlert.${variant}.minimalContrastBorder`,
themeColors["Color/Brand/Error/colorPrimaryBorder"].lightMode,
);

return {
display: "flex",
width: "100%",
maxWidth: 400,
backgroundColor: backgroundColor,
border: `1px solid ${borderColor}`,
borderRadius: 8,
gap: 8,
alignItems: designMode === "banner" ? "center" : "flex-start",
boxShadow: shadow ? themeShadows["boxShadow-03"] : "none",
padding:
designMode === "banner"
? `${paddingSizeVariants.sizeXS}px ${paddingSizeVariants.size}px`
: paddingSizeVariants.size,
"& .mainInfoContainer": {
flexGrow: 1,
width: "100%",
},
"& .actionCardMode": {
marginTop: 8,
},
"& > svg": {
color: get(
theme,
`notificationAlert.${variant}.iconColor`,
themeColors["Color/Brand/Neutral/colorPrimaryBg"].lightMode,
),
width: 16,
height: 16,
minWidth: 16,
minHeight: 16,
},
"& .dismissAlert": {
color: get(
theme,
"notificationAlert.contentColor",
themeColors["Color/Neutral/Text/colorTextLabel"].lightMode,
),
backgroundColor: "transparent",
border: 0,
padding: 0,
width: 16,
height: 16,
cursor: "pointer",
alignSelf: designMode === "card" ? "flex-start" : "center",
"& svg": {
width: 16,
height: 16,
},
},
"& .alertInitLine": {
display: "flex",
alignItems: "flex-start",
justifyContent: "flex-start",

"& .content": {
fontSize: 14,
fontStyle: "normal",
fontWeight: 400,
lineHeight: "20px",
letterSpacing: "0.16px",
},

"& .notificationTitle": {
display: "flex",
alignItems: "center",
justifyContent: "space-between",
width: "100%",
"& .fillTitleContent": {
display: "flex",
flex: 1,
width: "100%",
gap: 8,
alignItems: designMode === "card" ? "flex-start" : "center",
},
"& .cardTitle": {
fontSize: 14,
fontStyle: "normal",
fontWeight: 600,
letterSpacing: "0.16px",
lineHeight: 1,
color: get(
theme,
"notificationAlert.titleColor",
themeColors["Color/Neutral/Text/colorTextHeading"].lightMode,
),
},
},
},
};
},
);

const NotificationAlert: FC<NotificationAlertPrp> = ({
title,
children,
action,
onClose,
designMode = "banner",
emphasisMode = "subtle",
variant = "information",
shadow = false,
}) => {
const icon = useMemo(() => {
switch (variant) {
case "information":
return <InfoIcon />;
case "success":
return <CircleCheckIcon />;
case "warning":
return <CircleAlertIcon />;
case "danger":
return <CircleXIcon />;
default:
return <CircleSlashIcon />;
}
}, [variant]);

return (
<NotificationContainer
emphasisMode={emphasisMode}
shadow={shadow}
variant={variant}
designMode={designMode}
>
{icon}
<div className={"mainInfoContainer"}>
<div className={"alertInitLine"}>
<div className={"notificationTitle"}>
<div className={"fillTitleContent"}>
{designMode === "banner" ? (
<Fragment>
<div className={"content"}>{children}</div>
<div>{action}</div>
</Fragment>
) : (
<div className={"cardTitle"}>{title}</div>
)}
</div>
</div>
</div>
{designMode === "card" && (
<div>
<div className={"content"}>{children}</div>
<div className={"actionCardMode"}>{action}</div>
</div>
)}
</div>
{onClose && (
<button className={"dismissAlert"} onClick={onClose}>
<XIcon />
</button>
)}
</NotificationContainer>
);
};

export default NotificationAlert;
Loading

0 comments on commit a2d6100

Please sign in to comment.