Add threesizer division header with collapsible title
parent
6aa9501814
commit
5f8564ffa2
|
@ -1,5 +1,6 @@
|
|||
import React, {PureComponent, ReactElement, MouseEvent} from 'react'
|
||||
import classnames from 'classnames'
|
||||
import calculateSize from 'calculate-size'
|
||||
|
||||
import {HANDLE_VERTICAL, HANDLE_HORIZONTAL} from 'src/shared/constants/index'
|
||||
|
||||
|
@ -26,26 +27,49 @@ class Division extends PureComponent<Props> {
|
|||
handleDisplay: 'visible',
|
||||
}
|
||||
|
||||
private collapseThreshold: number = 0
|
||||
private containerRef: HTMLElement
|
||||
|
||||
public componentDidMount() {
|
||||
const {name} = this.props
|
||||
|
||||
if (!name) {
|
||||
return 0
|
||||
}
|
||||
|
||||
const {width} = calculateSize(name, {
|
||||
font: '"Roboto", Helvetica, Arial, Tahoma, Verdana, sans-serif',
|
||||
fontSize: '16px',
|
||||
fontWeight: '500',
|
||||
})
|
||||
const NAME_OFFSET = 66
|
||||
|
||||
this.collapseThreshold = width + NAME_OFFSET
|
||||
}
|
||||
|
||||
public render() {
|
||||
const {name, render, draggable} = this.props
|
||||
return (
|
||||
<>
|
||||
<div className={this.containerClass} style={this.containerStyle}>
|
||||
<div
|
||||
style={this.handleStyle}
|
||||
title={this.title}
|
||||
draggable={draggable}
|
||||
onDragStart={this.drag}
|
||||
className={this.handleClass}
|
||||
onDoubleClick={this.handleDoubleClick}
|
||||
>
|
||||
<div className="threesizer--title">{name}</div>
|
||||
</div>
|
||||
<div className={this.contentsClass} style={this.contentStyle}>
|
||||
{render()}
|
||||
</div>
|
||||
<div
|
||||
className={this.containerClass}
|
||||
style={this.containerStyle}
|
||||
ref={r => (this.containerRef = r)}
|
||||
>
|
||||
<div
|
||||
style={this.handleStyle}
|
||||
title={this.title}
|
||||
draggable={draggable}
|
||||
onDragStart={this.drag}
|
||||
className={this.handleClass}
|
||||
onDoubleClick={this.handleDoubleClick}
|
||||
>
|
||||
<div className={this.titleClass}>{name}</div>
|
||||
</div>
|
||||
</>
|
||||
<div className={this.contentsClass} style={this.contentStyle}>
|
||||
{name && <div className="threesizer--header" />}
|
||||
<div className="threesizer--body">{render()}</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -134,6 +158,32 @@ class Division extends PureComponent<Props> {
|
|||
})
|
||||
}
|
||||
|
||||
private get titleClass(): string {
|
||||
const {orientation} = this.props
|
||||
|
||||
const collapsed = orientation === HANDLE_VERTICAL && this.isTitleObscured
|
||||
|
||||
return classnames('threesizer--title', {
|
||||
'threesizer--collapsed': collapsed,
|
||||
vertical: orientation === HANDLE_VERTICAL,
|
||||
horizontal: orientation === HANDLE_HORIZONTAL,
|
||||
})
|
||||
}
|
||||
|
||||
private get isTitleObscured(): boolean {
|
||||
if (this.props.size === 0) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (!this.containerRef || this.props.size === 1) {
|
||||
return false
|
||||
}
|
||||
|
||||
const {width} = this.containerRef.getBoundingClientRect()
|
||||
|
||||
return width <= this.collapseThreshold
|
||||
}
|
||||
|
||||
private get isDragging(): boolean {
|
||||
const {id, activeHandleID} = this.props
|
||||
return id === activeHandleID
|
||||
|
|
|
@ -52,7 +52,6 @@ $threesizer-handle: 30px;
|
|||
transition: background-color 0.25s ease, color 0.25s ease;
|
||||
|
||||
&.vertical {
|
||||
padding: 12px 0;
|
||||
border-right: solid 2px $g3-castle;
|
||||
|
||||
&:hover,
|
||||
|
@ -62,7 +61,6 @@ $threesizer-handle: 30px;
|
|||
}
|
||||
|
||||
&.horizontal {
|
||||
padding: 0 12px;
|
||||
border-bottom: solid 2px $g3-castle;
|
||||
|
||||
&:hover,
|
||||
|
@ -85,20 +83,23 @@ $threesizer-handle: 30px;
|
|||
background-color: $g5-pepper;
|
||||
}
|
||||
}
|
||||
// First Handle should not have a outside facing border
|
||||
// .threesizer:first-child .threesizer--division .threesizer--handle {
|
||||
// border-top: 0;
|
||||
// border-left: 0;
|
||||
// }
|
||||
|
||||
.threesizer--title {
|
||||
font-size: 13px;
|
||||
padding-left: 14px;
|
||||
position: relative;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
color: $g11-sidewalk;
|
||||
z-index: 1;
|
||||
transition: transform 0.25s ease;
|
||||
|
||||
.vertical & {
|
||||
transform: rotate(90deg) translateX(8px);
|
||||
&.vertical {
|
||||
transform: translate(28px, 14px);
|
||||
|
||||
&.threesizer--collapsed {
|
||||
transform: translate(0, 3px) rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,8 +109,19 @@ $threesizer-shadow-start: fade-out($g0-obsidian, 0.82);
|
|||
$threesizer-shadow-stop: fade-out($g0-obsidian, 1);
|
||||
|
||||
.threesizer--contents {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
flex-wrap: nowrap;
|
||||
position: relative;
|
||||
|
||||
&.horizontal {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
&.vertical {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
// Bottom Shadow
|
||||
&.horizontal:after,
|
||||
&.vertical:after {
|
||||
|
@ -140,3 +152,22 @@ $threesizer-shadow-stop: fade-out($g0-obsidian, 1);
|
|||
content: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Header
|
||||
.threesizer--header {
|
||||
background-color: $g2-kevlar;
|
||||
|
||||
.horizontal > & {
|
||||
width: 50px;
|
||||
border-right: 2px solid $g4-onyx;
|
||||
}
|
||||
|
||||
.vertical > & {
|
||||
height: 50px;
|
||||
border-bottom: 2px solid $g4-onyx;
|
||||
}
|
||||
}
|
||||
|
||||
.threesizer--body {
|
||||
flex: 1 0 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue