improvement (UI): hover and select effect on files and breadcrumb improvements

This commit is contained in:
Mickael KERJEAN 2017-06-30 15:51:01 +10:00
parent c964c274a8
commit acf243bd07
4 changed files with 74 additions and 39 deletions

View file

@ -11,7 +11,7 @@ export class BreadCrumb extends React.Component {
this.state = {
path: this._formatPath(props.path)
};
}
}
componentWillReceiveProps(props){
this.setState({path: this._formatPath(props.path)});
@ -33,12 +33,12 @@ export class BreadCrumb extends React.Component {
});
return paths;
}
render(Element) {
const Path = Element? Element : PathElement;
return (
<div>
<BreadCrumbContainer className={this.props.className}>
<BreadCrumbContainer className={this.props.className+' no-select'}>
<Logout />
{
this.state.path.map((path, index) => {
@ -63,8 +63,8 @@ BreadCrumb.propTypes = {
const BreadCrumbContainer = (props) => {
let style1 = {background: 'white', margin: '0 0 0px 0', padding: '6px 0', boxShadow: '0 4px 5px 0 rgba(0,0,0,0.14), 0 1px 10px 0 rgba(0,0,0,0.12), 0 2px 4px -1px rgba(0,0,0,0.2)', zIndex: '1000', position: 'relative'};
let style2 = {margin: '0 auto', width: '95%', maxWidth: '800px', padding: '0'};
let style1 = {background: theme.component.breadcrumb.bg, margin: '0 0 0px 0', padding: '6px 0', boxShadow: '0 4px 5px 0 rgba(0,0,0,0.14), 0 1px 10px 0 rgba(0,0,0,0.12), 0 2px 4px -1px rgba(0,0,0,0.2)', zIndex: '1000', position: 'relative'};
let style2 = {margin: '0 auto', width: '95%', maxWidth: '800px', padding: '0', color: theme.component.breadcrumb.color};
return (
<div className={props.className} style={style1}>
<ul style={style2}>
@ -76,9 +76,8 @@ const BreadCrumbContainer = (props) => {
const Logout = (props) => {
let style = {
float: 'right',
fontSize: '17px',
display: 'inline-block',
padding: '6px 0px 6px 6px',
padding: '5px 0px 5px 5px',
margin: '0 0px'
}
return (
@ -109,8 +108,8 @@ const Saving = (props) => {
const Separator = (props) => {
return (
<NgIf cond={props.isLast === false} style={{display: 'inline', fontFamily: 'monospace', color: '#aaaaaa'}}>
>
<NgIf cond={props.isLast === false} style={{position: 'relative', top: '3px', display: 'inline'}}>
<img width="16" height="16" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAAA30lEQVQ4T63T7Q2CMBAG4OuVPdQNcAPdBCYwDdclCAQ3ACfRDXQDZQMHgNRcAoYApfWjv0jIPX3b3gn4wxJjI03TUAhRBkGwV0o9ffaYIEVRrJumuQHA3ReaILxzl+bCkNZ660ozi/QQIl4BoCKieAmyIlyU53lkjCld0CIyhIwxSmt9nEvkRLgoyzIuPggh4iRJqjHkhXTQAwBWUsqNUoq/38sL+TlJf7lf38ngdU5EFNme2adPFgGGrR2LiGcAqIko/LhjeXbatuVOraWUO58hnJ1iRKx8AetxXPHH/1+y62USursaSgAAAABJRU5ErkJggg=="/>
</NgIf>
);
}
@ -120,6 +119,7 @@ const Separator = (props) => {
export class PathElementWrapper extends React.Component {
constructor(props){
super(props);
this.state = {hover: false};
}
onClick(){
@ -128,24 +128,38 @@ export class PathElementWrapper extends React.Component {
}
}
toggleHover(shouldHover){
if(('ontouchstart' in window) === false){
this.setState({hover: shouldHover})
}
}
limitSize(str){
if(str.length > 30){
return str.substring(0,23)+'...'
}
return str;
}
render(){
let style = {
cursor: 'pointer',
fontSize: '17px',
cursor: this.props.isLast ? '' : 'pointer',
background: this.state.hover && this.props.isLast !== true? theme.effects.hover : 'inherit',
borderRadius: '1px',
fontSize: '18px',
display: 'inline-block',
padding: '5px 3px',
margin: '0 4px',
padding: '4px 5px',
fontWeight: this.props.isLast ? '100': ''
};
if(this.props.highlight === true){
style.background = to_rgba(theme.colors.primary, 0.5);
style.background = theme.effects.selected;
style.border = '2px solid '+theme.colors.primary;
style.borderRadius = '2px';
style.padding = '3px 20px';
style.padding = '2px 20px';
}
return (
<li onClick={this.onClick.bind(this)} style={style}>
{this.props.path.label}
<li onClick={this.onClick.bind(this)} style={style} onMouseEnter={this.toggleHover.bind(this, true)} onMouseLeave={this.toggleHover.bind(this, false)}>
{this.limitSize(this.props.path.label)}
<Saving isLast={this.props.isLast} needSaving={this.props.needSaving} isSaving={false} />
</li>
);
@ -161,7 +175,7 @@ export class PathElement extends PathElementWrapper {
render(highlight = false){
return (
<div style={{display: 'inline-block'}}>
<div style={{display: 'inline-block', color: this.props.isLast? theme.component.breadcrumb.last : 'inherit'}}>
<PathElementWrapper highlight={highlight} {...this.props} />
</div>
)

View file

@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Card, NgIf, Icon, pathBuilder, theme, to_rgba } from '../../utilities';
import { Card, NgIf, Icon, pathBuilder, theme } from '../../utilities';
import { EventEmitter } from '../../data';
import { DragSource, DropTarget } from 'react-dnd';
@ -100,7 +100,7 @@ export class ExistingThing extends React.Component {
message: props.file.message || null,
})
}
onSelect(){
if(this.state.icon !== 'loading'){
@ -127,7 +127,7 @@ export class ExistingThing extends React.Component {
this.setState({icon: 'error', message: err.message, filename: oldFilename});
});
}
onDelete(filename){
let toConfirm = this.props.file.name.length > 16? this.props.file.name.substring(0, 10).toLowerCase() : this.props.file.name;
let answer = prompt('Confirm by tapping "'+toConfirm+'"');
@ -151,20 +151,24 @@ export class ExistingThing extends React.Component {
const { connectDragSource, connectDropFile, connectDropNativeFile } = this.props;
let dragStyle = {whiteSpace: 'nowrap'};
if(this.props.isDragging) { dragStyle.opacity = 0.15; }
if(this.state.hover === true){
dragStyle.background = theme.effects.hover;
}
if((this.props.fileIsOver && this.props.canDropFile) || (this.props.nativeFileIsOver && this.props.canDropNativeFile)) {
dragStyle.background = to_rgba(theme.colors.primary, 0.5);
dragStyle.border = '2px solid '+theme.colors.primary;
dragStyle.background = theme.effects.selected;
}
return connectDragSource(connectDropNativeFile(connectDropFile(
<div>
<NgIf cond={this.state.appear}>
<Card onClick={this.onSelect.bind(this)} onMouseEnter={() => this.setState({hover: true})} onMouseLeave={() => this.setState({hover: false})} style={dragStyle}>
<DateTime show={this.state.hover !== true || this.state.icon === 'loading'} timestamp={this.props.file.time}/>
<DateTime show={this.state.hover !== true || this.state.icon === 'loading'} timestamp={this.props.file.time} background={dragStyle.background}/>
<Updater filename={this.state.filename}
icon={this.props.file.virtual? this.props.file.icon : this.state.icon}
can_move={this.props.file.can_move !== false}
can_delete={this.props.file.can_delete !== false}
background={dragStyle.background}
show={this.state.hover === true && this.state.icon !== 'loading' && !('ontouchstart' in window)}
onRename={this.onRename.bind(this)}
onDelete={this.onDelete.bind(this)} />
@ -215,7 +219,7 @@ class Updater extends React.Component {
}
}
preventSelect(e){
e.stopPropagation();
}
@ -223,7 +227,7 @@ class Updater extends React.Component {
render(){
const style = {
inline: {display: 'inline'},
el: {float: 'right', color: '#6f6f6f', height: '22px', background: 'white', margin: '0 -10px', padding: '0 10px', position: 'relative'},
el: {float: 'right', color: '#6f6f6f', height: '22px', background: this.props.background || 'white', margin: '0 -10px', padding: '0 10px', position: 'relative'},
margin: {marginRight: '10px'}
}
return (
@ -265,7 +269,7 @@ const DateTime = (props) => {
}
}
const style = {float: 'right', color: '#6f6f6f', lineHeight: '25px', background: 'white', margin: '0 -10px', padding: '0 10px', position: 'relative'};
const style = {float: 'right', color: '#6f6f6f', lineHeight: '25px', background: props.background || 'white', margin: '0 -10px', padding: '0 10px', position: 'relative'};
return (
<NgIf cond={props.show} style={style}>
@ -289,7 +293,7 @@ const FileSize = (props) => {
}
}
const style = {color: '#6f6f6f', fontSize: '0.85em'};
return (
<NgIf cond={props.type === 'file'} style={{display: 'inline-block'}}>
<span style={style}>({displaySize(props.size)})</span>

View file

@ -1,25 +1,33 @@
export const theme = {
colors: {
primary: '#9AD1ED',
secondary: '#466372',
emphasis: '#375160',
error: '#ff0000',
text: '#6f6f6f'
},
spacing: {
const palette = {
primary: '#9AD1ED',
secondary: '#466372',
emphasis: '#375160',
error: '#ff0000',
text: '#6f6f6f'
}
let _theme = {
colors: palette,
space: {
normal: '10px',
big: '20px'
},
effects: {
hover: '#f5f5f5',
selected: '#c5e2f1',
shadow_small: 'rgba(0, 0, 0, 0.14) 2px 2px 2px 0px',
shadow: 'rgba(0, 0, 0, 0.14) 0px 4px 5px 0px, rgba(0, 0, 0, 0.12) 0px 1px 10px 0px, rgba(0, 0, 0, 0.2) 0px 2px 4px -1px',
shadow_large: 'rgba(158, 163, 172, 0.3) 0px 19px 60px, rgba(158, 163, 172, 0.22) 0px 15px 20px'
},
component: {
breadcrumb: {bg: 'white', color: rgba(palette.text, 0.8), last: palette.text}
}
}
export const theme = _theme;
export const to_rgba = function(color, alpha){
function rgba(color, alpha){
const bigint = parseInt(color.replace(/^\#/, ''), 16);
const r = (bigint >> 16) & 255;
const g = (bigint >> 8) & 255;
@ -27,3 +35,4 @@ export const to_rgba = function(color, alpha){
return "rgba("+r+","+g+","+b+","+alpha+")";
}
export const to_rgba = rgba;

View file

@ -32,6 +32,14 @@ select::-ms-expand {
display: none;
}
.no-select {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.drag-drop{