Splitting menu in multiple components

This commit is contained in:
Jesús Espino 2020-10-26 13:56:32 +01:00
parent a0a182a613
commit 223d017bf9
9 changed files with 200 additions and 154 deletions

View file

@ -1,154 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import Switch from './switch'
type MenuOptionProps = {
id: string,
name: string,
onClick?: (id: string) => void,
}
function SeparatorOption() {
return (<div className='MenuOption MenuSeparator menu-separator'/>)
}
type SubMenuOptionProps = MenuOptionProps & {
}
type SubMenuState = {
isOpen: boolean;
}
class SubMenuOption extends React.Component<SubMenuOptionProps, SubMenuState> {
state = {
isOpen: false,
}
handleMouseEnter = () => {
this.setState({isOpen: true})
}
close = () => {
this.setState({isOpen: false})
}
render() {
return (
<div
className='MenuOption SubMenuOption menu-option'
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.close}
>
<div className='menu-name'>{this.props.name}</div>
<div
className='imageSubmenuTriangle'
style={{float: 'right'}}
/>
{this.state.isOpen &&
<Menu>
{this.props.children}
</Menu>
}
</div>
)
}
}
type ColorOptionProps = MenuOptionProps & {
icon?: 'checked' | 'sortUp' | 'sortDown' | undefined,
}
class ColorOption extends React.Component<ColorOptionProps> {
handleOnClick = () => {
this.props.onClick(this.props.id)
}
render() {
const {id, name, icon} = this.props
return (
<div
className='MenuOption ColorOption menu-option'
onClick={this.handleOnClick}
>
<div className='menu-name'>{name}</div>
{icon && <div className={'icon ' + icon}/>}
<div className={`menu-colorbox ${id}`}/>
</div>
)
}
}
type SwitchOptionProps = MenuOptionProps & {
isOn: boolean,
icon?: 'checked' | 'sortUp' | 'sortDown' | undefined,
}
class SwitchOption extends React.Component<SwitchOptionProps> {
handleOnClick = () => {
this.props.onClick(this.props.id)
}
render() {
const {name, icon, isOn} = this.props
return (
<div
className='MenuOption SwitchOption menu-option'
onClick={this.handleOnClick}
>
<div className='menu-name'>{name}</div>
{icon && <div className={`icon ${icon}`}/>}
<Switch
isOn={isOn}
onChanged={() => {}}
/>
</div>
)
}
}
type TextOptionProps = MenuOptionProps & {
icon?: 'checked' | 'sortUp' | 'sortDown' | undefined,
}
class TextOption extends React.Component<TextOptionProps> {
handleOnClick = () => {
this.props.onClick(this.props.id)
}
render() {
const {name, icon} = this.props
return (
<div
className='MenuOption TextOption menu-option'
onClick={this.handleOnClick}
>
<div className='menu-name'>{name}</div>
{icon && <div className={`icon ${icon}`}/>}
</div>
)
}
}
type MenuProps = {
children: React.ReactNode
position?: 'top'|'bottom'
}
export default class Menu extends React.Component<MenuProps> {
static Color = ColorOption
static SubMenu = SubMenuOption
static Switch = SwitchOption
static Separator = SeparatorOption
static Text = TextOption
render() {
const {position, children} = this.props
return (
<div className={'Menu menu noselect ' + (position || 'bottom')}>
<div className='menu-options'>
{children}
</div>
</div>
)
}
}

View file

@ -0,0 +1,29 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import {MenuOptionProps} from './menuItem'
type ColorOptionProps = MenuOptionProps & {
icon?: 'checked' | 'sortUp' | 'sortDown' | undefined,
}
export default class ColorOption extends React.PureComponent<ColorOptionProps> {
private handleOnClick = (): void => {
this.props.onClick(this.props.id)
}
public render(): JSX.Element {
const {id, name, icon} = this.props
return (
<div
className='MenuOption ColorOption menu-option'
onClick={this.handleOnClick}
>
<div className='menu-name'>{name}</div>
{icon && <div className={'icon ' + icon}/>}
<div className={`menu-colorbox ${id}`}/>
</div>
)
}
}

View file

@ -0,0 +1,6 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import Menu from './menu'
export default Menu

View file

@ -0,0 +1,33 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import SeparatorOption from './separatorOption'
import SwitchOption from './switchOption'
import TextOption from './textOption'
import ColorOption from './colorOption'
import SubMenuOption from './subMenuOption'
type MenuProps = {
children: React.ReactNode
position?: 'top'|'bottom'
}
export default class Menu extends React.PureComponent<MenuProps> {
static Color = ColorOption
static SubMenu = SubMenuOption
static Switch = SwitchOption
static Separator = SeparatorOption
static Text = TextOption
public render(): JSX.Element {
const {position, children} = this.props
return (
<div className={'Menu menu noselect ' + (position || 'bottom')}>
<div className='menu-options'>
{children}
</div>
</div>
)
}
}

View file

@ -0,0 +1,10 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
export type MenuOptionProps = {
id: string,
name: string,
onClick?: (id: string) => void,
}

View file

@ -0,0 +1,9 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {FC} from 'react'
const SeparatorOption: FC = (): JSX.Element => (
<div className='MenuOption MenuSeparator menu-separator'/>
)
export default SeparatorOption

View file

@ -0,0 +1,50 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import {MenuOptionProps} from './menuItem'
type SubMenuOptionProps = MenuOptionProps & {
position?: 'bottom | top'
}
type SubMenuState = {
isOpen: boolean;
}
export default class SubMenuOption extends React.PureComponent<SubMenuOptionProps, SubMenuState> {
state = {
isOpen: false,
}
private handleMouseEnter = (): void => {
this.setState({isOpen: true})
}
private close = (): void => {
this.setState({isOpen: false})
}
public render(): JSX.Element {
return (
<div
className='MenuOption SubMenuOption menu-option'
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.close}
>
<div className='menu-name'>{this.props.name}</div>
<div
className='imageSubmenuTriangle'
style={{float: 'right'}}
/>
{this.state.isOpen &&
<div className={'SubMenu menu noselect ' + (this.props.position || 'bottom')}>
<div className='menu-options'>
{this.props.children}
</div>
</div>
}
</div>
)
}
}

View file

@ -0,0 +1,35 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import Switch from '../switch'
import {MenuOptionProps} from './menuItem'
type SwitchOptionProps = MenuOptionProps & {
isOn: boolean,
icon?: 'checked' | 'sortUp' | 'sortDown' | undefined,
}
export default class SwitchOption extends React.PureComponent<SwitchOptionProps> {
private handleOnClick = (): void => {
this.props.onClick(this.props.id)
}
public render(): JSX.Element {
const {name, icon, isOn} = this.props
return (
<div
className='MenuOption SwitchOption menu-option'
onClick={this.handleOnClick}
>
<div className='menu-name'>{name}</div>
{icon && <div className={`icon ${icon}`}/>}
<Switch
isOn={isOn}
onChanged={() => {}}
/>
</div>
)
}
}

View file

@ -0,0 +1,28 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import {MenuOptionProps} from './menuItem'
type TextOptionProps = MenuOptionProps & {
icon?: 'checked' | 'sortUp' | 'sortDown' | undefined,
}
export default class TextOption extends React.PureComponent<TextOptionProps> {
private handleOnClick = (): void => {
this.props.onClick(this.props.id)
}
public render(): JSX.Element {
const {name, icon} = this.props
return (
<div
className='MenuOption TextOption menu-option'
onClick={this.handleOnClick}
>
<div className='menu-name'>{name}</div>
{icon && <div className={`icon ${icon}`}/>}
</div>
)
}
}