Dark theme for calling device selection
This commit is contained in:
parent
31c2fe56f4
commit
a9367f48f1
10 changed files with 70 additions and 36 deletions
|
@ -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-gray-75);
|
|
||||||
}
|
|
||||||
|
|
||||||
@include dark-theme {
|
|
||||||
@include color-svg('../images/x-shadow-16.svg', $color-white);
|
@include color-svg('../images/x-shadow-16.svg', $color-white);
|
||||||
}
|
|
||||||
|
|
||||||
height: 16px;
|
height: 16px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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}
|
||||||
>
|
>
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
16
ts/test-both/util/theme_test.ts
Normal file
16
ts/test-both/util/theme_test.ts
Normal 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
20
ts/util/theme.ts
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue