Update Settings to use Popout & Button

main
raboid 6 years ago committed by Michael Fix
parent 7a5145135c
commit 6da617b553

@ -1,15 +1,14 @@
import React from 'react' import React from 'react'
import enhanceWithClickOutside from 'react-click-outside'
import omitBy from 'lodash.omitby' import omitBy from 'lodash.omitby'
import ThemeSelect from './ThemeSelect' import ThemeSelect from './ThemeSelect'
import FontSelect from './FontSelect' import FontSelect from './FontSelect'
import Slider from './Slider' import Slider from './Slider'
import Toggle from './Toggle' import Toggle from './Toggle'
import WindowPointer from './WindowPointer' import Popout from './Popout'
import Button from './Button'
import { COLORS, DEFAULT_PRESETS } from '../lib/constants' import { COLORS, DEFAULT_PRESETS } from '../lib/constants'
import { getPresets, savePresets } from '../lib/util' import { toggle, getPresets, savePresets } from '../lib/util'
import { toggle } from '../lib/util'
import SettingsIcon from './svg/Settings' import SettingsIcon from './svg/Settings'
import * as Arrows from './svg/Arrows' import * as Arrows from './svg/Arrows'
import Remove from './svg/Remove' import Remove from './svg/Remove'
@ -134,35 +133,25 @@ const TypeSettings = React.memo(
} }
) )
const resetButtonStyle = { borderTop: `1px solid ${COLORS.SECONDARY}` }
const MiscSettings = React.memo(({ format, reset }) => { const MiscSettings = React.memo(({ format, reset }) => {
return ( return (
<div className="settings-content"> <div className="settings-content">
<button onClick={format}>Prettify code</button> <Button center title="Prettify code" onClick={format} />
<button onClick={reset} className="reset-button"> <Button
Reset settings center
</button> title="Reset settings"
color={COLORS.RED}
onClick={reset}
style={resetButtonStyle}
/>
<style jsx> <style jsx>
{` {`
button {
outline: none;
border: none;
background: transparent;
cursor: pointer;
flex: 1;
color: ${COLORS.SECONDARY};
font-size: 12px;
padding: 0;
}
.settings-content { .settings-content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.reset-button {
border-top: 1px solid ${COLORS.SECONDARY};
color: ${COLORS.RED};
}
`} `}
</style> </style>
</div> </div>
@ -171,37 +160,31 @@ const MiscSettings = React.memo(({ format, reset }) => {
const MenuButton = React.memo(({ name, select, selected }) => { const MenuButton = React.memo(({ name, select, selected }) => {
return ( return (
<button onClick={select(name)} className={selected === name ? 'selected' : ''}> <div className="menu-button">
{name} <Button
<div className="arrow-icon"> padding="8px"
<Arrows.Right /> onClick={select(name)}
</div> background={selected === name ? COLORS.BLACK : COLORS.DARK_GRAY}
>
{name}
<div className="arrow-icon">
<Arrows.Right />
</div>
</Button>
<style jsx> <style jsx>
{` {`
button { .menu-button {
outline: none;
border: none;
background: transparent;
color: ${COLORS.SECONDARY};
display: flex; display: flex;
padding: 8px;
height: 33px; height: 33px;
line-height: 0;
cursor: pointer;
font-size: 14px;
border-bottom: 1px solid ${COLORS.SECONDARY}; border-bottom: 1px solid ${COLORS.SECONDARY};
position: relative; position: relative;
align-items: center; align-items: center;
} }
button:last-child { .menu-button:last-child {
${selected === 'Window' ? '' : 'border-bottom: none;'}; ${selected === 'Window' ? '' : 'border-bottom: none;'};
} }
button.selected {
background-color: ${COLORS.BLACK};
}
.arrow-icon { .arrow-icon {
position: absolute; position: absolute;
right: 14px; right: 14px;
@ -209,71 +192,70 @@ const MenuButton = React.memo(({ name, select, selected }) => {
} }
`} `}
</style> </style>
</button> </div>
)
})
const removeButtonStyles = {
position: 'absolute',
top: '6px',
right: '6px',
width: '11px',
height: '11px',
borderRadius: '999px'
}
const Preset = React.memo(({ remove, apply, selected, preset }) => {
const isSelected = preset.id === selected
return (
<div className="preset-container">
<Button
onClick={() => apply(preset)}
disabled={isSelected}
border={isSelected}
selected={isSelected}
hoverBackground={preset.backgroundColor}
style={{
height: '96px',
backgroundRepeat: 'no-repeat',
backgroundPosition: 'center center',
backgroundSize: 'contain',
backgroundImage: `url('${preset.icon}')`,
backgroundColor: preset.backgroundColor
}}
/>
{preset.custom && (
<Button
center
hoverBackground={COLORS.SECONDARY}
background={COLORS.SECONDARY}
onClick={() => remove(preset.id)}
style={removeButtonStyles}
>
<Remove />
</Button>
)}
<style jsx>
{`
.preset-container {
display: flex;
position: relative;
flex: 0 0 96px;
margin-right: 8px;
}
`}
</style>
</div>
) )
}) })
const Preset = React.memo(({ remove, apply, selected, preset }) => ( const arrowButtonStyle = {
<div className="preset-container"> position: 'absolute',
<button top: 0,
className="preset-tile" right: '16px',
onClick={() => apply(preset)} height: '100%'
disabled={preset.id === selected} }
/>
{preset.custom ? (
<button className="preset-remove" onClick={() => remove(preset.id)}>
<Remove />
</button>
) : null}
<style jsx>
{`
button {
outline: none;
border: none;
background: transparent;
cursor: pointer;
padding: 0;
}
.preset-container {
display: flex;
position: relative;
flex: 0 0 96px;
height: 96px;
margin-right: 8px;
}
.preset-tile {
flex: 1;
border-radius: 3px;
background-repeat: no-repeat;
background-position: center center;
background-size: contain;
cursor: ${preset.id === selected ? 'initial' : 'pointer'};
background-image: ${`url('${preset.icon}')`};
background-color: ${preset.icon ? 'initial' : preset.backgroundColor};
box-shadow: ${preset.id === selected
? `inset 0px 0px 0px 2px ${COLORS.SECONDARY}`
: 'initial'};
}
.preset-remove {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
padding: 0;
top: 6px;
right: 6px;
width: 11px;
height: 11px;
border-radius: 999px;
background-color: ${COLORS.SECONDARY};
}
`}
</style>
</div>
))
const Presets = React.memo( const Presets = React.memo(
({ show, create, toggle, undo, presets, selected, remove, apply, applied, contentRef }) => { ({ show, create, toggle, undo, presets, selected, remove, apply, applied, contentRef }) => {
@ -286,15 +268,22 @@ const Presets = React.memo(
<div className="settings-presets-header"> <div className="settings-presets-header">
<span>Presets</span> <span>Presets</span>
{show && ( {show && (
<button className="settings-presets-create" onClick={create} disabled={disabledCreate}> <Button
create + title="create +"
</button> margin="0 0 0 8px"
flex="0 0 48px"
color={COLORS.GRAY}
hoverBackground="transparent"
hoverColor={disabledCreate ? COLORS.GRAY : COLORS.SECONDARY}
onClick={create}
notAllowed={disabledCreate}
/>
)} )}
<button className="settings-presets-arrow" onClick={toggle}> <Button center onClick={toggle} style={arrowButtonStyle} hoverBackground={COLORS.BLACK}>
{show ? <Arrows.Up /> : <Arrows.Down />} {show ? <Arrows.Up /> : <Arrows.Down />}
</button> </Button>
</div> </div>
{show ? ( {show && (
<div className="settings-presets-content" ref={contentRef}> <div className="settings-presets-content" ref={contentRef}>
{presets {presets
.filter(p => p.custom) .filter(p => p.custom)
@ -314,32 +303,31 @@ const Presets = React.memo(
<Preset key={preset.id} apply={apply} preset={preset} selected={selected} /> <Preset key={preset.id} apply={apply} preset={preset} selected={selected} />
))} ))}
</div> </div>
) : null} )}
{show && applied ? ( {show && applied && (
<div className="settings-presets-applied"> <div className="settings-presets-applied">
<span>Preset applied!</span> <span>Preset applied!</span>
<button onClick={undo}> <Button
center
flex="0"
onClick={undo}
color={COLORS.BLACK}
hoverBackground="transparent"
background="transparent"
>
undo <span>&#x21A9;</span> undo <span>&#x21A9;</span>
</button> </Button>
</div> </div>
) : null} )}
<style jsx> <style jsx>
{` {`
button {
outline: none;
border: none;
background: transparent;
cursor: pointer;
padding: 0;
}
.settings-presets { .settings-presets {
border-bottom: 2px solid ${COLORS.SECONDARY}; border-bottom: 2px solid ${COLORS.SECONDARY};
} }
.settings-presets-header { .settings-presets-header {
display: flex; display: flex;
padding: 8px 8px; padding: 8px;
position: relative; position: relative;
color: ${COLORS.SECONDARY}; color: ${COLORS.SECONDARY};
width: 100%; width: 100%;
@ -350,33 +338,6 @@ const Presets = React.memo(
font-size: 14px; font-size: 14px;
} }
.settings-presets-arrow,
.settings-presets-create,
.settings-presets-remove {
cursor: pointer;
background: transparent;
outline: none;
border: none;
font-size: 12px;
}
.settings-presets-create {
line-height: 1;
color: ${COLORS.GRAY};
padding: 0 8px;
cursor: ${disabledCreate ? 'not-allowed' : 'pointer'};
}
.settings-presets-create:enabled:hover {
color: ${COLORS.SECONDARY};
}
.settings-presets-arrow {
display: flex;
position: absolute;
right: 16px;
}
.settings-presets-content { .settings-presets-content {
display: flex; display: flex;
overflow-x: scroll; overflow-x: scroll;
@ -399,18 +360,13 @@ const Presets = React.memo(
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
background-color: ${COLORS.SECONDARY}; background-color: ${COLORS.SECONDARY};
width: 100%;
color: ${COLORS.BLACK}; color: ${COLORS.BLACK};
padding: 4px 8px; padding: 4px 8px;
} }
.settings-presets-applied button { .settings-presets-applied span {
float: right;
}
.settings-presets-applied button span {
float: right; float: right;
margin: 1px 0 0 2px; margin: 2px 0 0 2px;
} }
`} `}
</style> </style>
@ -419,6 +375,11 @@ const Presets = React.memo(
} }
) )
const settingButtonStyle = {
width: '40px',
height: '100%'
}
class Settings extends React.PureComponent { class Settings extends React.PureComponent {
state = { state = {
presets: DEFAULT_PRESETS, presets: DEFAULT_PRESETS,
@ -440,17 +401,18 @@ class Settings extends React.PureComponent {
})) }))
} }
toggleVisible = () => this.setState(toggle('isVisible')) toggleVisible = e => {
e.stopPropagation()
this.setState(toggle('isVisible'))
}
togglePresets = () => this.setState(toggle('showPresets')) togglePresets = () => this.setState(toggle('showPresets'))
handleClickOutside = () => this.setState({ isVisible: false })
selectMenu = selectedMenu => () => this.setState({ selectedMenu }) selectMenu = selectedMenu => () => this.setState({ selectedMenu })
handleWidthChanging = () => { handleWidthChanging = () => {
const rect = this.settingsRef.current.getBoundingClientRect() const rect = this.settingsRef.current.getBoundingClientRect()
this.settingPosition = { top: rect.bottom + 12, left: rect.left } this.settingPosition = { top: rect.bottom, left: rect.left }
this.setState({ widthChanging: true }) this.setState({ widthChanging: true })
} }
@ -575,14 +537,26 @@ class Settings extends React.PureComponent {
return ( return (
<div className="settings-container" ref={this.settingsRef}> <div className="settings-container" ref={this.settingsRef}>
<div <Button
className={`settings-display ${isVisible ? 'is-visible' : ''}`} border
center
selected={isVisible}
style={settingButtonStyle}
onClick={this.toggleVisible} onClick={this.toggleVisible}
> >
<SettingsIcon /> <SettingsIcon />
</div> </Button>
<div className="settings-settings"> <Popout
<WindowPointer fromLeft="15px" /> pointerLeft="15px"
onClickOutside={this.toggleVisible}
hidden={!isVisible}
style={{
position: widthChanging ? 'fixed' : 'absolute',
width: '316px',
top: widthChanging ? this.settingPosition.top : 'initial',
left: widthChanging ? this.settingPosition.left : 'initial'
}}
>
<Presets <Presets
show={showPresets} show={showPresets}
presets={presets} presets={presets}
@ -603,56 +577,11 @@ class Settings extends React.PureComponent {
</div> </div>
{this.renderContent()} {this.renderContent()}
</div> </div>
</div> </Popout>
<style jsx> <style jsx>
{` {`
.settings-container { .settings-container {
display: flex;
position: relative; position: relative;
height: 100%;
width: 40px;
align-items: center;
justify-content: center;
border-radius: 3px;
color: #fff;
font-size: 12px;
}
.settings-display {
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
border: 1px solid ${COLORS.SECONDARY};
border-radius: 3px;
user-select: none;
position: relative;
z-index: 1;
cursor: pointer;
}
.settings-display.is-visible {
border-width: 2px;
}
.settings-display:hover {
background: ${COLORS.HOVER};
}
.is-visible + .settings-settings {
display: block;
}
.settings-settings {
display: none;
position: ${widthChanging ? 'fixed' : 'absolute'};
top: ${widthChanging ? this.settingPosition.top : 52}px;
left: ${widthChanging ? this.settingPosition.left : 0}px;
border: 2px solid ${COLORS.SECONDARY};
width: 316px;
border-radius: 3px;
background: ${COLORS.BLACK};
} }
.settings-bottom { .settings-bottom {
@ -684,4 +613,4 @@ class Settings extends React.PureComponent {
} }
} }
export default enhanceWithClickOutside(Settings) export default Settings

Loading…
Cancel
Save