diff --git a/ui/components/component-library/banner-base/__snapshots__/banner-base.test.js.snap b/ui/components/component-library/banner-base/__snapshots__/banner-base.test.js.snap
index 13440fa40..bb950921f 100644
--- a/ui/components/component-library/banner-base/__snapshots__/banner-base.test.js.snap
+++ b/ui/components/component-library/banner-base/__snapshots__/banner-base.test.js.snap
@@ -3,7 +3,7 @@
exports[`BannerBase should render bannerbase element correctly 1`] = `
diff --git a/ui/components/component-library/banner-base/banner-base.js b/ui/components/component-library/banner-base/banner-base.js
index 7141d3650..14a9e76b3 100644
--- a/ui/components/component-library/banner-base/banner-base.js
+++ b/ui/components/component-library/banner-base/banner-base.js
@@ -29,11 +29,12 @@ export const BannerBase = ({
return (
{startAccessory && <>{startAccessory}>}
@@ -68,6 +69,7 @@ export const BannerBase = ({
{onClose && (
+
+
+
+## Props
+
+The `Banner` accepts all props below as well as all [Box](/docs/components-ui-box--default-story#props) component props
+
+
+
+The `Banner` accepts all `BannerBase` component props below
+
+
+
+### Severity
+
+Use the `severity` prop and the `SEVERITIES` object from `./ui/helpers/constants/design-system.js` to change the context of `Banner`.
+
+Optional: `BANNER_SEVERITIES` from `./banner` object can be used instead of `SEVERITIES`.
+
+Possible options:
+
+- `SEVERITIES.INFO` Default
+- `SEVERITIES.WARNING`
+- `SEVERITIES.DANGER`
+- `SEVERITIES.SUCCESS`
+
+
+
+```jsx
+import { Banner } from '../../component-library';
+import { SEVERITIES } from '../../../helpers/constants/design-system';
+
+
+ This is a demo of severity Info.
+
+
+ This is a demo of severity Warning.
+
+
+ This is a demo of severity Danger.
+
+
+ This is a demo of severity Success.
+
+```
+
+### Title
+
+Use the `title` prop to pass a string that is sentence case no period. Use the `titleProps` prop to pass additional props to the `Text` component.
+
+
+
+```jsx
+import { Banner } from '../../component-library';
+
+
+ Pass only a string through the title prop
+;
+```
+
+### Children
+
+The `children` is the description area of the `Banner` that can be a text or react node. Description shouldn't repeat title and only 1-3 lines.
+
+
+
+```jsx
+import { SIZES } from '../../../helpers/constants/design-system';
+import { Banner } from '../../component-library';
+
+
+ {`Description shouldn't repeat title. 1-3 lines. Can contain a `}
+
+ hyperlink.
+
+;
+```
+
+### Action Button Label, onClick, & Props
+
+Use the `actionButtonLabel` prop to pass text, `actionButtonOnClick` prop to pass an onClick handler, and `actionButtonProps` prop to pass an object of [ButtonLink props](/docs/components-componentlibrary-buttonlink--default-story) for the action
+
+
+
+```jsx
+import { Banner, ICON_NAMES } from '../../component-library';
+
+ console.log('ButtonLink actionButtonOnClick demo')}
+>
+ Use actionButtonLabel for action text, actionButtonOnClick for the onClick
+ handler, and actionButtonProps to pass any ButtonLink prop types such as
+ iconName
+;
+```
+
+### On Close
+
+Use the `onClose` prop to pass a function to the close button. The close button will appear when this prop is used.
+
+Additional props can be passed to the close button with `closeButtonProps`
+
+
+
+```jsx
+import { Banner } from '../../component-library';
+
+ console.log('close button clicked')}
+>
+ Click the close button icon to hide this notifcation
+;
+```
diff --git a/ui/components/component-library/banner/__snapshots__/banner.test.js.snap b/ui/components/component-library/banner/__snapshots__/banner.test.js.snap
new file mode 100644
index 000000000..3d991a687
--- /dev/null
+++ b/ui/components/component-library/banner/__snapshots__/banner.test.js.snap
@@ -0,0 +1,27 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Banner should render banner element correctly 1`] = `
+
+
+
+
+
+ Banner test
+
+
+ should render banner element correctly
+
+
+
+
+`;
diff --git a/ui/components/component-library/banner/banner.constants.js b/ui/components/component-library/banner/banner.constants.js
new file mode 100644
index 000000000..88f653d51
--- /dev/null
+++ b/ui/components/component-library/banner/banner.constants.js
@@ -0,0 +1,8 @@
+import { SEVERITIES } from '../../../helpers/constants/design-system';
+
+export const BANNER_SEVERITIES = {
+ DANGER: SEVERITIES.DANGER,
+ INFO: SEVERITIES.INFO,
+ SUCCESS: SEVERITIES.SUCCESS,
+ WARNING: SEVERITIES.WARNING,
+};
diff --git a/ui/components/component-library/banner/banner.js b/ui/components/component-library/banner/banner.js
new file mode 100644
index 000000000..80083d97c
--- /dev/null
+++ b/ui/components/component-library/banner/banner.js
@@ -0,0 +1,93 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import classnames from 'classnames';
+
+import { BannerBase, Icon, ICON_NAMES } from '..';
+
+import {
+ COLORS,
+ SEVERITIES,
+ SIZES,
+} from '../../../helpers/constants/design-system';
+import { BANNER_SEVERITIES } from './banner.constants';
+
+export const Banner = ({
+ children,
+ className,
+ severity = SEVERITIES.INFO,
+ ...props
+}) => {
+ const severityIcon = () => {
+ switch (severity) {
+ case SEVERITIES.DANGER:
+ return {
+ name: ICON_NAMES.DANGER,
+ color: COLORS.ERROR_DEFAULT,
+ };
+ case SEVERITIES.WARNING:
+ return {
+ name: ICON_NAMES.WARNING,
+ color: COLORS.WARNING_DEFAULT,
+ };
+ case SEVERITIES.SUCCESS:
+ return {
+ name: ICON_NAMES.CONFIRMATION,
+ color: COLORS.SUCCESS_DEFAULT,
+ };
+ // Defaults to SEVERITIES.INFO
+ default:
+ return {
+ name: ICON_NAMES.INFO,
+ color: COLORS.PRIMARY_DEFAULT,
+ };
+ }
+ };
+
+ const severityBackground = () => {
+ switch (severity) {
+ case SEVERITIES.DANGER:
+ return COLORS.ERROR_MUTED;
+ case SEVERITIES.WARNING:
+ return COLORS.WARNING_MUTED;
+ case SEVERITIES.SUCCESS:
+ return COLORS.SUCCESS_MUTED;
+ // Defaults to SEVERITIES.INFO
+ default:
+ return COLORS.PRIMARY_MUTED;
+ }
+ };
+
+ return (
+ }
+ backgroundColor={severityBackground()}
+ className={classnames(
+ 'mm-banner',
+ {
+ [`mm-banner--severity-${severity}`]:
+ Object.values(BANNER_SEVERITIES).includes(severity),
+ },
+ className,
+ )}
+ {...props}
+ >
+ {children}
+
+ );
+};
+
+Banner.propTypes = {
+ /**
+ * An additional className to apply to the Banner
+ */
+ className: PropTypes.string,
+ /**
+ * Use the `severity` prop and the `SEVERITIES` object from `./ui/helpers/constants/design-system.js` to change the context of `Banner`.
+ * Possible options: `SEVERITIES.INFO`(Default), `SEVERITIES.WARNING`, `SEVERITIES.DANGER`, `SEVERITIES.SUCCESS`
+ */
+ severity: PropTypes.oneOf(Object.values(BANNER_SEVERITIES)),
+ /**
+ * Banner accepts all the props from BannerBase
+ */
+ ...BannerBase.propTypes,
+};
diff --git a/ui/components/component-library/banner/banner.scss b/ui/components/component-library/banner/banner.scss
new file mode 100644
index 000000000..5def11e64
--- /dev/null
+++ b/ui/components/component-library/banner/banner.scss
@@ -0,0 +1,16 @@
+.mm-banner {
+ border-left-color: var(--color-primary-default);
+
+ &--severity-danger {
+ border-left-color: var(--color-error-default);
+ }
+
+ &--severity-warning {
+ border-left-color: var(--color-warning-default);
+ }
+
+ &--severity-success {
+ border-left-color: var(--color-success-default);
+ }
+}
+
diff --git a/ui/components/component-library/banner/banner.stories.js b/ui/components/component-library/banner/banner.stories.js
new file mode 100644
index 000000000..8c674cde5
--- /dev/null
+++ b/ui/components/component-library/banner/banner.stories.js
@@ -0,0 +1,183 @@
+import React from 'react';
+import { useState } from '@storybook/addons';
+import {
+ DISPLAY,
+ FLEX_DIRECTION,
+ SEVERITIES,
+ SIZES,
+} from '../../../helpers/constants/design-system';
+import Box from '../../ui/box/box';
+import { ICON_NAMES, ButtonLink, ButtonPrimary } from '..';
+import README from './README.mdx';
+import { Banner, BANNER_SEVERITIES } from '.';
+
+const marginSizeControlOptions = [
+ undefined,
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 'auto',
+];
+
+export default {
+ title: 'Components/ComponentLibrary/Banner',
+ component: Banner,
+ parameters: {
+ docs: {
+ page: README,
+ },
+ backgrounds: { default: 'alternative' },
+ },
+ argTypes: {
+ severity: {
+ options: Object.values(BANNER_SEVERITIES),
+ control: 'select',
+ },
+ className: {
+ control: 'text',
+ },
+ title: {
+ control: 'text',
+ },
+ children: {
+ control: 'text',
+ },
+ action: {
+ control: 'func',
+ },
+ actionButtonLabel: {
+ control: 'text',
+ },
+ actionButtonOnClick: {
+ control: 'func',
+ },
+ actionButtonProps: {
+ control: 'object',
+ },
+ onClose: {
+ action: 'onClose',
+ },
+ marginTop: {
+ options: marginSizeControlOptions,
+ control: 'select',
+ table: { category: 'box props' },
+ },
+ marginRight: {
+ options: marginSizeControlOptions,
+ control: 'select',
+ table: { category: 'box props' },
+ },
+ marginBottom: {
+ options: marginSizeControlOptions,
+ control: 'select',
+ table: { category: 'box props' },
+ },
+ marginLeft: {
+ options: marginSizeControlOptions,
+ control: 'select',
+ table: { category: 'box props' },
+ },
+ },
+};
+
+export const DefaultStory = (args) => {
+ const onClose = () => console.log('Banner onClose trigger');
+ return ;
+};
+
+DefaultStory.args = {
+ title: 'Title is sentence case no period',
+ children: "Description shouldn't repeat title. 1-3 lines.",
+ actionButtonLabel: 'Action',
+};
+
+DefaultStory.storyName = 'Default';
+
+export const Severity = (args) => {
+ return (
+
+
+ This is a demo of severity Info.
+
+
+ This is a demo of severity Warning.
+
+
+ This is a demo of severity Danger.
+
+
+ This is a demo of severity Success.
+
+
+ );
+};
+
+export const Title = (args) => {
+ return ;
+};
+
+Title.args = {
+ title: 'Title is sentence case no period',
+ children: 'Pass only a string through the title prop',
+};
+
+export const Children = (args) => {
+ return (
+
+ {`Description shouldn't repeat title. 1-3 lines. Can contain a `}
+
+ hyperlink.
+
+
+ );
+};
+
+export const ActionButton = (args) => {
+ return ;
+};
+
+ActionButton.args = {
+ title: 'Action prop demo',
+ actionButtonLabel: 'Action',
+ actionButtonOnClick: () => console.log('ButtonLink actionButtonOnClick demo'),
+ actionButtonProps: {
+ iconName: ICON_NAMES.ARROW_2_RIGHT,
+ iconPositionRight: true,
+ },
+ children:
+ 'Use actionButtonLabel for action text, actionButtonOnClick for the onClick handler, and actionButtonProps to pass any ButtonLink prop types such as iconName',
+};
+
+export const OnClose = (args) => {
+ const [isShown, setShown] = useState(true);
+ const bannerToggle = () => {
+ if (isShown) {
+ console.log('close button clicked');
+ }
+ setShown(!isShown);
+ };
+ return (
+ <>
+ {isShown ? (
+
+ ) : (
+ View Banner
+ )}
+ >
+ );
+};
+
+OnClose.args = {
+ title: 'onClose demo',
+ children: 'Click the close button icon to hide this notifcation',
+};
diff --git a/ui/components/component-library/banner/banner.test.js b/ui/components/component-library/banner/banner.test.js
new file mode 100644
index 000000000..9f92450b0
--- /dev/null
+++ b/ui/components/component-library/banner/banner.test.js
@@ -0,0 +1,111 @@
+/* eslint-disable jest/require-top-level-describe */
+import { render } from '@testing-library/react';
+import React from 'react';
+
+import { renderWithUserEvent } from '../../../../test/lib/render-helpers';
+
+import { Banner, BANNER_SEVERITIES } from '.';
+
+describe('Banner', () => {
+ it('should render banner element correctly', () => {
+ const { getByTestId, container } = render(
+
+ should render banner element correctly
+ ,
+ );
+ expect(getByTestId('banner')).toHaveClass('mm-banner');
+ expect(container).toMatchSnapshot();
+ });
+
+ it('should render with added classname', () => {
+ const { getByTestId } = render(
+
+ should render banner element correctly
+ ,
+ );
+ expect(getByTestId('banner')).toHaveClass('mm-banner--test');
+ });
+
+ it('should render with different severity classnames', () => {
+ const { getByTestId } = render(
+ <>
+
+ This is a demo of severity Info.
+
+
+ This is a demo of severity Warning.
+
+
+ This is a demo of severity Danger.
+
+
+ This is a demo of severity Success.
+
+ >,
+ );
+ expect(getByTestId('info')).toHaveClass('mm-banner--severity-info');
+ expect(getByTestId('warning')).toHaveClass('mm-banner--severity-warning');
+ expect(getByTestId('danger')).toHaveClass('mm-banner--severity-danger');
+ expect(getByTestId('success')).toHaveClass('mm-banner--severity-success');
+ });
+
+ it('should render banner title', () => {
+ const { getByText } = render();
+ expect(getByText('Banner title test')).toHaveClass('mm-banner-base__title');
+ });
+
+ it('should render banner description', () => {
+ const { getByText } = render(Banner description test);
+ expect(getByText('Banner description test')).toBeDefined();
+ });
+
+ it('should render banner action button', () => {
+ const { getByTestId } = render(
+
+ console.log('ButtonLink actionButtonOnClick demo')
+ }
+ >
+ Use actionButtonLabel for action text, actionButtonOnClick for the
+ onClick handler, and actionButtonProps to pass any ButtonLink prop types
+ such as iconName
+ ,
+ );
+ expect(getByTestId('action')).toHaveClass('mm-banner-base__action');
+ });
+
+ it('should render and fire onClose event', async () => {
+ const onClose = jest.fn();
+ const { user, getByTestId } = renderWithUserEvent(
+ ,
+ );
+ await user.click(getByTestId('close-button'));
+ expect(onClose).toHaveBeenCalledTimes(1);
+ });
+});
diff --git a/ui/components/component-library/banner/index.js b/ui/components/component-library/banner/index.js
new file mode 100644
index 000000000..0e9e3ed86
--- /dev/null
+++ b/ui/components/component-library/banner/index.js
@@ -0,0 +1,2 @@
+export { Banner } from './banner';
+export { BANNER_SEVERITIES } from './banner.constants';
diff --git a/ui/components/component-library/component-library-components.scss b/ui/components/component-library/component-library-components.scss
index 96a05a086..d56a616cc 100644
--- a/ui/components/component-library/component-library-components.scss
+++ b/ui/components/component-library/component-library-components.scss
@@ -27,3 +27,4 @@
@import 'text-field-search/text-field-search';
@import 'form-text-field/form-text-field';
@import 'banner-base/banner-base';
+@import 'banner/banner';
diff --git a/ui/components/component-library/index.js b/ui/components/component-library/index.js
index c40fc7dea..28338b1fb 100644
--- a/ui/components/component-library/index.js
+++ b/ui/components/component-library/index.js
@@ -37,3 +37,4 @@ export { TextFieldSearch } from './text-field-search';
// Molecules
export { BannerBase } from './banner-base';
+export { Banner, BANNER_SEVERITIES } from './banner';