1
0
mirror of https://github.com/mattermost/focalboard.git synced 2024-11-27 08:31:20 +02:00

Moving icons into components and make them aware of the theme

This commit is contained in:
Jesús Espino 2020-10-27 12:53:14 +01:00
parent b47577d18f
commit a783d318aa
33 changed files with 329 additions and 116 deletions

View File

@ -10,6 +10,7 @@ import {Card} from '../blocks/card'
import mutator from '../mutator'
import MenuWrapper from '../widgets/menuWrapper'
import Menu from '../widgets/menu'
import OptionsIcon from '../widgets/icons/options'
import PropertyValueElement from './propertyValueElement'
@ -60,7 +61,7 @@ class BoardCard extends React.Component<BoardCardProps, BoardCardState> {
}}
>
<MenuWrapper className='optionsMenu' stopPropagationOnToggle={true}>
<div className='octo-hoverbutton square'><div className='imageOptions'/></div>
<div className='octo-hoverbutton square'><OptionsIcon/></div>
<Menu>
<Menu.Text
id='delete'

View File

@ -14,6 +14,8 @@ import mutator from '../mutator'
import {Utils} from '../utils'
import Menu from '../widgets/menu'
import MenuWrapper from '../widgets/menuWrapper'
import OptionsIcon from '../widgets/icons/options'
import AddIcon from '../widgets/icons/add'
import BoardCard from './boardCard'
import {BoardColumn} from './boardColumn'
@ -284,7 +286,7 @@ class BoardComponent extends React.Component<Props, State> {
<Button>{`${group.cards.length}`}</Button>
<div className='octo-spacer'/>
<MenuWrapper>
<Button><div className='imageOptions'/></Button>
<Button><OptionsIcon/></Button>
<Menu>
<Menu.Text
id='hide'
@ -297,7 +299,7 @@ class BoardComponent extends React.Component<Props, State> {
onClick={() => {
this.addCard(undefined)
}}
><div className='imageAdd'/></Button>
><AddIcon/></Button>
</div>
)
}
@ -347,7 +349,7 @@ class BoardComponent extends React.Component<Props, State> {
<Button>{`${group.cards.length}`}</Button>
<div className='octo-spacer'/>
<MenuWrapper>
<Button><div className='imageOptions'/></Button>
<Button><OptionsIcon/></Button>
<Menu>
<Menu.Text
id='hide'
@ -374,7 +376,7 @@ class BoardComponent extends React.Component<Props, State> {
onClick={() => {
this.addCard(group.option.id)
}}
><div className='imageAdd'/></Button>
><AddIcon/></Button>
</div>
)
}

View File

@ -12,6 +12,7 @@ import {MutableTextBlock} from '../blocks/textBlock'
import Menu from '../widgets/menu'
import MenuWrapper from '../widgets/menuWrapper'
import OptionsIcon from '../widgets/icons/options'
import {MarkdownEditor} from './markdownEditor'
@ -36,7 +37,7 @@ class ContentBlock extends React.Component<Props> {
<div className='octo-block octo-hover-container'>
<div className='octo-block-margin'>
<MenuWrapper>
<div className='octo-button octo-hovercontrol square octo-hover-item'><div className='imageOptions'/></div>
<div className='octo-button octo-hovercontrol square octo-hover-item'><OptionsIcon/></div>
<Menu>
{index > 0 &&
<Menu.Text

View File

@ -32,6 +32,22 @@
font-weight: 600;
padding: 3px 20px;
margin-bottom: 5px;
.show-button {
.HamburgerIcon {
display: block;
}
.ShowSidebarIcon {
display: none;
}
&:hover {
.HamburgerIcon {
display: none;
}
.ShowSidebarIcon {
display: block;
}
}
}
}
.octo-sidebar-item {

View File

@ -10,6 +10,10 @@ import {BoardTree} from '../viewModel/boardTree'
import mutator from '../mutator'
import Menu from '../widgets/menu'
import MenuWrapper from '../widgets/menuWrapper'
import OptionsIcon from '../widgets/icons/options'
import ShowSidebarIcon from '../widgets/icons/showSidebar'
import HideSidebarIcon from '../widgets/icons/hideSidebar'
import HamburgerIcon from '../widgets/icons/hamburger'
import {WorkspaceTree} from '../viewModel/workspaceTree'
import {BoardView} from '../blocks/boardView'
@ -46,24 +50,15 @@ class Sidebar extends React.Component<Props, State> {
const {boards, views} = workspaceTree
if (this.state.isHidden) {
const hamburgerRef = React.createRef<HTMLDivElement>()
return (
<div className='Sidebar octo-sidebar hidden'>
<div className='octo-sidebar-header'>
<div
className='octo-button square'
className='octo-button square show-button'
onClick={() => this.showClicked()}
>
<div
ref={hamburgerRef}
className='imageHamburger'
onMouseOver={() => {
hamburgerRef.current.className = 'imageShowSidebar'
}}
onMouseOut={() => {
hamburgerRef.current.className = 'imageHamburger'
}}
/>
<HamburgerIcon/>
<ShowSidebarIcon/>
</div>
</div>
</div>
@ -78,7 +73,7 @@ class Sidebar extends React.Component<Props, State> {
<div
className='octo-button square octo-hover-item'
onClick={() => this.hideClicked()}
><div className='imageHideSidebar'/></div>
><HideSidebarIcon/></div>
</div>
{
boards.map((board) => {
@ -101,7 +96,7 @@ class Sidebar extends React.Component<Props, State> {
{board.icon ? `${board.icon} ${displayTitle}` : displayTitle}
</div>
<MenuWrapper>
<div className='octo-button square octo-hover-item'><div className='imageOptions'/></div>
<div className='octo-button square octo-hover-item'><OptionsIcon/></div>
<Menu>
<FormattedMessage
id='Sidebar.delete-board'

View File

@ -16,6 +16,10 @@ import mutator from '../mutator'
import {Utils} from '../utils'
import Menu from '../widgets/menu'
import MenuWrapper from '../widgets/menuWrapper'
import DropdownIcon from '../widgets/icons/dropdown'
import OptionsIcon from '../widgets/icons/options'
import SortUpIcon from '../widgets/icons/sortUp'
import SortDownIcon from '../widgets/icons/sortDown'
import {Editable} from './editable'
import FilterComponent from './filterComponent'
@ -128,7 +132,7 @@ class ViewHeader extends React.Component<Props, State> {
className='octo-button'
style={{color: 'rgb(var(--main-fg))', fontWeight: 600}}
>
<div className='imageDropdown'/>
<DropdownIcon/>
</div>
<ViewMenu
board={board}
@ -244,7 +248,7 @@ class ViewHeader extends React.Component<Props, State> {
key={option.id}
id={option.id}
name={option.name}
icon={(activeView.sortOptions[0]?.propertyId === option.id) ? activeView.sortOptions[0].reversed ? 'sortUp' : 'sortDown' : undefined}
icon={(activeView.sortOptions[0]?.propertyId === option.id) ? activeView.sortOptions[0].reversed ? <SortUpIcon/> : <SortDownIcon/> : undefined}
onClick={(propertyId: string) => {
let newSortOptions: ISortOption[] = []
if (activeView.sortOptions[0] && activeView.sortOptions[0].propertyId === propertyId) {
@ -289,7 +293,7 @@ class ViewHeader extends React.Component<Props, State> {
/>
</div>}
<MenuWrapper>
<div className='imageOptions'/>
<OptionsIcon/>
<Menu>
<Menu.Text
id='exportCsv'

View File

@ -1,73 +0,0 @@
.imageDropdown {
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><polyline points="30,35 50,55 70,35" style="fill:none;stroke:black;stroke-width:4;" /></svg>');
background-size: 100% 100%;
min-width: 24px;
min-height: 24px;
}
.imageAdd {
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="stroke:black;stroke-width:4;" fill="none" stroke-opacity="50%"><polyline points="30,50 70,50" /><polyline points="50,30 50,70" /></svg>');
background-size: 100% 100%;
min-width: 24px;
min-height: 24px;
}
.imageOptions {
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="fill:black;" fill-opacity="50%"><circle cx="30" cy="50" r="5" /><circle cx="50" cy="50" r="5" /><circle cx="70" cy="50" r="5" /></svg>');
background-size: 100% 100%;
min-width: 24px;
min-height: 24px;
}
/*-- Menu images --*/
.imageSubmenuTriangle {
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><polygon points="50,35 75,50 50,65" style="fill:black;stroke:none;" fill-opacity="70%" /></svg>');
background-size: 100% 100%;
min-width: 24px;
min-height: 24px;
}
.imageMenuCheck {
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="stroke:black;stroke-width:8;" fill="none" stroke-opacity="50%"><polyline points="20,60 40,80 80,40" /></svg>');
background-size: 100% 100%;
min-width: 24px;
min-height: 24px;
}
.imageMenuSortUp {
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="stroke:black;stroke-width:8;" fill="none" stroke-opacity="50%"><polyline points="50,20 50,80" /><polyline points="30,40 50,20 70,40" /></svg>');
background-size: 100% 100%;
min-width: 24px;
min-height: 24px;
}
.imageMenuSortDown {
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="stroke:black;stroke-width:8;" fill="none" stroke-opacity="50%"><polyline points="50,20 50,80" /><polyline points="30,60 50,80 70,60" /></svg>');
background-size: 100% 100%;
min-width: 24px;
min-height: 24px;
}
.imageHideSidebar {
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="stroke:black;stroke-width:6;" fill="none" stroke-opacity="50%"><polyline points="80,20 50,50 80,80" /><polyline points="50,20 20,50, 50,80" /></svg>');
background-size: 100% 100%;
min-width: 24px;
min-height: 24px;
}
/*-- Sidebar images --*/
.imageShowSidebar {
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="stroke:black;stroke-width:6;" fill="none" stroke-opacity="50%"><polyline points="20,20 50,50 20,80" /><polyline points="50,20 80,50, 50,80" /></svg>');
background-size: 100% 100%;
min-width: 24px;
min-height: 24px;
}
.imageHamburger {
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="stroke:black;stroke-width:6;" fill="none" stroke-opacity="50%"><polyline points="20,25 80,25" /><polyline points="20,50 80,50" /><polyline points="20,75 80,75" /></svg>');
background-size: 100% 100%;
min-width: 24px;
min-height: 24px;
}

View File

@ -121,6 +121,8 @@ hr {
.octo-clickable,
.octo-button {
display: flex;
justify-content: center;
text-align: center;
border-radius: 5px;
padding: 0 5px;

View File

@ -0,0 +1,7 @@
.AddIcon {
stroke: rgb(var(--main-fg), 0.5);
stroke-width: 4px;
fill: none;
width: 24px;
height: 24px;
}

View File

@ -0,0 +1,19 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import './add.scss'
export default function AddIcon(): JSX.Element {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
className='AddIcon Icon'
viewBox='0 0 100 100'
>
<polyline points='30,50 70,50'/>
<polyline points='50,30 50,70'/>
</svg>
)
}

View File

@ -0,0 +1,7 @@
.CheckIcon {
stroke: rgba(var(--main-fg), 0.5);
stroke-width: 8px;
fill: none;
width: 24px;
height: 24px;
}

View File

@ -0,0 +1,18 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import './check.scss'
export default function CheckIcon(): JSX.Element {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
className='CheckIcon Icon'
viewBox='0 0 100 100'
>
<polyline points='20,60 40,80 80,40'/>
</svg>
)
}

View File

@ -0,0 +1,7 @@
.DropdownIcon {
fill: none;
stroke: rgb(var(--main-fg));
stroke-width: 4px;
width: 24px;
height: 24px;
}

View File

@ -0,0 +1,20 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import './dropdown.scss'
export default function DropdownIcon(): JSX.Element {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
className='DropdownIcon Icon'
viewBox='0 0 100 100'
>
<polyline
points='30,35 50,55 70,35'
/>
</svg>
)
}

View File

@ -0,0 +1,7 @@
.HamburgerIcon {
stroke: rgba(var(--main-fg), 0.5);
stroke-width: 6px;
fill: none;
width: 24px;
height: 24px;
}

View File

@ -0,0 +1,20 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import './hamburger.scss'
export default function HamburgerIcon(): JSX.Element {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
className='HamburgerIcon Icon'
viewBox='0 0 100 100'
>
<polyline points='20,25 80,25'/>
<polyline points='20,50 80,50'/>
<polyline points='20,75 80,75'/>
</svg>
)
}

View File

@ -0,0 +1,7 @@
.HideSidebarIcon {
stroke: rgba(var(--main-fg), 0.5);
stroke-width: 6px;
fill: none;
width: 24px;
height: 24px;
}

View File

@ -0,0 +1,19 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import './hideSidebar.scss'
export default function HideSidebarIcon(): JSX.Element {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
className='HideSidebarIcon Icon'
viewBox='0 0 100 100'
>
<polyline points='80,20 50,50 80,80'/>
<polyline points='50,20 20,50, 50,80'/>
</svg>
)
}

View File

@ -0,0 +1,5 @@
.OptionsIcon {
fill: rgba(var(--main-fg), 0.5);
width: 24px;
height: 24px;
}

View File

@ -0,0 +1,32 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import './options.scss'
export default function OptionsIcon(): JSX.Element {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
className='OptionsIcon Icon'
viewBox='0 0 100 100'
>
<circle
cx='30'
cy='50'
r='5'
/>
<circle
cx='50'
cy='50'
r='5'
/>
<circle
cx='70'
cy='50'
r='5'
/>
</svg>
)
}

View File

@ -0,0 +1,7 @@
.ShowSidebarIcon {
stroke: rgba(var(--main-fg), 0.5);
stroke-width: 6px;
fill: none;
width: 24px;
height: 24px;
}

View File

@ -0,0 +1,19 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import './showSidebar.scss'
export default function ShowSidebarIcon(): JSX.Element {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
className='ShowSidebarIcon Icon'
viewBox='0 0 100 100'
>
<polyline points='20,20 50,50 20,80'/>
<polyline points='50,20 80,50, 50,80'/>
</svg>
)
}

View File

@ -0,0 +1,7 @@
.SortDownIcon {
stroke: rgba(var(--main-fg), 0.5);
stroke-width: 8px;
fill: none;
width: 24px;
height: 24px;
}

View File

@ -0,0 +1,19 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import './sortDown.scss'
export default function SortDownIcon(): JSX.Element {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
className='SortDownIcon Icon'
viewBox='0 0 100 100'
>
<polyline points='50,20 50,80'/>
<polyline points='30,60 50,80 70,60'/>
</svg>
)
}

View File

@ -0,0 +1,7 @@
.SortUpIcon {
stroke: rgba(var(--main-fg), 0.5);
stroke-width: 8px;
fill: none;
width: 24px;
height: 24px;
}

View File

@ -0,0 +1,19 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import './sortUp.scss'
export default function SortUpIcon(): JSX.Element {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
className='SortUpIcon Icon'
viewBox='0 0 100 100'
>
<polyline points='50,20 50,80'/>
<polyline points='30,40 50,20 70,40'/>
</svg>
)
}

View File

@ -0,0 +1,6 @@
.SubmenuTriangleIcon {
fill: rgba(var(--main-fg), 0.7);
stroke: none;
width: 24px;
height: 24px;
}

View File

@ -0,0 +1,18 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import './submenuTriangle.scss'
export default function SubmenuTriangleIcon(): JSX.Element {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
className='SubmenuTriangleIcon Icon'
viewBox='0 0 100 100'
>
<polygon points='50,35 75,50 50,65'/>
</svg>
)
}

View File

@ -7,7 +7,7 @@ import {MenuOptionProps} from './menuItem'
import './colorOption.scss'
type ColorOptionProps = MenuOptionProps & {
icon?: 'checked' | 'sortUp' | 'sortDown' | undefined,
icon?: React.ReactNode
}
export default class ColorOption extends React.PureComponent<ColorOptionProps> {
@ -23,7 +23,7 @@ export default class ColorOption extends React.PureComponent<ColorOptionProps> {
onClick={this.handleOnClick}
>
<div className='menu-name'>{name}</div>
{icon && <div className={'icon ' + icon}/>}
{icon}
<div className={`menu-colorbox ${id}`}/>
</div>
)

View File

@ -0,0 +1,5 @@
.SubMenuOption {
.SubmenuTriangleIcon {
float: 'right'
}
}

View File

@ -3,6 +3,9 @@
import React from 'react'
import {MenuOptionProps} from './menuItem'
import SubmenuTriangleIcon from '../icons/submenuTriangle'
import './subMenuOption.scss'
type SubMenuOptionProps = MenuOptionProps & {
position?: 'bottom | top'
@ -33,10 +36,7 @@ export default class SubMenuOption extends React.PureComponent<SubMenuOptionProp
onMouseLeave={this.close}
>
<div className='menu-name'>{this.props.name}</div>
<div
className='imageSubmenuTriangle'
style={{float: 'right'}}
/>
<SubmenuTriangleIcon/>
{this.state.isOpen &&
<div className={'SubMenu menu noselect ' + (this.props.position || 'bottom')}>
<div className='menu-options'>

View File

@ -8,7 +8,7 @@ import {MenuOptionProps} from './menuItem'
type SwitchOptionProps = MenuOptionProps & {
isOn: boolean,
icon?: 'checked' | 'sortUp' | 'sortDown' | undefined,
icon?: React.ReactNode,
}
export default class SwitchOption extends React.PureComponent<SwitchOptionProps> {
@ -24,7 +24,7 @@ export default class SwitchOption extends React.PureComponent<SwitchOptionProps>
onClick={this.handleOnClick}
>
<div className='menu-name'>{name}</div>
{icon && <div className={`icon ${icon}`}/>}
{icon}
<Switch
isOn={isOn}
onChanged={() => {}}

View File

@ -1,12 +1,11 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import { Utils } from '../../utils'
import {MenuOptionProps} from './menuItem'
type TextOptionProps = MenuOptionProps & {
icon?: 'checked' | 'sortUp' | 'sortDown' | undefined,
icon?: React.ReactNode,
}
export default class TextOption extends React.PureComponent<TextOptionProps> {
@ -22,17 +21,8 @@ export default class TextOption extends React.PureComponent<TextOptionProps> {
onClick={this.handleOnClick}
>
<div className='menu-name'>{name}</div>
{icon && <div className={`icon ${this.iconCssClass(icon)}`}/>}
{icon}
</div>
)
}
private iconCssClass(name: 'checked' | 'sortUp' | 'sortDown') {
switch (name) {
case 'checked': return 'imageMenuCheck'
case 'sortUp': return 'imageMenuSortUp'
case 'sortDown': return 'imageMenuSortDown'
default: Utils.assertFailure(`Invalid menu icon: ${name}`)
}
}
}