Prototype Banner component

parent 286d34e0
import React, { useMemo } from 'react';
import { composeClassNames as cx } from '../../helpers/composeClassNames';
import { useStyleSheet } from '../../hooks/useStyleSheet';
import Button from '../Button';
import { Icon } from '../Icon';
const variants = ['neutral', 'info', 'success', 'warning', 'danger'];
const Banner = ({
inline = false,
children,
className,
closeable,
icon,
title,
variant = 'neutral',
onClose,
...props
}) => {
useStyleSheet();
variant = variants.includes(variant) ? variant : variants[0];
const closeButtonProps = useMemo(() => {
return variant !== variants[0] ? { [variant]: true } : {};
}, [variant]);
return (
<div
className={cx('rcx-banner')({ [variant]: true }, className)}
{...props}
>
{icon && <div className={cx('rcx-banner__icon')({ inline })}>{icon}</div>}
<div className={cx('rcx-banner__content')({ inline })}>
{title && (
<h6 className={cx('rcx-banner__title')({ inline })}>{title}</h6>
)}
{children}
</div>
{closeable && (
<div className={cx('rcx-banner__close-button')({ inline })}>
<Button ghostish square small {...closeButtonProps} onClick={onClose}>
<Icon name='cross' size={24} />
</Button>
</div>
)}
</div>
);
};
export default Banner;
import { action } from '@storybook/addon-actions';
import React from 'react';
import { Icon } from '../Icon';
import Banner from './Banner';
export default {
title: 'Containers/Banner',
component: Banner,
};
export const _Banner = () => (
<Banner
closeable
icon={<Icon name='info' size={24} />}
title='Sed ut perspiciatis unde'
onClose={action('close')}
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor
</Banner>
);
_Banner.storyName = 'Banner';
export const Normal = () => (
<>
<Banner
closeable
icon={<Icon name='info' size={24} />}
title='Sed ut perspiciatis unde'
variant='neutral'
onClose={action('close')}
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor
</Banner>
<br />
<Banner
closeable
icon={<Icon name='info' size={24} />}
title='Sed ut perspiciatis unde'
variant='info'
onClose={action('close')}
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor
</Banner>
<br />
<Banner
closeable
icon={<Icon name='circle-check' size={24} />}
title='Sed ut perspiciatis unde'
variant='success'
onClose={action('close')}
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor
</Banner>
<br />
<Banner
closeable
icon={<Icon name='warning' size={24} />}
title='Sed ut perspiciatis unde'
variant='warning'
onClose={action('close')}
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor
</Banner>
<br />
<Banner
closeable
icon={<Icon name='ban' size={24} />}
title='Sed ut perspiciatis unde'
variant='danger'
onClose={action('close')}
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor
</Banner>
<br />
</>
);
export const Inline = () => (
<>
<Banner
inline
closeable
icon={<Icon name='info' size={24} />}
title='Sed ut perspiciatis unde'
variant='neutral'
onClose={action('close')}
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor
</Banner>
<br />
<Banner
inline
closeable
icon={<Icon name='info' size={24} />}
title='Sed ut perspiciatis unde'
variant='info'
onClose={action('close')}
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor
</Banner>
<br />
<Banner
inline
closeable
icon={<Icon name='circle-check' size={24} />}
title='Sed ut perspiciatis unde'
variant='success'
onClose={action('close')}
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor
</Banner>
<br />
<Banner
inline
closeable
icon={<Icon name='warning' size={24} />}
title='Sed ut perspiciatis unde'
variant='warning'
onClose={action('close')}
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor
</Banner>
<br />
<Banner
inline
closeable
icon={<Icon name='ban' size={24} />}
title='Sed ut perspiciatis unde'
variant='danger'
onClose={action('close')}
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor
</Banner>
<br />
</>
);
@use 'sass:map';
@use '../../styles/colors.scss';
@use '../../styles/typography.scss';
@mixin -variant($colors) {
color: map.get($colors, color);
background-color: map.get($colors, background-color);
}
.rcx-banner {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
align-items: flex-start;
flex: 0 1 auto;
box-sizing: border-box;
font-family: typography.font-family('sans');
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
&--neutral {
@include -variant(
(
background-color: colors.neutral(100),
color: colors.neutral(800),
)
);
}
&--info {
@include -variant(
(
background-color: colors.info(200),
color: colors.info(600),
)
);
}
&--success {
@include -variant(
(
background-color: colors.success(200),
color: colors.success(800),
)
);
}
&--warning {
@include -variant(
(
background-color: colors.warning(200),
color: colors.warning(900),
)
);
}
&--danger {
@include -variant(
(
background-color: colors.danger(200),
color: colors.danger(600),
)
);
}
&__icon {
display: none;
padding-block: 22px;
padding-inline-start: 16px;
@include on-breakpoint(sm) {
display: unset;
}
&--inline {
padding-block: 10px;
}
}
&__content {
flex-grow: 1;
align-self: center;
padding-block: 14px;
padding-inline: 12px;
@include typography.use-font-scale(p1);
&--inline {
padding-block: 12px;
@include typography.use-with-truncated-text;
}
}
&__title {
margin: 0;
padding: 0;
@include typography.use-font-scale(p2);
&--inline {
float: inline-start;
padding-inline-end: 8px;
}
}
&__close-button {
padding-block: 20px;
padding-inline-end: 24px;
&--inline {
padding-block: 8px;
}
}
}
export { default } from './Banner';
...@@ -2,6 +2,7 @@ export * from './Accordion'; ...@@ -2,6 +2,7 @@ export * from './Accordion';
export * from './AutoComplete'; export * from './AutoComplete';
export * from './Avatar'; export * from './Avatar';
export * from './Badge'; export * from './Badge';
export { default } from './Banner';
export * from './Box'; export * from './Box';
export { default as Button, ActionButton } from './Button'; export { default as Button, ActionButton } from './Button';
export * from './ButtonGroup'; export * from './ButtonGroup';
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
@import './AutoComplete/styles.scss'; @import './AutoComplete/styles.scss';
@import './Avatar/styles.scss'; @import './Avatar/styles.scss';
@import './Badge/styles.scss'; @import './Badge/styles.scss';
@import './Banner/Banner.styles.scss';
@import './Box/styles.scss'; @import './Box/styles.scss';
@import './Button/Button.styles.scss'; @import './Button/Button.styles.scss';
@import './ButtonGroup/styles.scss'; @import './ButtonGroup/styles.scss';
......
const withPrefix = (prefix) => (modifier) =>
prefix ? `${prefix}--${modifier}` : modifier;
export const composeClassNames = (prefix) => (...args) => {
const addPrefix = withPrefix(prefix);
const classNames = args
.map((arg) => {
if (typeof arg === 'string') {
return arg;
}
if (typeof arg === 'object' && Array.isArray(arg)) {
return arg.filter(Boolean).map(addPrefix).join(' ');
}
if (typeof arg === 'object' && arg !== null) {
return Object.entries(arg)
.map(([key, value]) => {
if (typeof value === 'boolean') {
if (value) {
return addPrefix(key);
}
return null;
}
if (typeof value === 'string' || typeof value === 'number') {
return addPrefix(`${key}-${value}`);
}
return null;
})
.filter(Boolean)
.join(' ');
}
return null;
})
.concat()
.filter(Boolean)
.join(' ');
if (!prefix) {
return classNames;
}
return `${prefix} ${classNames}`;
};
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment