diff --git a/stylesheets/components/NavTabs.scss b/stylesheets/components/NavTabs.scss index 489ad19c5b..1dd6958ba7 100644 --- a/stylesheets/components/NavTabs.scss +++ b/stylesheets/components/NavTabs.scss @@ -141,12 +141,17 @@ $NavTabs__ProfileAvatar__size: 28px; .NavTabs__ItemUpdateBadge { background: variables.$color-ultramarine; border-radius: 100%; - border: 1px solid variables.$color-white; height: 8px; width: 8px; position: absolute; top: 0; inset-inline-end: 0; + @include mixins.light-theme { + border: 1px solid variables.$color-white; + } + @include mixins.dark-theme { + border: 1px solid variables.$color-gray-80; + } } .NavTabs__ItemIcon { diff --git a/stylesheets/components/Preferences.scss b/stylesheets/components/Preferences.scss index 50569d83a9..feb674186d 100644 --- a/stylesheets/components/Preferences.scss +++ b/stylesheets/components/Preferences.scss @@ -286,6 +286,7 @@ $secondary-text-color: light-dark( height: 100%; flex-direction: row; overflow-y: scroll; + container-type: inline-size; } &__settings-pane { @@ -374,6 +375,73 @@ $secondary-text-color: light-dark( } } + &__light-icon-label { + display: flex; + } + + &__flow-control { + display: block; + padding-block: 4px; + padding-inline: 24px; + } + &__one-third-flow { + vertical-align: middle; + display: inline-block; + width: 33%; + @container (max-width: 350px) { + width: 100%; + } + } + &__half-flow { + vertical-align: middle; + display: inline-block; + width: 50%; + @container (max-width: 350px) { + width: 100%; + } + } + &__two-thirds-flow { + vertical-align: middle; + display: inline-block; + width: 66%; + @container (max-width: 350px) { + width: 100%; + } + } + + &__half-flow--align-right { + text-align: end; + @container (max-width: 350px) { + text-align: start; + } + } + &__one-third-flow--align-right { + text-align: end; + @container (max-width: 350px) { + text-align: start; + } + } + &__full-flow { + vertical-align: middle; + display: inline-block; + width: 100%; + } + &__flow-value, + &__flow-description { + vertical-align: middle; + color: $secondary-text-color; + } + &__device-name-description { + padding-top: 8px; + } + &__flow-button { + padding-inline-start: 5px; + @container (max-width: 350px) { + padding-inline-start: 0px; + padding-top: 8px; + } + } + &__control { align-items: center; display: flex; @@ -432,9 +500,16 @@ $secondary-text-color: light-dark( } } + &__checkbox__description, &__description { @include mixins.font-subtitle; - color: $secondary-text-color; + // For specificity reasons, we can't use $secondary-text-color. We need the mixins. + @include mixins.light-theme { + color: variables.$color-gray-60; + } + @include mixins.dark-theme { + color: variables.$color-gray-25; + } &--error { color: variables.$color-accent-red !important; } diff --git a/ts/components/NavTabs.stories.tsx b/ts/components/NavTabs.stories.tsx new file mode 100644 index 0000000000..f03d961a6f --- /dev/null +++ b/ts/components/NavTabs.stories.tsx @@ -0,0 +1,56 @@ +// Copyright 2021 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only + +import React from 'react'; + +import { action } from '@storybook/addon-actions'; +import type { Meta } from '@storybook/react'; +import type { NavTabsProps } from './NavTabs'; +import { NavTabs } from './NavTabs'; +import { NavTab } from '../state/ducks/nav'; +import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation'; +import { ThemeType } from '../types/Util'; + +const { i18n } = window.SignalContext; + +const createProps = ( + overrideProps: Partial = {} +): NavTabsProps => ({ + badge: overrideProps.badge, + hasFailedStorySends: Boolean(overrideProps.hasFailedStorySends), + hasPendingUpdate: Boolean(overrideProps.hasPendingUpdate), + i18n, + me: getDefaultConversation(), + navTabsCollapsed: Boolean(overrideProps.navTabsCollapsed), + onChangeLocation: action('onChangeLocation'), + onToggleNavTabsCollapse: action('onToggleNavTabsCollapse'), + renderCallsTab: () =>
Calls Tab goes here
, + renderChatsTab: () =>
Chats Tab goes here
, + renderStoriesTab: () =>
Stories Tab goes here
, + renderSettingsTab: () =>
Settings Tab goes here
, + selectedNavTab: overrideProps.selectedNavTab ?? NavTab.Chats, + shouldShowProfileIcon: Boolean(overrideProps.shouldShowProfileIcon), + storiesEnabled: Boolean(overrideProps.storiesEnabled), + theme: overrideProps.theme ?? ThemeType.light, + unreadCallsCount: overrideProps.unreadCallsCount ?? 0, + unreadConversationsStats: overrideProps.unreadConversationsStats ?? { + unreadCount: 0, + unreadMentionsCount: 0, + markedUnread: false, + }, + unreadStoriesCount: overrideProps.unreadStoriesCount ?? 0, +}); + +export default { + title: 'Components/NavTabs', +} satisfies Meta; + +export function HasPendingUpdate(): JSX.Element { + return ( + + ); +} diff --git a/ts/components/Preferences.tsx b/ts/components/Preferences.tsx index acf586339e..d8fcab6cd1 100644 --- a/ts/components/Preferences.tsx +++ b/ts/components/Preferences.tsx @@ -43,6 +43,7 @@ import { FunSkinTonesList } from './fun/FunSkinTones'; import { emojiParentKeyConstant, type EmojiSkinTone } from './fun/data/emojis'; import { SettingsControl as Control, + FlowingSettingsControl as FlowingControl, SettingsRadio, SettingsRow, } from './PreferencesUtil'; @@ -672,27 +673,43 @@ export function Preferences({ const pageContents = ( <> - - -
{i18n('icu:Preferences--device-name')}
-
- {i18n('icu:Preferences--device-name__description')} -
- - } - right={deviceName} - rightStyle={{ - maxWidth: '33%', - }} - /> + +
+ {i18n('icu:Preferences--phone-number')} +
+
+ {phoneNumber} +
+
+ +
+ {i18n('icu:Preferences--device-name')} +
+
+ {deviceName} +
+
+ {i18n('icu:Preferences--device-name__description')} +
+
{isAutoLaunchSupported && ( @@ -1374,24 +1391,34 @@ export function Preferences({ const pageContents = ( <> - -

{i18n('icu:Preferences__pnp__row--title')}

-
- {i18n('icu:Preferences__pnp__row--body')} -
+ +
+

{i18n('icu:Preferences__pnp__row--title')}

+
+ {i18n('icu:Preferences__pnp__row--body')}
- } - right={ +
+
- } - /> +
+
)} - -
- {i18n('icu:settings__DisappearingMessages__timer__label')} -
-
- {i18n('icu:settings__DisappearingMessages__footer')} -
- - } - right={ + +
+
+ {i18n('icu:settings__DisappearingMessages__timer__label')} +
+
+ {i18n('icu:settings__DisappearingMessages__footer')} +
+
+
- } - /> +
+
); diff --git a/ts/components/PreferencesBackups.tsx b/ts/components/PreferencesBackups.tsx index c017638cae..5da0e38e8b 100644 --- a/ts/components/PreferencesBackups.tsx +++ b/ts/components/PreferencesBackups.tsx @@ -2,13 +2,20 @@ // SPDX-License-Identifier: AGPL-3.0-only import React from 'react'; +import classNames from 'classnames'; + import type { BackupsSubscriptionType, BackupStatusType, } from '../types/backups'; import type { LocalizerType } from '../types/I18N'; import { formatTimestamp } from '../util/formatTimestamp'; -import { SettingsControl as Control, SettingsRow } from './PreferencesUtil'; +import { + SettingsControl as Control, + FlowingSettingsControl as FlowingControl, + LightIconLabel, + SettingsRow, +} from './PreferencesUtil'; import { missingCaseError } from '../util/missingCaseError'; import { Button, ButtonVariant } from './Button'; import type { PreferencesBackupPage } from '../types/PreferencesBackupPage'; @@ -97,29 +104,36 @@ export function PreferencesBackups({ {backupSubscriptionStatus ? ( - - {i18n('icu:Preferences--signal-backups')}{' '} -
- {renderBackupsSubscriptionSummary({ - subscriptionStatus: backupSubscriptionStatus, - i18n, - locale, - })} -
- - } - right={ + +
+ + + +
+
- } - /> +
+
) : ( @@ -148,19 +162,26 @@ export function PreferencesBackups({ className="Preferences--BackupsRow" title={i18n('icu:Preferences__backup-other-ways')} > - - {i18n('icu:Preferences__local-backups')}{' '} -
- {isLocalBackupsSetup - ? null - : i18n('icu:Preferences--local-backups-off-description')} -
- - } - right={ + +
+ + + +
+
- } - /> +
+
); diff --git a/ts/components/PreferencesInternal.tsx b/ts/components/PreferencesInternal.tsx index c7bda77dd7..b4f1b5a9b7 100644 --- a/ts/components/PreferencesInternal.tsx +++ b/ts/components/PreferencesInternal.tsx @@ -2,12 +2,14 @@ // SPDX-License-Identifier: AGPL-3.0-only import React, { useState, useCallback } from 'react'; +import classNames from 'classnames'; + import type { LocalizerType } from '../types/I18N'; import { toLogFormat } from '../types/errors'; import { formatFileSize } from '../util/formatFileSize'; import { SECOND } from '../util/durations'; import type { ValidationResultType as BackupValidationResultType } from '../services/backups'; -import { SettingsRow, SettingsControl } from './PreferencesUtil'; +import { SettingsRow, FlowingSettingsControl } from './PreferencesUtil'; import { Button, ButtonVariant } from './Button'; import { Spinner } from './Spinner'; import type { MessageCountBySchemaVersionType } from '../sql/Interface'; @@ -124,9 +126,17 @@ export function PreferencesInternal({ className="Preferences--internal--backups" title={i18n('icu:Preferences__button--backups')} > - +
+ {i18n('icu:Preferences__internal__validate-backup--description')} +
+
+ {renderValidationResult(validationResult)}
@@ -148,11 +158,19 @@ export function PreferencesInternal({ className="Preferences--internal--backups" title={i18n('icu:Preferences__internal__local-backups')} > - +
+ {i18n( + 'icu:Preferences__internal__export-local-backup--description' + )} +
+
+ {renderValidationResult(exportResult)}
@@ -174,9 +192,17 @@ export function PreferencesInternal({ className="Preferences--internal--message-schemas" title="Message schema versions" > - +
+ Check message schema versions +
+
- } - /> +
+ {messageCountBySchemaVersion ? (
diff --git a/ts/components/PreferencesLocalBackups.tsx b/ts/components/PreferencesLocalBackups.tsx index 7adcb4168c..2ffaabff16 100644 --- a/ts/components/PreferencesLocalBackups.tsx +++ b/ts/components/PreferencesLocalBackups.tsx @@ -10,8 +10,13 @@ import React, { useRef, } from 'react'; import { noop } from 'lodash'; +import classNames from 'classnames'; + import type { LocalizerType } from '../types/I18N'; -import { SettingsControl as Control, SettingsRow } from './PreferencesUtil'; +import { + FlowingSettingsControl as FlowingControl, + SettingsRow, +} from './PreferencesUtil'; import { Button, ButtonSize, ButtonVariant } from './Button'; import { SIGNAL_BACKUPS_LEARN_MORE_URL } from './PreferencesBackups'; import { I18n } from './I18n'; @@ -87,42 +92,54 @@ export function PreferencesLocalBackups({
- +
- } - right={ +
+
- } - /> - + + +
- } - right={ +
+
- } - /> +
+
diff --git a/ts/components/PreferencesUtil.tsx b/ts/components/PreferencesUtil.tsx index 2d95b36d94..fdf6142a4d 100644 --- a/ts/components/PreferencesUtil.tsx +++ b/ts/components/PreferencesUtil.tsx @@ -27,19 +27,42 @@ export function SettingsRow({ ); } +export function FlowingSettingsControl({ + children, +}: { + children: ReactNode; +}): JSX.Element { + return
{children}
; +} + +export function LightIconLabel({ + icon, + children, +}: { + icon: string; + children: ReactNode; +}): JSX.Element { + return ( +