Dark theme for calling device selection

This commit is contained in:
Evan Hahn 2020-12-04 17:03:01 -06:00 committed by GitHub
parent 31c2fe56f4
commit a9367f48f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 70 additions and 36 deletions

View File

@ -9714,13 +9714,7 @@ button.module-image__border-overlay:focus {
.module-calling-device-selection__close-button { .module-calling-device-selection__close-button {
@include button-reset; @include button-reset;
@include light-theme { @include color-svg('../images/x-shadow-16.svg', $color-white);
@include color-svg('../images/x-shadow-16.svg', $color-gray-75);
}
@include dark-theme {
@include color-svg('../images/x-shadow-16.svg', $color-white);
}
height: 16px; height: 16px;
position: absolute; position: absolute;

View File

@ -3,7 +3,8 @@
import React from 'react'; import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { Tooltip, TooltipPlacement, TooltipTheme } from './Tooltip'; import { Tooltip, TooltipPlacement } from './Tooltip';
import { Theme } from '../util/theme';
import { LocalizerType } from '../types/Util'; import { LocalizerType } from '../types/Util';
export enum CallingButtonType { export enum CallingButtonType {
@ -63,7 +64,7 @@ export const CallingButton = ({
<Tooltip <Tooltip
content={tooltipContent} content={tooltipContent}
direction={tooltipDirection} direction={tooltipDirection}
theme={TooltipTheme.Dark} theme={Theme.Dark}
> >
<button <button
aria-label={tooltipContent} aria-label={tooltipContent}

View File

@ -11,6 +11,7 @@ import {
ChangeIODevicePayloadType, ChangeIODevicePayloadType,
MediaDeviceSettings, MediaDeviceSettings,
} from '../types/Calling'; } from '../types/Calling';
import { Theme } from '../util/theme';
export type Props = MediaDeviceSettings & { export type Props = MediaDeviceSettings & {
changeIODevice: (payload: ChangeIODevicePayloadType) => void; changeIODevice: (payload: ChangeIODevicePayloadType) => void;
@ -134,7 +135,12 @@ export const CallingDeviceSelection = ({
: undefined; : undefined;
return ( return (
<ConfirmationModal actions={[]} i18n={i18n} onClose={toggleSettings}> <ConfirmationModal
actions={[]}
i18n={i18n}
theme={Theme.Dark}
onClose={toggleSettings}
>
<div className="module-calling-device-selection"> <div className="module-calling-device-selection">
<button <button
type="button" type="button"

View File

@ -4,7 +4,8 @@
import React from 'react'; import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { LocalizerType } from '../types/Util'; import { LocalizerType } from '../types/Util';
import { Tooltip, TooltipTheme } from './Tooltip'; import { Tooltip } from './Tooltip';
import { Theme } from '../util/theme';
export type PropsType = { export type PropsType = {
canPip?: boolean; canPip?: boolean;
@ -43,7 +44,7 @@ export const CallingHeader = ({
<div className="module-calling-tools__button"> <div className="module-calling-tools__button">
<Tooltip <Tooltip
content={i18n('calling__participants', [String(participantCount)])} content={i18n('calling__participants', [String(participantCount)])}
theme={TooltipTheme.Dark} theme={Theme.Dark}
> >
<button <button
aria-label={i18n('calling__participants', [ aria-label={i18n('calling__participants', [
@ -69,7 +70,7 @@ export const CallingHeader = ({
<div className="module-calling-tools__button"> <div className="module-calling-tools__button">
<Tooltip <Tooltip
content={i18n('callingDeviceSelection__settings')} content={i18n('callingDeviceSelection__settings')}
theme={TooltipTheme.Dark} theme={Theme.Dark}
> >
<button <button
aria-label={i18n('callingDeviceSelection__settings')} aria-label={i18n('callingDeviceSelection__settings')}
@ -81,7 +82,7 @@ export const CallingHeader = ({
</div> </div>
{canPip && ( {canPip && (
<div className="module-calling-tools__button"> <div className="module-calling-tools__button">
<Tooltip content={i18n('calling__pip--on')} theme={TooltipTheme.Dark}> <Tooltip content={i18n('calling__pip--on')} theme={Theme.Dark}>
<button <button
aria-label={i18n('calling__pip--on')} aria-label={i18n('calling__pip--on')}
className="module-calling-button__pip" className="module-calling-button__pip"

View File

@ -2,22 +2,25 @@
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react'; import * as React from 'react';
import classNames from 'classnames';
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { import {
ConfirmationDialog, ConfirmationDialog,
Props as ConfirmationDialogProps, Props as ConfirmationDialogProps,
} from './ConfirmationDialog'; } from './ConfirmationDialog';
import { LocalizerType } from '../types/Util'; import { LocalizerType } from '../types/Util';
import { Theme, themeClassName } from '../util/theme';
export type OwnProps = { export type OwnProps = {
readonly i18n: LocalizerType; readonly i18n: LocalizerType;
readonly onClose: () => unknown; readonly onClose: () => unknown;
readonly theme?: Theme;
}; };
export type Props = OwnProps & ConfirmationDialogProps; export type Props = OwnProps & ConfirmationDialogProps;
export const ConfirmationModal = React.memo( export const ConfirmationModal = React.memo(
({ i18n, onClose, children, ...rest }: Props) => { ({ i18n, onClose, theme, children, ...rest }: Props) => {
const [root, setRoot] = React.useState<HTMLElement | null>(null); const [root, setRoot] = React.useState<HTMLElement | null>(null);
React.useEffect(() => { React.useEffect(() => {
@ -69,7 +72,10 @@ export const ConfirmationModal = React.memo(
? createPortal( ? createPortal(
<div <div
role="presentation" role="presentation"
className="module-confirmation-dialog__overlay" className={classNames(
'module-confirmation-dialog__overlay',
theme ? themeClassName(theme) : undefined
)}
onClick={handleCancel} onClick={handleCancel}
onKeyUp={handleKeyCancel} onKeyUp={handleKeyCancel}
> >

View File

@ -3,7 +3,8 @@
import React from 'react'; import React from 'react';
import { Avatar } from './Avatar'; import { Avatar } from './Avatar';
import { Tooltip, TooltipTheme } from './Tooltip'; import { Tooltip } from './Tooltip';
import { Theme } from '../util/theme';
import { ContactName } from './conversation/ContactName'; import { ContactName } from './conversation/ContactName';
import { LocalizerType } from '../types/Util'; import { LocalizerType } from '../types/Util';
import { ColorType } from '../types/Colors'; import { ColorType } from '../types/Colors';
@ -41,7 +42,7 @@ const CallButton = ({
tooltipContent, tooltipContent,
}: CallButtonProps): JSX.Element => { }: CallButtonProps): JSX.Element => {
return ( return (
<Tooltip content={tooltipContent} theme={TooltipTheme.Dark}> <Tooltip content={tooltipContent} theme={Theme.Dark}>
<button <button
className={`module-incoming-call__button module-incoming-call__button--${classSuffix}`} className={`module-incoming-call__button module-incoming-call__button--${classSuffix}`}
onClick={onClick} onClick={onClick}

View File

@ -5,7 +5,8 @@ import * as React from 'react';
import { storiesOf } from '@storybook/react'; import { storiesOf } from '@storybook/react';
import { select } from '@storybook/addon-knobs'; import { select } from '@storybook/addon-knobs';
import { Tooltip, TooltipPlacement, TooltipTheme, PropsType } from './Tooltip'; import { Tooltip, TooltipPlacement, PropsType } from './Tooltip';
import { Theme } from '../util/theme';
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
content: overrideProps.content || 'Hello World', content: overrideProps.content || 'Hello World',
@ -84,7 +85,7 @@ story.add('Dark Theme', () => (
<Tooltip <Tooltip
{...createProps({ {...createProps({
sticky: true, sticky: true,
theme: TooltipTheme.Dark, theme: Theme.Dark,
})} })}
> >
{Trigger} {Trigger}

View File

@ -3,6 +3,7 @@
import React from 'react'; import React from 'react';
import { Manager, Reference, Popper } from 'react-popper'; import { Manager, Reference, Popper } from 'react-popper';
import { Theme, themeClassName } from '../util/theme';
export enum TooltipPlacement { export enum TooltipPlacement {
Top = 'top', Top = 'top',
@ -11,17 +12,11 @@ export enum TooltipPlacement {
Left = 'left', Left = 'left',
} }
export enum TooltipTheme {
System = 'system',
Light = 'light',
Dark = 'dark',
}
export type PropsType = { export type PropsType = {
content: string | JSX.Element; content: string | JSX.Element;
direction?: TooltipPlacement; direction?: TooltipPlacement;
sticky?: boolean; sticky?: boolean;
theme?: TooltipTheme; theme?: Theme;
}; };
export const Tooltip: React.FC<PropsType> = ({ export const Tooltip: React.FC<PropsType> = ({
@ -29,19 +24,12 @@ export const Tooltip: React.FC<PropsType> = ({
content, content,
direction, direction,
sticky, sticky,
theme = TooltipTheme.System, theme,
}) => { }) => {
const isSticky = Boolean(sticky); const isSticky = Boolean(sticky);
const [showTooltip, setShowTooltip] = React.useState(isSticky); const [showTooltip, setShowTooltip] = React.useState(isSticky);
let tooltipTheme: string; const tooltipTheme = theme ? themeClassName(theme) : undefined;
if (theme === TooltipTheme.Light) {
tooltipTheme = 'light-theme';
} else if (theme === TooltipTheme.Dark) {
tooltipTheme = 'dark-theme';
} else {
tooltipTheme = '';
}
return ( return (
<Manager> <Manager>

View File

@ -0,0 +1,16 @@
// Copyright 2019-2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai';
import { Theme, themeClassName } from '../../util/theme';
describe('themeClassName', () => {
it('returns "light-theme" when passed a light theme', () => {
assert.strictEqual(themeClassName(Theme.Light), 'light-theme');
});
it('returns "dark-theme" when passed a dark theme', () => {
assert.strictEqual(themeClassName(Theme.Dark), 'dark-theme');
});
});

20
ts/util/theme.ts Normal file
View File

@ -0,0 +1,20 @@
// Copyright 2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { missingCaseError } from './missingCaseError';
export enum Theme {
Light,
Dark,
}
export function themeClassName(theme: Theme): string {
switch (theme) {
case Theme.Light:
return 'light-theme';
case Theme.Dark:
return 'dark-theme';
default:
throw missingCaseError(theme);
}
}