mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-09 02:42:47 +00:00
12.0 support drag side nav (#6340)
* 01 optimize resize bar * 02 app side panel support resize * 03 side panel is folded do not support resize * 04 optimise code * 05 use localStorage
This commit is contained in:
@@ -9,7 +9,13 @@ import SystemNotification from './components/system-notification';
|
|||||||
import EventBus from './components/common/event-bus';
|
import EventBus from './components/common/event-bus';
|
||||||
import Header from './components/header';
|
import Header from './components/header';
|
||||||
import SidePanel from './components/side-panel';
|
import SidePanel from './components/side-panel';
|
||||||
import MainPanel from './components/main-panel';
|
import ResizeBar from './components/resize-bar';
|
||||||
|
import {
|
||||||
|
DRAG_HANDLER_HEIGHT,
|
||||||
|
INIT_SIDE_PANEL_RATE,
|
||||||
|
MAX_SIDE_PANEL_RATE,
|
||||||
|
MIN_SIDE_PANEL_RATE
|
||||||
|
} from './components/resize-bar/constants';
|
||||||
import FilesActivities from './pages/dashboard/files-activities';
|
import FilesActivities from './pages/dashboard/files-activities';
|
||||||
import MyFileActivities from './pages/dashboard/my-file-activities';
|
import MyFileActivities from './pages/dashboard/my-file-activities';
|
||||||
import Starred from './pages/starred/starred';
|
import Starred from './pages/starred/starred';
|
||||||
@@ -48,11 +54,15 @@ class App extends Component {
|
|||||||
isSidePanelFolded: localStorage.getItem('sf_user_side_nav_folded') == 'true' || false,
|
isSidePanelFolded: localStorage.getItem('sf_user_side_nav_folded') == 'true' || false,
|
||||||
currentTab: '',
|
currentTab: '',
|
||||||
pathPrefix: [],
|
pathPrefix: [],
|
||||||
|
inResizing: false,
|
||||||
|
sidePanelRate: parseFloat(localStorage.getItem('sf_side_panel_rate') || INIT_SIDE_PANEL_RATE),
|
||||||
};
|
};
|
||||||
this.dirViewPanels = ['libraries', 'my-libs', 'shared-libs', 'org']; // and group
|
this.dirViewPanels = ['libraries', 'my-libs', 'shared-libs', 'org']; // and group
|
||||||
window.onpopstate = this.onpopstate;
|
window.onpopstate = this.onpopstate;
|
||||||
const eventBus = new EventBus();
|
const eventBus = new EventBus();
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
|
this.resizeBarRef = React.createRef();
|
||||||
|
this.dragHandlerRef = React.createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
onpopstate = (event) => {
|
onpopstate = (event) => {
|
||||||
@@ -207,9 +217,53 @@ class App extends Component {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
onResizeMouseUp = () => {
|
||||||
const { currentTab, isSidePanelClosed, isSidePanelFolded } = this.state;
|
if (this.state.inResizing) {
|
||||||
|
this.setState({
|
||||||
|
inResizing: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
localStorage.setItem('sf_side_panel_rate', this.state.sidePanelRate);
|
||||||
|
};
|
||||||
|
|
||||||
|
onResizeMouseDown = () => {
|
||||||
|
this.setState({
|
||||||
|
inResizing: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onResizeMouseMove = (e) => {
|
||||||
|
let rate = e.nativeEvent.clientX / window.innerWidth;
|
||||||
|
this.setState({
|
||||||
|
sidePanelRate: Math.max(Math.min(rate, MAX_SIDE_PANEL_RATE), MIN_SIDE_PANEL_RATE),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onResizeMouseOver = (event) => {
|
||||||
|
if (!this.dragHandlerRef.current) return;
|
||||||
|
const { top } = this.resizeBarRef.current.getBoundingClientRect();
|
||||||
|
const dragHandlerRefTop = event.pageY - top - DRAG_HANDLER_HEIGHT / 2;
|
||||||
|
this.setDragHandlerTop(dragHandlerRefTop);
|
||||||
|
};
|
||||||
|
|
||||||
|
setDragHandlerTop = (top) => {
|
||||||
|
this.dragHandlerRef.current.style.top = top + 'px';
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { currentTab, isSidePanelClosed, isSidePanelFolded, sidePanelRate, inResizing } = this.state;
|
||||||
|
let mainPanelStyle = {};
|
||||||
|
let sidePanelStyle = {};
|
||||||
|
if (!isSidePanelFolded) {
|
||||||
|
mainPanelStyle = {
|
||||||
|
userSelect: inResizing ? 'none' : '',
|
||||||
|
flex: sidePanelRate ? `1 0 ${(1 - sidePanelRate) * 100}%` : `0 0 ${100 - INIT_SIDE_PANEL_RATE * 100}%`,
|
||||||
|
};
|
||||||
|
sidePanelStyle = {
|
||||||
|
userSelect: inResizing ? 'none' : '',
|
||||||
|
flex: sidePanelRate ? `0 0 ${sidePanelRate * 100}%` : `0 0 ${INIT_SIDE_PANEL_RATE * 100}%`,
|
||||||
|
};
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<SystemNotification />
|
<SystemNotification />
|
||||||
@@ -220,7 +274,12 @@ class App extends Component {
|
|||||||
onSearchedClick={this.onSearchedClick}
|
onSearchedClick={this.onSearchedClick}
|
||||||
eventBus={this.eventBus}
|
eventBus={this.eventBus}
|
||||||
/>
|
/>
|
||||||
<div id="main" className="user-panel">
|
<div
|
||||||
|
id="main"
|
||||||
|
className="user-panel"
|
||||||
|
onMouseMove={inResizing ? this.onResizeMouseMove : null}
|
||||||
|
onMouseUp={this.onResizeMouseUp}
|
||||||
|
>
|
||||||
<SidePanel
|
<SidePanel
|
||||||
isSidePanelClosed={isSidePanelClosed}
|
isSidePanelClosed={isSidePanelClosed}
|
||||||
isSidePanelFolded={isSidePanelFolded}
|
isSidePanelFolded={isSidePanelFolded}
|
||||||
@@ -228,8 +287,19 @@ class App extends Component {
|
|||||||
currentTab={currentTab}
|
currentTab={currentTab}
|
||||||
tabItemClick={this.tabItemClick}
|
tabItemClick={this.tabItemClick}
|
||||||
toggleFoldSideNav={this.toggleFoldSideNav}
|
toggleFoldSideNav={this.toggleFoldSideNav}
|
||||||
|
style={sidePanelStyle}
|
||||||
/>
|
/>
|
||||||
<MainPanel>
|
{!isSidePanelFolded &&
|
||||||
|
<ResizeBar
|
||||||
|
resizeBarRef={this.resizeBarRef}
|
||||||
|
dragHandlerRef={this.dragHandlerRef}
|
||||||
|
resizeBarStyle={{ left: `calc(${sidePanelRate ? sidePanelRate * 100 + '%' : `${INIT_SIDE_PANEL_RATE * 100}%`} - 1px)` }}
|
||||||
|
dragHandlerStyle={{ height: DRAG_HANDLER_HEIGHT }}
|
||||||
|
onResizeMouseDown={this.onResizeMouseDown}
|
||||||
|
onResizeMouseOver={this.onResizeMouseOver}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
<div className="main-panel" style={mainPanelStyle}>
|
||||||
<Router className="reach-router">
|
<Router className="reach-router">
|
||||||
<Libraries path={siteRoot} />
|
<Libraries path={siteRoot} />
|
||||||
<Libraries path={siteRoot + 'libraries'} />
|
<Libraries path={siteRoot + 'libraries'} />
|
||||||
@@ -263,7 +333,7 @@ class App extends Component {
|
|||||||
eventBus={this.eventBus}
|
eventBus={this.eventBus}
|
||||||
/>
|
/>
|
||||||
</Router>
|
</Router>
|
||||||
</MainPanel>
|
</div>
|
||||||
<MediaQuery query="(max-width: 767.8px)">
|
<MediaQuery query="(max-width: 767.8px)">
|
||||||
<Modal zIndex="1030" isOpen={!isSidePanelClosed} toggle={this.toggleSidePanel} contentClassName="d-none"></Modal>
|
<Modal zIndex="1030" isOpen={!isSidePanelClosed} toggle={this.toggleSidePanel} contentClassName="d-none"></Modal>
|
||||||
</MediaQuery>
|
</MediaQuery>
|
||||||
|
@@ -5,6 +5,8 @@ import DirColumnFile from './dir-column-file';
|
|||||||
import DirListView from './dir-list-view';
|
import DirListView from './dir-list-view';
|
||||||
import DirGridView from './dir-grid-view';
|
import DirGridView from './dir-grid-view';
|
||||||
import { SIDE_PANEL_FOLDED_WIDTH } from '../../constants';
|
import { SIDE_PANEL_FOLDED_WIDTH } from '../../constants';
|
||||||
|
import ResizeBar from '../resize-bar';
|
||||||
|
import { DRAG_HANDLER_HEIGHT, MAX_SIDE_PANEL_RATE, MIN_SIDE_PANEL_RATE } from '../resize-bar/constants';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
isSidePanelFolded: PropTypes.bool,
|
isSidePanelFolded: PropTypes.bool,
|
||||||
@@ -73,19 +75,17 @@ const propTypes = {
|
|||||||
isDirentDetailShow: PropTypes.bool.isRequired
|
isDirentDetailShow: PropTypes.bool.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
const DRAG_HANDLER_HEIGHT = 26;
|
|
||||||
|
|
||||||
class DirColumnView extends React.Component {
|
class DirColumnView extends React.Component {
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
inResizing: false,
|
inResizing: false,
|
||||||
navRate: 0.25,
|
navRate: parseFloat(localStorage.getItem('sf_dir_content_nav_rate') || 0.25),
|
||||||
};
|
};
|
||||||
this.containerWidth = null;
|
this.containerWidth = null;
|
||||||
this.resizeRef = null;
|
this.resizeBarRef = React.createRef();
|
||||||
this.dragHandler = null;
|
this.dragHandlerRef = React.createRef();
|
||||||
this.viewModeContainer = React.createRef();
|
this.viewModeContainer = React.createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ class DirColumnView extends React.Component {
|
|||||||
inResizing: false
|
inResizing: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.setCookie('navRate', this.state.navRate);
|
localStorage.setItem('sf_dir_content_nav_rate', this.state.navRate);
|
||||||
};
|
};
|
||||||
|
|
||||||
onResizeMouseDown = () => {
|
onResizeMouseDown = () => {
|
||||||
@@ -107,65 +107,24 @@ class DirColumnView extends React.Component {
|
|||||||
|
|
||||||
onResizeMouseMove = (e) => {
|
onResizeMouseMove = (e) => {
|
||||||
const { isSidePanelFolded } = this.props;
|
const { isSidePanelFolded } = this.props;
|
||||||
let sizeNavWidth = isSidePanelFolded ? SIDE_PANEL_FOLDED_WIDTH + 3 : this.containerWidth / 0.78 * 0.22 + 3;
|
let sizeNavWidth = isSidePanelFolded ? SIDE_PANEL_FOLDED_WIDTH + 3 : window.innerWidth - this.containerWidth;
|
||||||
|
|
||||||
let rate = (e.nativeEvent.clientX - sizeNavWidth) / this.containerWidth;
|
let rate = (e.nativeEvent.clientX - sizeNavWidth) / this.containerWidth;
|
||||||
if (rate < 0.1) {
|
this.setState({
|
||||||
this.setState({
|
navRate: Math.max(Math.min(rate, MAX_SIDE_PANEL_RATE), MIN_SIDE_PANEL_RATE),
|
||||||
inResizing: false,
|
});
|
||||||
navRate: 0.12,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (rate > 0.4) {
|
|
||||||
this.setState({
|
|
||||||
inResizing: false,
|
|
||||||
navRate: 0.38,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.setState({
|
|
||||||
navRate: rate
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onMouseOver = (event) => {
|
onResizeMouseOver = (event) => {
|
||||||
if (!this.dragHandler) return;
|
if (!this.dragHandlerRef.current) return;
|
||||||
const { top } = this.resizeRef.getBoundingClientRect();
|
const { top } = this.resizeBarRef.current.getBoundingClientRect();
|
||||||
const dragHandlerTop = event.pageY - top - DRAG_HANDLER_HEIGHT / 2;
|
const dragHandlerRefTop = event.pageY - top - DRAG_HANDLER_HEIGHT / 2;
|
||||||
this.setDragHandlerTop(dragHandlerTop);
|
this.setDragHandlerTop(dragHandlerRefTop);
|
||||||
};
|
};
|
||||||
|
|
||||||
setDragHandlerTop = (top) => {
|
setDragHandlerTop = (top) => {
|
||||||
this.dragHandler.style.top = top + 'px';
|
this.dragHandlerRef.current.style.top = top + 'px';
|
||||||
};
|
};
|
||||||
|
|
||||||
setCookie = (name, value) => {
|
|
||||||
let cookie = name + '=' + value + ';';
|
|
||||||
document.cookie = cookie;
|
|
||||||
};
|
|
||||||
|
|
||||||
getCookie = (cookiename) => {
|
|
||||||
let name = cookiename + '=';
|
|
||||||
let cookie = document.cookie.split(';');
|
|
||||||
for (let i = 0, len = cookie.length; i < len; i++) {
|
|
||||||
let c = cookie[i].trim();
|
|
||||||
if (c.indexOf(name) == 0) {
|
|
||||||
return c.substring(name.length, c.length) * 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
};
|
|
||||||
|
|
||||||
UNSAFE_componentWillMount() {
|
|
||||||
let rate = this.getCookie('navRate');
|
|
||||||
if (rate) {
|
|
||||||
this.setState({
|
|
||||||
navRate: rate,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { currentMode, isTreePanelShown } = this.props;
|
const { currentMode, isTreePanelShown } = this.props;
|
||||||
const { navRate, inResizing } = this.state;
|
const { navRate, inResizing } = this.state;
|
||||||
@@ -198,16 +157,14 @@ class DirColumnView extends React.Component {
|
|||||||
selectedDirentList={this.props.selectedDirentList}
|
selectedDirentList={this.props.selectedDirentList}
|
||||||
onItemsMove={this.props.onItemsMove}
|
onItemsMove={this.props.onItemsMove}
|
||||||
/>
|
/>
|
||||||
<div
|
<ResizeBar
|
||||||
className="dir-content-resize"
|
resizeBarRef={this.resizeBarRef}
|
||||||
ref={ref => this.resizeRef = ref}
|
dragHandlerRef={this.dragHandlerRef}
|
||||||
style={{ left: `calc(${navRate ? navRate * 100 + '%' : '25%'} - 1px)` }}
|
resizeBarStyle={{ left: `calc(${navRate ? navRate * 100 + '%' : '25%'} - 1px)` }}
|
||||||
onMouseDown={this.onResizeMouseDown}
|
dragHandlerStyle={{ height: DRAG_HANDLER_HEIGHT }}
|
||||||
onMouseOver={this.onMouseOver}
|
onResizeMouseDown={this.onResizeMouseDown}
|
||||||
>
|
onResizeMouseOver={this.onResizeMouseOver}
|
||||||
<div className="line"></div>
|
/>
|
||||||
<div className="drag-handler" ref={ref => this.dragHandler = ref} style={{ height: DRAG_HANDLER_HEIGHT }}></div>
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<div className="dir-content-main" style={{userSelect: select, flex: mainFlex}} onScroll={this.props.isViewFile ? () => {} : this.props.onItemsScroll}>
|
<div className="dir-content-main" style={{userSelect: select, flex: mainFlex}} onScroll={this.props.isViewFile ? () => {} : this.props.onItemsScroll}>
|
||||||
|
4
frontend/src/components/resize-bar/constants.js
Normal file
4
frontend/src/components/resize-bar/constants.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export const DRAG_HANDLER_HEIGHT = 26;
|
||||||
|
export const INIT_SIDE_PANEL_RATE = 0.22;
|
||||||
|
export const MAX_SIDE_PANEL_RATE = 0.40;
|
||||||
|
export const MIN_SIDE_PANEL_RATE = 0.15;
|
43
frontend/src/components/resize-bar/index.css
Normal file
43
frontend/src/components/resize-bar/index.css
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
.resize-bar {
|
||||||
|
height: 100%;
|
||||||
|
width: 6px;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
z-index: 8;
|
||||||
|
opacity: 0;
|
||||||
|
transition-duration: .2s;
|
||||||
|
transition-property: opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resize-bar:hover {
|
||||||
|
opacity: 1;
|
||||||
|
cursor: col-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resize-bar .resize-bar-line {
|
||||||
|
background-color: #aaa;
|
||||||
|
height: 100%;
|
||||||
|
width: 2px;
|
||||||
|
display: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resize-bar:hover .resize-bar-line {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resize-bar .resize-bar-drag-handler {
|
||||||
|
background: #2d7ff9;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin-left: 1px;
|
||||||
|
position: absolute;
|
||||||
|
transform: translate(-50%);
|
||||||
|
width: 6px;
|
||||||
|
display: none;
|
||||||
|
z-index: 1;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resize-bar:hover .resize-bar-drag-handler {
|
||||||
|
display: block;
|
||||||
|
}
|
29
frontend/src/components/resize-bar/index.js
Normal file
29
frontend/src/components/resize-bar/index.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import './index.css';
|
||||||
|
|
||||||
|
function ResizeBar(props) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="resize-bar"
|
||||||
|
ref={props.resizeBarRef}
|
||||||
|
style={props.resizeBarStyle}
|
||||||
|
onMouseDown={props.onResizeMouseDown}
|
||||||
|
onMouseOver={props.onResizeMouseOver}
|
||||||
|
>
|
||||||
|
<div className="resize-bar-line"></div>
|
||||||
|
<div className="resize-bar-drag-handler" ref={props.dragHandlerRef} style={props.dragHandlerStyle}></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResizeBar.propTypes = {
|
||||||
|
resizeBarRef: PropTypes.object.isRequired,
|
||||||
|
resizeBarStyle: PropTypes.object.isRequired,
|
||||||
|
dragHandlerRef: PropTypes.object.isRequired,
|
||||||
|
dragHandlerStyle: PropTypes.object.isRequired,
|
||||||
|
onResizeMouseDown: PropTypes.func.isRequired,
|
||||||
|
onResizeMouseOver: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ResizeBar;
|
@@ -12,6 +12,7 @@ const propTypes = {
|
|||||||
onCloseSidePanel: PropTypes.func,
|
onCloseSidePanel: PropTypes.func,
|
||||||
tabItemClick: PropTypes.func,
|
tabItemClick: PropTypes.func,
|
||||||
children: PropTypes.object,
|
children: PropTypes.object,
|
||||||
|
style: PropTypes.object,
|
||||||
isSidePanelFolded: PropTypes.bool,
|
isSidePanelFolded: PropTypes.bool,
|
||||||
toggleFoldSideNav: PropTypes.func
|
toggleFoldSideNav: PropTypes.func
|
||||||
};
|
};
|
||||||
@@ -19,10 +20,12 @@ const propTypes = {
|
|||||||
class SidePanel extends React.Component {
|
class SidePanel extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { children, isSidePanelFolded } = this.props;
|
const { children, isSidePanelFolded, style } = this.props;
|
||||||
const style = isSidePanelFolded ? { flexBasis: SIDE_PANEL_FOLDED_WIDTH } : {};
|
|
||||||
return (
|
return (
|
||||||
<div className={classnames('side-panel', { 'side-panel-folded': isSidePanelFolded, 'left-zero': !this.props.isSidePanelClosed })} style={style}>
|
<div
|
||||||
|
className={classnames('side-panel', {'side-panel-folded': isSidePanelFolded, 'left-zero': !this.props.isSidePanelClosed})}
|
||||||
|
style={isSidePanelFolded ? { flexBasis: SIDE_PANEL_FOLDED_WIDTH } : style}
|
||||||
|
>
|
||||||
<MediaQuery query="(max-width: 767.8px)">
|
<MediaQuery query="(max-width: 767.8px)">
|
||||||
<div className='side-panel-north'>
|
<div className='side-panel-north'>
|
||||||
<Logo onCloseSidePanel={this.props.onCloseSidePanel} />
|
<Logo onCloseSidePanel={this.props.onCloseSidePanel} />
|
||||||
|
@@ -224,50 +224,6 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dir-content-resize {
|
|
||||||
height: 100%;
|
|
||||||
width: 6px;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
z-index: 8;
|
|
||||||
opacity: 0;
|
|
||||||
transition-duration: .2s;
|
|
||||||
transition-property: opacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dir-content-resize:hover {
|
|
||||||
opacity: 1;
|
|
||||||
cursor: col-resize;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dir-content-resize .line {
|
|
||||||
background-color: #aaa;
|
|
||||||
height: 100%;
|
|
||||||
width: 2px;
|
|
||||||
display: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dir-content-resize:hover .line {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dir-content-resize .drag-handler {
|
|
||||||
background: #2d7ff9;
|
|
||||||
border-radius: 10px;
|
|
||||||
margin-left: 1px;
|
|
||||||
position: absolute;
|
|
||||||
transform: translate(-50%);
|
|
||||||
width: 6px;
|
|
||||||
display: none;
|
|
||||||
z-index: 1;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dir-content-resize:hover .drag-handler {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.readonly-tip-message {
|
.readonly-tip-message {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0.25rem 0;
|
padding: 0.25rem 0;
|
||||||
|
Reference in New Issue
Block a user