1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-13 22:01:06 +00:00

12.0 remove glamor (#6256)

* remove glamor

* change toaster style
This commit is contained in:
Michael An
2024-06-25 16:46:29 +08:00
committed by GitHub
parent 544ebe7fe6
commit 939c85d3c1
7 changed files with 183 additions and 398 deletions

View File

@@ -1,115 +1,53 @@
import React from 'react';
import PropTypes from 'prop-types';
import { css } from 'glamor';
const propTypes = {
intent: PropTypes.string.isRequired,
title: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
onRemove: PropTypes.func.isRequired,
children: PropTypes.string,
isRemovable: PropTypes.bool,
};
class Alert extends React.PureComponent {
constructor(props) {
super(props);
this.containerStyle = css({
borderRadius: '3px',
backgroundColor: '#fff',
padding: '10px 16px',
display: 'flex',
boxSizing: 'border-box',
boxShadow: 'rgba(67, 90, 111, 0.3) 0px 0px 1px, rgba(67, 90, 111, 0.47) 0px 8px 10px -4px',
justifyContent: 'space-between',
flexDirection: 'row',
});
this.containerBorderSuccess = css({
borderLeft: '3px solid rgb(71, 184, 129)'
});
this.containerBorderWarn = css({
borderLeft: '3px solid rgb(217, 130, 43)'
});
this.containerBorderDanger = css({
borderLeft: '3px solid rgb(236, 76, 71)'
});
this.containerBorderNotify = css({
borderLeft: '3px solid rgb(16, 112, 202)'
});
this.toastTextTitle = css({
fontWeight: '600',
fontSize: '14px',
color: '#435a6f',
margin: '0'
});
this.toastTextChild = css({
fontSize: '14px',
color: '#999',
margin: '0'
});
this.toastClose = css({
marginLeft: '15px',
height: '24px',
width: '24px',
lineHeight: '22px',
fontWeight: '700',
textAlign: 'center',
fontSize: '20px',
color: '#000',
cursor: 'pointer',
opacity: '0.5',
':hover': {
opacity: 1
}
});
this.toastIcon = css({
marginRight: '10px',
width: '14px',
height: '20px',
lineHeight: '20px'
});
}
getContainerStyle(intent) {
getIconClass(intent) {
switch (intent) {
case 'success':
return { borderStyle: this.containerBorderSuccess, iconColor: css({color: 'rgb(71, 184, 129)'}), iconClass: 'fa fa-check-circle' };
return 'fa fa-check-circle';
case 'warning':
return { borderStyle: this.containerBorderWarn, iconColor: css({color: 'rgb(217, 130, 43)'}) , iconClass: 'fa fa-exclamation-triangle' };
return 'fa fa-exclamation-triangle';
case 'none':
return { borderStyle: this.containerBorderNotify, iconColor: css({color: 'rgb(16, 112, 202)'}), iconClass: 'fa fa-exclamation-circle' };
case 'notify-in-progress':
return { borderStyle: this.containerBorderNotify, iconColor: css({width: '15px', height: '15px', margin: '3px'}), iconClass: 'loading-icon' };
case 'danger':
return { borderStyle: this.containerBorderDanger, iconColor: css({color: 'rgb(236, 76, 71)'}), iconClass: 'fa fa-exclamation-circle' };
return 'fa fa-exclamation-circle';
case 'danger':
return 'fa fa-exclamation-circle';
default:
return 'fa fa-check-circle';
}
}
render() {
const toastStyle = this.getContainerStyle(this.props.intent);
const { intent, title, children, isRemovable, onRemove } = this.props;
const iconClass = this.getIconClass(intent);
return (
<div {...css(toastStyle.borderStyle, this.containerStyle)}>
<div className={this.toastIcon} >
<i className={toastStyle.iconClass} {...toastStyle.iconColor}/>
<div className={`seahub-toast-alert-container ${intent || 'success'}`}>
<div className="toast-alert-icon">
<i className={iconClass} />
</div>
<div className={this.toastTextContainer}>
<p className={this.toastTextTitle}>{this.props.title}</p>
{this.props.children ? <p className={this.toastTextChild}>{this.props.children}</p> : null}
</div>
<div onClick={this.props.onRemove} className={this.toastClose}>
<span>&times;</span>
<div className="toast-text-container">
<p className="toast-text-title">{title}</p>
{children ? <p className="toast-text-child">{children}</p> : null}
</div>
{isRemovable && (
<div onClick={onRemove} className="toast-close">
<span>&times;</span>
</div>
)}
</div>
);
}
}
Alert.propTypes = {
onRemove: PropTypes.func.isRequired,
children: PropTypes.any,
title: PropTypes.string.isRequired,
intent: PropTypes.string.isRequired,
};
Alert.propTypes = propTypes;
export default Alert;

View File

@@ -1,52 +1,10 @@
import React from 'react';
import { css } from 'glamor';
import PropTypes from 'prop-types';
import Transition from 'react-transition-group/Transition';
import Alert from './alert';
const animationEasing = {
deceleration: 'cubic-bezier(0.0, 0.0, 0.2, 1)',
acceleration: 'cubic-bezier(0.4, 0.0, 1, 1)',
spring: 'cubic-bezier(0.175, 0.885, 0.320, 1.175)'
};
const ANIMATION_DURATION = 240;
const openAnimation = css.keyframes('openAnimation', {
from: {
opacity: 0,
transform: 'translateY(-120%)'
},
to: {
transform: 'translateY(0)'
}
});
const closeAnimation = css.keyframes('closeAnimation', {
from: {
transform: 'scale(1)',
opacity: 1
},
to: {
transform: 'scale(0.9)',
opacity: 0
}
});
const animationStyles = css({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
height: 0,
transition: `all ${ANIMATION_DURATION}ms ${animationEasing.deceleration}`,
'&[data-state="entering"], &[data-state="entered"]': {
animation: `${openAnimation} ${ANIMATION_DURATION}ms ${animationEasing.spring} both`
},
'&[data-state="exiting"]': {
animation: `${closeAnimation} 120ms ${animationEasing.acceleration} both`
}
});
export default class Toast extends React.PureComponent {
static propTypes = {
/**
@@ -67,7 +25,7 @@ export default class Toast extends React.PureComponent {
/**
* The type of the alert.
*/
intent: PropTypes.oneOf(['none', 'notify-in-progress', 'success', 'warning', 'danger']).isRequired,
intent: PropTypes.oneOf(['none', 'success', 'warning', 'danger']).isRequired,
/**
* The title of the alert.
@@ -116,7 +74,11 @@ export default class Toast extends React.PureComponent {
this.clearCloseTimer();
}
close = () => {
close = (event) => {
if (event) {
event.nativeEvent.stopImmediatePropagation();
event.stopPropagation();
}
this.clearCloseTimer();
this.setState({
isShown: false
@@ -168,7 +130,7 @@ export default class Toast extends React.PureComponent {
{state => (
<div
data-state={state}
className={animationStyles}
className={`seahub-toast-container ${state}`}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
style={{
@@ -181,9 +143,9 @@ export default class Toast extends React.PureComponent {
<Alert
intent={this.props.intent}
title={this.props.title}
children={this.props.children}
isRemoveable={this.props.hasCloseButton}
onRemove={() => this.close()}
children={this.props.children || ''}
isRemovable={this.props.hasCloseButton}
onRemove={(event) => this.close(event)}
/>
</div>
</div>

View File

@@ -1,20 +1,7 @@
import React from 'react';
import { css } from 'glamor';
import PropTypes from 'prop-types';
import Toast from './toast';
const wrapperClass = css({
maxWidth: 560,
margin: '0 auto',
top: 0,
left: 0,
right: 0,
position: 'fixed',
zIndex: 999999,
});
const hasCustomId = settings => Object.hasOwnProperty.call(settings, 'id');
export default class ToastManager extends React.PureComponent {
@@ -83,12 +70,22 @@ export default class ToastManager extends React.PureComponent {
const uniqueId = ++ToastManager.idCounter;
const id = hasCustomId(settings) ? `${settings.id}-${uniqueId}` : uniqueId;
let hasCloseButton = settings.hasCloseButton || true;
let duration = settings.duration || 2;
if (settings.hasCloseButton !== undefined) {
hasCloseButton = settings.hasCloseButton;
}
if (settings.duration !== undefined) {
duration = settings.duration;
}
return {
id,
title,
description: settings.description,
hasCloseButton: settings.hasCloseButton || true,
duration: settings.duration || 2,
hasCloseButton: hasCloseButton,
duration: duration,
close: () => this.closeToast(id),
intent: settings.intent
};
@@ -124,7 +121,7 @@ export default class ToastManager extends React.PureComponent {
render() {
return (
<span className={wrapperClass}>
<div className="seahub-toast-manager">
{this.state.toasts.map(({ id, description, ...props }) => {
return (
<Toast key={id} onRemove={() => this.removeToast(id)} {...props}>
@@ -132,7 +129,7 @@ export default class ToastManager extends React.PureComponent {
</Toast>
);
})}
</span>
</div>
);
}
}

View File

@@ -0,0 +1,116 @@
.seahub-toast-manager {
position: fixed;
margin: 0 auto;
max-width: 560px;
top: 0;
left: 0;
right: 0;
z-index: 999999;
}
.seahub-toast-container {
display: flex;
flex-direction: column;
align-items: center;
height: 0;
transition: all 240ms cubic-bezier(0.0, 0.0, 0.2, 1);
}
@keyframes openAnimation {
from {
opacity: 0;
transform: translateY(-120%);
}
to {
transform: translateY(0);
}
}
@keyframes closeAnimation {
from {
transform: scale(1);
opacity: 1;
}
to {
transform: scale(0.9);
opacity: 0;
}
}
.seahub-toast-container.entering,
.seahub-toast-container.entered {
animation: openAnimation 240ms cubic-bezier(0.175, 0.885, 0.320, 1.175) both;
}
.seahub-toast-container.exiting {
animation: closeAnimation 120ms cubic-bezier(0.4, 0.0, 1, 1) both;
}
.seahub-toast-alert-container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
border-radius: 3px;
box-shadow: rgba(67, 90, 111, 0.3) 0px 0px 1px, rgba(67, 90, 111, 0.47) 0px 8px 10px -4px;
padding: 10px 16px;
background-color: #fff;
}
.seahub-toast-alert-container.success {
border-left: 3px solid rgb(71, 184, 129);
color: rgb(71, 184, 129);
}
.seahub-toast-alert-container.warning {
border-left: 3px solid rgb(217, 130, 43);
color: rgb(217, 130, 43);
}
.seahub-toast-alert-container.none {
border-left: 3px solid rgb(16, 112, 202);
color: rgb(16, 112, 202);
}
.seahub-toast-alert-container.danger {
border-left: 3px solid rgb(236, 76, 71);
color: rgb(236, 76, 71);
}
.seahub-toast-alert-container .toast-alert-icon {
margin-right: 10px;
width: 14px;
height: 20px;
line-height: 20px;
}
.seahub-toast-alert-container .toast-text-title {
margin: 0;
font-weight: 600;
font-size: 14px;
color: #435a6f;
}
.seahub-toast-alert-container .toast-text-child {
font-size: 14px;
color: #666;
margin: 0;
}
.seahub-toast-alert-container .toast-close {
text-align: center;
cursor: pointer;
height: 24px;
width: 24px;
margin-left: 15px;
line-height: 22px;
font-weight: 700;
font-size: 20px;
color: #000;
opacity: 0.5;
}
.seahub-toast-alert-container .toast-close:hover {
opacity: 1;
}

View File

@@ -1,9 +1,10 @@
import React from 'react';
import ReactDom from 'react-dom';
import ReactDOM from 'react-dom';
import ToastManager from './toastManager';
const isBrowser =
typeof window !== 'undefined' && typeof window.document !== 'undefined';
import './toaster.css';
const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
/**
* The Toaster manages the interactionsb between
@@ -17,7 +18,7 @@ export default class Toaster {
container.setAttribute('data-evergreen-toaster-container', '');
document.body.appendChild(container);
ReactDom.render(
ReactDOM.render(
<ToastManager
bindNotify={this._bindNotify}
bindGetToasts={this._bindGetToasts}
@@ -51,10 +52,6 @@ export default class Toaster {
return this.notifyHandler(title, { ...settings, intent: 'none' });
};
notifyInProgress = (title, settings = {}) => {
return this.notifyHandler(title, { ...settings, intent: 'notify-in-progress' });
};
success = (title, settings = {}) => {
return this.notifyHandler(title, { ...settings, intent: 'success' });
};