Fix composer button visibility in contrast colour mode (#31255)
* Fix composer button visibility in contrast colour mode Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update snapshot Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update test Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Simplify Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update snapshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update screenshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update screenshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update screenshot Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
@@ -6,14 +6,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React, { type ReactNode } from "react";
|
||||
import classNames from "classnames";
|
||||
import React, { type HTMLAttributes, type ReactNode } from "react";
|
||||
import { PlayPauseButton as SharedPlayPauseButton } from "@element-hq/web-shared-components";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import { type Playback, PlaybackState } from "../../../audio/Playback";
|
||||
import AccessibleButton, { type ButtonProps } from "../elements/AccessibleButton";
|
||||
|
||||
type Props = Omit<ButtonProps<"div">, "title" | "onClick" | "disabled" | "element" | "ref"> & {
|
||||
type Props = HTMLAttributes<HTMLButtonElement> & {
|
||||
// Playback instance to manipulate. Cannot change during the component lifecycle.
|
||||
playback: Playback;
|
||||
|
||||
@@ -27,8 +25,7 @@ type Props = Omit<ButtonProps<"div">, "title" | "onClick" | "disabled" | "elemen
|
||||
*/
|
||||
export default class PlayPauseButton extends React.PureComponent<Props> {
|
||||
private onClick = (): void => {
|
||||
// noinspection JSIgnoredPromiseFromCall
|
||||
this.toggleState();
|
||||
void this.toggleState();
|
||||
};
|
||||
|
||||
public async toggleState(): Promise<void> {
|
||||
@@ -37,21 +34,14 @@ export default class PlayPauseButton extends React.PureComponent<Props> {
|
||||
|
||||
public render(): ReactNode {
|
||||
const { playback, playbackPhase, ...restProps } = this.props;
|
||||
const isPlaying = playback.isPlaying;
|
||||
const isDisabled = playbackPhase === PlaybackState.Decoding;
|
||||
const classes = classNames("mx_PlayPauseButton", {
|
||||
mx_PlayPauseButton_play: !isPlaying,
|
||||
mx_PlayPauseButton_pause: isPlaying,
|
||||
mx_PlayPauseButton_disabled: isDisabled,
|
||||
});
|
||||
|
||||
return (
|
||||
<AccessibleButton
|
||||
<SharedPlayPauseButton
|
||||
data-testid="play-pause-button"
|
||||
className={classes}
|
||||
title={isPlaying ? _t("action|pause") : _t("action|play")}
|
||||
onClick={this.onClick}
|
||||
disabled={isDisabled}
|
||||
className="mx_PlayPauseButton"
|
||||
togglePlay={this.onClick}
|
||||
playing={playback.isPlaying}
|
||||
disabled={playbackPhase === PlaybackState.Decoding}
|
||||
{...restProps}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -32,6 +32,7 @@ interface IOptionListProps {
|
||||
}
|
||||
|
||||
interface IOptionProps extends React.ComponentProps<typeof MenuItem> {
|
||||
icon?: ReactNode;
|
||||
iconClassName?: string;
|
||||
isDestructive?: boolean;
|
||||
}
|
||||
@@ -114,6 +115,7 @@ export const IconizedContextMenuOption: React.FC<IOptionProps> = ({
|
||||
label,
|
||||
className,
|
||||
iconClassName,
|
||||
icon,
|
||||
children,
|
||||
isDestructive,
|
||||
...props
|
||||
@@ -129,6 +131,7 @@ export const IconizedContextMenuOption: React.FC<IOptionProps> = ({
|
||||
label={label}
|
||||
>
|
||||
{iconClassName && <span className={classNames("mx_IconizedContextMenu_icon", iconClassName)} />}
|
||||
{icon}
|
||||
<span className="mx_IconizedContextMenu_label">{label}</span>
|
||||
{children}
|
||||
</MenuItem>
|
||||
|
||||
@@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React, { type ReactNode, type SyntheticEvent, useContext } from "react";
|
||||
import classNames from "classnames";
|
||||
import { type RoomMember, type IEventRelation } from "matrix-js-sdk/src/matrix";
|
||||
import { LocationPinSolidIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import { CollapsibleButton } from "../rooms/CollapsibleButton";
|
||||
@@ -54,13 +55,9 @@ const LocationButton: React.FC<IProps> = ({ roomId, sender, menuPosition, relati
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<CollapsibleButton
|
||||
className={className}
|
||||
iconClassName="mx_MessageComposer_location"
|
||||
onClick={openMenu}
|
||||
title={_t("common|location")}
|
||||
inputRef={button}
|
||||
/>
|
||||
<CollapsibleButton className={className} onClick={openMenu} title={_t("common|location")} inputRef={button}>
|
||||
<LocationPinSolidIcon />
|
||||
</CollapsibleButton>
|
||||
|
||||
{contextMenu}
|
||||
</React.Fragment>
|
||||
|
||||
@@ -7,7 +7,6 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React, { type RefObject, useContext } from "react";
|
||||
import classNames from "classnames";
|
||||
|
||||
import AccessibleButton, { type ButtonProps } from "../elements/AccessibleButton";
|
||||
import { OverflowMenuContext } from "./MessageComposerButtons";
|
||||
@@ -16,24 +15,16 @@ import { IconizedContextMenuOption } from "../context_menus/IconizedContextMenu"
|
||||
interface Props extends Omit<ButtonProps<"div">, "element"> {
|
||||
inputRef?: RefObject<HTMLElement | null>;
|
||||
title: string;
|
||||
iconClassName: string;
|
||||
}
|
||||
|
||||
export const CollapsibleButton: React.FC<Props> = ({
|
||||
title,
|
||||
children,
|
||||
className,
|
||||
iconClassName,
|
||||
inputRef,
|
||||
...props
|
||||
}) => {
|
||||
export const CollapsibleButton: React.FC<Props> = ({ title, children, className, inputRef, ...props }) => {
|
||||
const inOverflowMenu = !!useContext(OverflowMenuContext);
|
||||
if (inOverflowMenu) {
|
||||
return <IconizedContextMenuOption {...props} iconClassName={iconClassName} label={title} inputRef={inputRef} />;
|
||||
return <IconizedContextMenuOption {...props} icon={children} label={title} inputRef={inputRef} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<AccessibleButton {...props} title={title} className={classNames(className, iconClassName)} ref={inputRef}>
|
||||
<AccessibleButton {...props} title={title} className={className} ref={inputRef}>
|
||||
{children}
|
||||
</AccessibleButton>
|
||||
);
|
||||
|
||||
@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import classNames from "classnames";
|
||||
import React, { type JSX, useContext } from "react";
|
||||
import { ReactionIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import ContextMenu, { aboveLeftOf, type MenuProps, useContextMenu } from "../../structures/ContextMenu";
|
||||
@@ -50,11 +51,12 @@ export function EmojiButton({ addEmoji, menuPosition, className }: IEmojiButtonP
|
||||
<>
|
||||
<CollapsibleButton
|
||||
className={computedClassName}
|
||||
iconClassName="mx_EmojiButton_icon"
|
||||
onClick={openMenu}
|
||||
title={_t("common|emoji")}
|
||||
inputRef={button}
|
||||
/>
|
||||
>
|
||||
<ReactionIcon />
|
||||
</CollapsibleButton>
|
||||
|
||||
{contextMenu}
|
||||
</>
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { Tooltip } from "@vector-im/compound-web";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { LockOffIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
import { LockOffIcon, SendSolidIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
@@ -72,7 +72,9 @@ function SendButton(props: ISendButtonProps): JSX.Element {
|
||||
onClick={props.onClick}
|
||||
title={props.title ?? _t("composer|send_button_title")}
|
||||
data-testid="sendmessagebtn"
|
||||
/>
|
||||
>
|
||||
<SendSolidIcon />
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,13 @@ import {
|
||||
M_POLL_START,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import React, { type JSX, createContext, type ReactElement, type ReactNode, useContext, useRef } from "react";
|
||||
import {
|
||||
AttachmentIcon,
|
||||
MicOnSolidIcon,
|
||||
OverflowHorizontalIcon,
|
||||
PollsIcon,
|
||||
TextFormattingIcon,
|
||||
} from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import { CollapsibleButton } from "./CollapsibleButton";
|
||||
@@ -35,6 +42,7 @@ import { filterBoolean } from "../../../utils/arrays";
|
||||
import { useSettingValue } from "../../../hooks/useSettings";
|
||||
import AccessibleButton, { type ButtonEvent } from "../elements/AccessibleButton";
|
||||
import { useScopedRoomContext } from "../../../contexts/ScopedRoomContext.tsx";
|
||||
import { Icon as StickersIcon } from "../../../../res/img/element-icons/room/composer/sticker.svg";
|
||||
|
||||
interface IProps {
|
||||
addEmoji: (emoji: string) => boolean;
|
||||
@@ -125,7 +133,9 @@ const MessageComposerButtons: React.FC<IProps> = (props: IProps) => {
|
||||
className={moreOptionsClasses}
|
||||
onClick={props.toggleButtonMenu}
|
||||
title={_t("quick_settings|sidebar_settings")}
|
||||
/>
|
||||
>
|
||||
<OverflowHorizontalIcon />
|
||||
</AccessibleButton>
|
||||
)}
|
||||
{props.isMenuOpen && (
|
||||
<IconizedContextMenu
|
||||
@@ -235,12 +245,9 @@ const UploadButton: React.FC = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<CollapsibleButton
|
||||
className="mx_MessageComposer_button"
|
||||
iconClassName="mx_MessageComposer_upload"
|
||||
onClick={onClick}
|
||||
title={_t("common|attachment")}
|
||||
/>
|
||||
<CollapsibleButton className="mx_MessageComposer_button" onClick={onClick} title={_t("common|attachment")}>
|
||||
<AttachmentIcon />
|
||||
</CollapsibleButton>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -250,10 +257,11 @@ function showStickersButton(props: IProps): ReactElement | null {
|
||||
id="stickersButton"
|
||||
key="controls_stickers"
|
||||
className="mx_MessageComposer_button"
|
||||
iconClassName="mx_MessageComposer_stickers"
|
||||
onClick={() => props.setStickerPickerOpen(!props.isStickerPickerOpen)}
|
||||
title={props.isStickerPickerOpen ? _t("composer|close_sticker_picker") : _t("common|sticker")}
|
||||
/>
|
||||
>
|
||||
<StickersIcon />
|
||||
</CollapsibleButton>
|
||||
) : null;
|
||||
}
|
||||
|
||||
@@ -263,10 +271,11 @@ function voiceRecordingButton(props: IProps, narrow: boolean): ReactElement | nu
|
||||
<CollapsibleButton
|
||||
key="voice_message_send"
|
||||
className="mx_MessageComposer_button"
|
||||
iconClassName="mx_MessageComposer_voiceMessage"
|
||||
onClick={props.onRecordStartEndClick}
|
||||
title={_t("composer|voice_message_button")}
|
||||
/>
|
||||
>
|
||||
<MicOnSolidIcon />
|
||||
</CollapsibleButton>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -318,10 +327,11 @@ class PollButton extends React.PureComponent<IPollButtonProps> {
|
||||
return (
|
||||
<CollapsibleButton
|
||||
className="mx_MessageComposer_button"
|
||||
iconClassName="mx_MessageComposer_poll"
|
||||
onClick={this.onCreateClick}
|
||||
title={_t("composer|poll_button")}
|
||||
/>
|
||||
>
|
||||
<PollsIcon />
|
||||
</CollapsibleButton>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -349,15 +359,9 @@ function ComposerModeButton({ isRichTextEnabled, onClick }: WysiwygToggleButtonP
|
||||
const title = isRichTextEnabled ? _t("composer|mode_plain") : _t("composer|mode_rich_text");
|
||||
|
||||
return (
|
||||
<CollapsibleButton
|
||||
className="mx_MessageComposer_button"
|
||||
iconClassName={classNames({
|
||||
mx_MessageComposer_plain_text: !isRichTextEnabled,
|
||||
mx_MessageComposer_rich_text: isRichTextEnabled,
|
||||
})}
|
||||
onClick={onClick}
|
||||
title={title}
|
||||
/>
|
||||
<CollapsibleButton className="mx_MessageComposer_button" onClick={onClick} title={title}>
|
||||
<TextFormattingIcon />
|
||||
</CollapsibleButton>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React, { type ReactNode } from "react";
|
||||
import { type Room, type IEventRelation, type MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { DeleteIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import { RecordingState } from "../../../audio/VoiceRecording";
|
||||
@@ -274,7 +275,9 @@ export default class VoiceRecordComposerTile extends React.PureComponent<IProps,
|
||||
className="mx_VoiceRecordComposerTile_delete"
|
||||
title={_t("action|delete")}
|
||||
onClick={this.onCancel}
|
||||
/>
|
||||
>
|
||||
<DeleteIcon />
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user