123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- import styled from '@emotion/styled';
- import classNames from 'classnames';
- import {motion} from 'framer-motion';
- import {Indicator} from 'sentry/actionCreators/indicator';
- import LoadingIndicator from 'sentry/components/loadingIndicator';
- import {IconCheckmark, IconClose} from 'sentry/icons';
- import {t} from 'sentry/locale';
- import space from 'sentry/styles/space';
- import testableTransition from 'sentry/utils/testableTransition';
- type Props = {
- indicator: Indicator;
- onDismiss: (indicator: Indicator, event: React.MouseEvent) => void;
- className?: string;
- };
- function ToastIndicator({indicator, onDismiss, className, ...props}: Props) {
- let icon: React.ReactNode;
- const {options, message, type} = indicator;
- const {undo, disableDismiss} = options || {};
- const showUndo = typeof undo === 'function';
- const handleClick = (e: React.MouseEvent) => {
- if (disableDismiss) {
- return;
- }
- if (typeof onDismiss === 'function') {
- onDismiss(indicator, e);
- }
- };
- if (type === 'success') {
- icon = <IconCheckmark size="lg" isCircled />;
- } else if (type === 'error') {
- icon = <IconClose size="lg" isCircled />;
- }
- // TODO(billy): Remove ref- className after removing usage from getsentry
- return (
- <Toast
- onClick={handleClick}
- data-test-id={type ? `toast-${type}` : 'toast'}
- className={classNames(className, 'ref-toast', `ref-${type}`)}
- {...props}
- >
- {type === 'loading' ? (
- <StyledLoadingIndicator mini />
- ) : (
- <Icon type={type}>{icon}</Icon>
- )}
- <Message>{message}</Message>
- {showUndo && <Undo onClick={undo}>{t('Undo')}</Undo>}
- </Toast>
- );
- }
- const Toast = styled(motion.div)`
- display: flex;
- align-items: center;
- height: 40px;
- padding: 0 15px 0 10px;
- margin-top: 15px;
- background: ${p => p.theme.inverted.background};
- color: ${p => p.theme.inverted.textColor};
- border-radius: 44px 7px 7px 44px;
- box-shadow: ${p => p.theme.dropShadowHeavy};
- position: relative;
- `;
- Toast.defaultProps = {
- initial: {
- opacity: 0,
- y: 70,
- },
- animate: {
- opacity: 1,
- y: 0,
- },
- exit: {
- opacity: 0,
- y: 70,
- },
- transition: testableTransition({
- type: 'spring',
- stiffness: 450,
- damping: 25,
- }),
- };
- const Icon = styled('div', {shouldForwardProp: p => p !== 'type'})<{type: string}>`
- margin-right: ${space(0.75)};
- svg {
- display: block;
- }
- color: ${p => (p.type === 'success' ? p.theme.green300 : p.theme.red300)};
- `;
- const Message = styled('div')`
- flex: 1;
- `;
- const Undo = styled('div')`
- display: inline-block;
- color: ${p => p.theme.linkColor};
- padding-left: ${space(1)};
- margin-left: ${space(1)};
- cursor: pointer;
- &:hover {
- color: ${p => p.theme.linkHoverColor};
- }
- `;
- const StyledLoadingIndicator = styled(LoadingIndicator)`
- .loading-indicator {
- border-color: ${p => p.theme.inverted.border};
- border-left-color: ${p => p.theme.inverted.purple300};
- }
- `;
- export default ToastIndicator;
|