MM-51798: Fix Boards+Playbooks channel header RHS button styling (#23276)
* fix playbook icon * fix boards icon * lint * fix test
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
6905df9f97
Коммит
f815c20fca
36
webapp/boards/src/components/rhsChannelBoardsToggleIcon.tsx
Обычный файл
36
webapp/boards/src/components/rhsChannelBoardsToggleIcon.tsx
Обычный файл
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {ElementRef, useRef} from 'react'
|
||||
|
||||
import {useSelector} from 'react-redux'
|
||||
import {GlobalState} from '@mattermost/types/store'
|
||||
|
||||
import FocalboardIcon from 'src/widgets/icons/logo'
|
||||
|
||||
type Props = {
|
||||
boardsRhsId: string
|
||||
}
|
||||
|
||||
type ViewsState = {views: {rhs: {isSidebarOpen: boolean, pluggableId: string}, rhsSuppressed: boolean}}
|
||||
|
||||
const RhsChannelBoardsToggleIcon = ({boardsRhsId}: Props) => {
|
||||
const iconRef = useRef<ElementRef<typeof FocalboardIcon>>(null)
|
||||
const isOpen = useSelector(({views: {rhs, rhsSuppressed}}: GlobalState & ViewsState) => (
|
||||
rhs.isSidebarOpen &&
|
||||
!rhsSuppressed &&
|
||||
rhs.pluggableId === boardsRhsId
|
||||
))
|
||||
|
||||
// If it has been mounted, we know our parent is always a button.
|
||||
const parent = iconRef?.current ? iconRef?.current?.parentNode as HTMLButtonElement : null
|
||||
parent?.classList.toggle('channel-header__icon--active-inverted', isOpen)
|
||||
|
||||
return (
|
||||
<FocalboardIcon
|
||||
ref={iconRef}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default RhsChannelBoardsToggleIcon
|
||||
@@ -74,6 +74,7 @@ import './plugin.scss'
|
||||
import CreateBoardFromTemplate from 'src/components/createBoardFromTemplate'
|
||||
|
||||
import CloudUpgradeNudge from './components/cloudUpgradeNudge/cloudUpgradeNudge'
|
||||
import RhsChannelBoardsToggle from './components/rhsChannelBoardsToggleIcon'
|
||||
|
||||
function getSubpath(siteURL: string): string {
|
||||
const url = new URL(siteURL)
|
||||
@@ -365,10 +366,15 @@ export default class Plugin {
|
||||
</ErrorBoundary>
|
||||
)
|
||||
|
||||
const {rhsId, toggleRHSPlugin} = this.registry.registerRightHandSidebarComponent(component, title)
|
||||
this.rhsId = rhsId
|
||||
const {id, toggleRHSPlugin} = this.registry.registerRightHandSidebarComponent(component, title)
|
||||
this.rhsId = id
|
||||
|
||||
this.channelHeaderButtonId = registry.registerChannelHeaderButtonAction(<FocalboardIcon/>, () => mmStore.dispatch(toggleRHSPlugin), 'Boards', 'Boards')
|
||||
this.channelHeaderButtonId = registry.registerChannelHeaderButtonAction(
|
||||
() => <RhsChannelBoardsToggle boardsRhsId={id}/>,
|
||||
() => mmStore.dispatch(toggleRHSPlugin),
|
||||
'Boards',
|
||||
'Boards'
|
||||
)
|
||||
|
||||
this.registry.registerProduct(
|
||||
'/boards',
|
||||
|
||||
@@ -8,10 +8,14 @@ type Props = {
|
||||
className?: string
|
||||
}
|
||||
|
||||
export default function CompassIcon(props: Props): JSX.Element {
|
||||
export default React.forwardRef<HTMLElement, Props>(({icon, className, ...props}, ref) => {
|
||||
// All compass icon classes start with icon,
|
||||
// so not expecting that prefix in props.
|
||||
return (
|
||||
<i className={`CompassIcon icon-${props.icon}${props.className === undefined ? '' : ` ${props.className}`}`}/>
|
||||
<i
|
||||
{...props}
|
||||
ref={ref}
|
||||
className={`CompassIcon icon-${icon}${className === undefined ? '' : ` ${className}`}`}
|
||||
/>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -6,11 +6,13 @@ import React from 'react'
|
||||
import './logo.scss'
|
||||
import CompassIcon from './compassIcon'
|
||||
|
||||
export default function LogoIcon(): JSX.Element {
|
||||
export default React.forwardRef<HTMLElement>((_, ref) => {
|
||||
return (
|
||||
<CompassIcon
|
||||
ref={ref}
|
||||
data-testid='boardsIcon'
|
||||
icon='product-boards'
|
||||
className='boards-rhs-icon'
|
||||
/>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export type Ref = HTMLElement;
|
||||
|
||||
interface Props {
|
||||
id?: string;
|
||||
}
|
||||
@@ -14,7 +12,7 @@ const Icon = styled.i`
|
||||
font-size: 22px;
|
||||
`;
|
||||
|
||||
const PlaybooksProductIcon = React.forwardRef<Ref, Props>((props: Props, forwardedRef) => (
|
||||
const PlaybooksProductIcon = React.forwardRef<HTMLElement, Props>((props: Props, forwardedRef) => (
|
||||
<Icon
|
||||
id={props?.id}
|
||||
ref={forwardedRef}
|
||||
|
||||
@@ -1,27 +1,21 @@
|
||||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License for license information.
|
||||
|
||||
import React, {useRef} from 'react';
|
||||
import React, {ElementRef, useRef} from 'react';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
import {useSelector} from 'react-redux';
|
||||
|
||||
import PlaybooksProductIcon, {Ref as PlaybookRunIconRef} from 'src/components/assets/icons/playbooks_product_icon';
|
||||
import PlaybooksProductIcon from 'src/components/assets/icons/playbooks_product_icon';
|
||||
|
||||
import {isPlaybookRunRHSOpen} from 'src/selectors';
|
||||
|
||||
export const ChannelHeaderButton = () => {
|
||||
const myRef = useRef<PlaybookRunIconRef>(null);
|
||||
const myRef = useRef<ElementRef<typeof PlaybooksProductIcon>>(null);
|
||||
const isRHSOpen = useSelector(isPlaybookRunRHSOpen);
|
||||
|
||||
// If it has been mounted, we know our parent is always a button.
|
||||
const parent = myRef?.current ? myRef?.current?.parentNode as HTMLButtonElement : null;
|
||||
if (parent) {
|
||||
if (isRHSOpen) {
|
||||
parent.classList.add('channel-header__icon--active');
|
||||
} else {
|
||||
parent.classList.remove('channel-header__icon--active');
|
||||
}
|
||||
}
|
||||
parent?.classList.toggle('channel-header__icon--active-inverted', isRHSOpen);
|
||||
|
||||
return (
|
||||
<PlaybooksProductIcon
|
||||
|
||||
Ссылка в новой задаче
Block a user