Splitting menu in multiple components
This commit is contained in:
parent
a0a182a613
commit
223d017bf9
9 changed files with 200 additions and 154 deletions
|
@ -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>
|
||||
)
|
||||
}
|
||||
}
|
29
webapp/src/widgets/menu/colorOption.tsx
Normal file
29
webapp/src/widgets/menu/colorOption.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
}
|
6
webapp/src/widgets/menu/index.tsx
Normal file
6
webapp/src/widgets/menu/index.tsx
Normal 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
|
33
webapp/src/widgets/menu/menu.tsx
Normal file
33
webapp/src/widgets/menu/menu.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
}
|
10
webapp/src/widgets/menu/menuItem.tsx
Normal file
10
webapp/src/widgets/menu/menuItem.tsx
Normal 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,
|
||||
}
|
9
webapp/src/widgets/menu/separatorOption.tsx
Normal file
9
webapp/src/widgets/menu/separatorOption.tsx
Normal 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
|
50
webapp/src/widgets/menu/subMenuOption.tsx
Normal file
50
webapp/src/widgets/menu/subMenuOption.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
}
|
35
webapp/src/widgets/menu/switchOption.tsx
Normal file
35
webapp/src/widgets/menu/switchOption.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
}
|
28
webapp/src/widgets/menu/textOption.tsx
Normal file
28
webapp/src/widgets/menu/textOption.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue