diff --git a/_locales/en/messages.json b/_locales/en/messages.json index d025f0f18..5c38a28d2 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1163,7 +1163,7 @@ "description": "Label for the time a message was received" }, "sendMessage": { - "message": "Send a message", + "message": "Message", "description": "Placeholder text in the message entry field" }, "groupMembers": { diff --git a/images/icons/v2/chevron-down-20.svg b/images/icons/v2/chevron-down-20.svg new file mode 100644 index 000000000..29da65daa --- /dev/null +++ b/images/icons/v2/chevron-down-20.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/v2/phone-outline-24.svg b/images/icons/v2/phone-outline-24.svg index 76fa8539c..09d86bf78 100644 --- a/images/icons/v2/phone-outline-24.svg +++ b/images/icons/v2/phone-outline-24.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/stylesheets/_modules.scss b/stylesheets/_modules.scss index 35b6ad830..ee4a7cc94 100644 --- a/stylesheets/_modules.scss +++ b/stylesheets/_modules.scss @@ -3950,7 +3950,7 @@ button.module-image__border-overlay:focus { &__button { &::before { @include color-svg( - '../images/icons/v2/arrow-down-24.svg', + '../images/icons/v2/chevron-down-24.svg', $color-white ); @@ -6181,15 +6181,14 @@ button.module-image__border-overlay:focus { background: none; width: 32px; height: 32px; - border-radius: 16px; display: flex; justify-content: center; align-items: center; - opacity: 0.5; - &:focus, - &:hover { - opacity: 1; + @include keyboard-mode { + &:focus { + outline: 1px solid $color-ultramarine; + } } outline: none; @@ -6209,7 +6208,7 @@ button.module-image__border-overlay:focus { } @include dark-theme { @include color-svg( - '../images/icons/v2/sticker-solid-24.svg', + '../images/icons/v2/sticker-outline-24.svg', $color-gray-15 ); } @@ -6686,15 +6685,14 @@ button.module-image__border-overlay:focus { background: none; width: 32px; height: 32px; - border-radius: 16px; display: flex; justify-content: center; align-items: center; - opacity: 0.5; - &:focus, - &:hover { - opacity: 1; + @include keyboard-mode { + &:focus { + outline: 1px solid $color-ultramarine; + } } outline: none; @@ -6714,7 +6712,7 @@ button.module-image__border-overlay:focus { } @include dark-theme { @include color-svg( - '../images/icons/v2/emoji-smiley-solid-24.svg', + '../images/icons/v2/emoji-smiley-outline-24.svg', $color-gray-15 ); } @@ -6796,6 +6794,7 @@ button.module-image__border-overlay:focus { padding: 0; text-align: start; white-space: break-spaces; + line-height: inherit; &--loaded { caret-color: auto; @@ -6830,7 +6829,6 @@ button.module-image__border-overlay:focus { } &__input { - border: none; border-radius: 18px; overflow: hidden; word-break: break-word; @@ -6838,28 +6836,34 @@ button.module-image__border-overlay:focus { // Override Quill styles .ql-container { @include font-body-1; + line-height: 21px; + font-size: 15px; } .ql-blank::before { - color: $color-gray-45; + @include light-theme() { + color: $color-gray-45; + } + + @include dark-theme() { + color: $color-gray-25; + } } @include light-theme() { // Same as background color - border: 1px solid $color-white; background-color: $color-gray-05; color: $color-gray-90; } @include dark-theme() { // Same as background color - border: 1px solid $color-gray-95; background-color: $color-gray-75; color: $color-gray-05; } &__scroller { - padding: 7px 12px; + padding: 5px 11px 6px 11px; min-height: 32px; max-height: 80px; overflow: auto; @@ -6885,11 +6889,11 @@ button.module-image__border-overlay:focus { &:focus-within { @include light-theme() { - border: 1px solid $color-ultramarine; + outline: 1px solid $color-ultramarine; } @include dark-theme() { - border: 1px solid $color-ultramarine; + outline: 1px solid $color-ultramarine; } } } @@ -7000,57 +7004,6 @@ button.module-image__border-overlay:focus { } } -// Module: Scroll Down Button - -.module-scroll-down { - z-index: $z-index-scroll-down-button; - position: absolute; - right: 20px; - bottom: 10px; -} - -.module-scroll-down__button { - height: 44px; - width: 44px; - border-radius: 22px; - text-align: center; - border: none; - outline: none; - - @include light-theme { - background-color: $color-gray-25; - &:hover { - background-color: $color-gray-45; - } - - box-shadow: 0px 3px 5px 0px $color-black-alpha-20; - } - @include dark-theme { - background-color: $color-gray-45; - &:hover { - background-color: $color-gray-25; - } - - box-shadow: 0px 3px 5px 0px $color-white-alpha-20; - } -} - -.module-scroll-down__button--new-messages { - background-color: $color-ultramarine; - - &:hover { - background-color: $color-ultramarine-dark; - } -} - -.module-scroll-down__icon { - @include color-svg('../images/icons/v2/arrow-down-24.svg', $color-white); - height: 36px; - width: 36px; - margin-left: -3px; - margin-top: -1px; -} - // Module: Avatar Popup .module-avatar-popup { diff --git a/stylesheets/_variables.scss b/stylesheets/_variables.scss index 40d93455c..e6d4258dd 100644 --- a/stylesheets/_variables.scss +++ b/stylesheets/_variables.scss @@ -43,6 +43,7 @@ $color-black-alpha-08: rgba($color-black, 0.08); $color-black-alpha-12: rgba($color-black, 0.12); $color-black-alpha-16: rgba($color-black, 0.16); $color-black-alpha-20: rgba($color-black, 0.2); +$color-black-alpha-24: rgba($color-black, 0.24); $color-black-alpha-30: rgba($color-black, 0.3); $color-black-alpha-40: rgba($color-black, 0.4); $color-black-alpha-50: rgba($color-black, 0.5); diff --git a/stylesheets/components/AudioCapture.scss b/stylesheets/components/AudioCapture.scss index 0efa5c469..53ce6b3d4 100644 --- a/stylesheets/components/AudioCapture.scss +++ b/stylesheets/components/AudioCapture.scss @@ -8,21 +8,23 @@ justify-content: center; align-items: center; background: none; - padding: 0 5px; &__microphone { height: 32px; width: 32px; text-align: center; - opacity: 0.5; background: none; + display: flex; + align-items: center; + justify-content: center; padding: 0; border: none; - &:focus, - &:hover { - opacity: 1; + @include keyboard-mode { + &:focus { + outline: 1px solid $color-ultramarine; + } } outline: none; @@ -41,7 +43,7 @@ } @include dark-theme { @include color-svg( - '../images/icons/v2/mic-solid-24.svg', + '../images/icons/v2/mic-outline-24.svg', $color-gray-15 ); } diff --git a/stylesheets/components/CompositionArea.scss b/stylesheets/components/CompositionArea.scss index 6212d9c9d..b48f0b26d 100644 --- a/stylesheets/components/CompositionArea.scss +++ b/stylesheets/components/CompositionArea.scss @@ -16,6 +16,8 @@ &__row { display: flex; flex-direction: row; + align-items: center; + &--center { justify-content: center; } @@ -31,28 +33,22 @@ } &__button-cell { - margin-top: 2px; + margin: 0 6px; display: flex; justify-content: center; align-items: center; - width: 40px; height: 100%; flex-shrink: 0; - &--mic-active { - width: 150px; + + &:first-child { + margin-left: 12px; } - &--large-right { - margin-left: auto; - margin-right: 4px; - } - &--large-right-mic-active { - margin-left: auto; + + &:last-child { margin-right: 12px; } } &__send-button { - width: 32px; - height: 32px; display: flex; justify-content: center; align-items: center; @@ -69,6 +65,11 @@ } &__input { flex-grow: 1; + margin: 0 6px; + + &--large { + margin: 0; + } } $comp-area: &; &__toggle-large { @@ -76,7 +77,7 @@ height: 24px; position: absolute; left: calc(50% - 24px); - top: -18px; + top: -19px; border-radius: 12px 12px 0 0; pointer-events: none; @@ -188,13 +189,16 @@ width: 32px; height: 32px; padding: 0; - opacity: 0.5; border: none; background: transparent; + display: flex; + align-items: center; + justify-content: center; - &:focus, - &:hover { - opacity: 1; + @include keyboard-mode { + &:focus { + outline: 1px solid $color-ultramarine; + } } outline: none; diff --git a/stylesheets/components/ConversationHeader.scss b/stylesheets/components/ConversationHeader.scss index 35ab7a6dd..28dbb5591 100644 --- a/stylesheets/components/ConversationHeader.scss +++ b/stylesheets/components/ConversationHeader.scss @@ -185,7 +185,8 @@ -webkit-app-region: no-drag; @include button-reset; - align-items: stretch; + align-items: center; + justify-content: center; border-radius: 4px; border: 2px solid transparent; display: flex; @@ -240,56 +241,49 @@ } } - @mixin normal-button($light-icon, $dark-icon) { + @mixin normal-button($icon, $size) { &::before { content: ''; display: block; - flex-grow: 1; + width: $size; + height: $size; + @include light-theme { - @include color-svg($light-icon, $color-gray-75); + @include color-svg($icon, $color-gray-75); &:hover, &:active, &:focus { - @include color-svg($light-icon, $color-gray-90); + @include color-svg($icon, $color-gray-90); } } @include dark-theme { - @include color-svg($dark-icon, $color-gray-15); + @include color-svg($icon, $color-gray-15); &:hover, &:active, &:focus { - @include color-svg($dark-icon, $color-gray-02); + @include color-svg($icon, $color-gray-02); } } } } &--video { - @include normal-button( - '../images/icons/v2/video-outline-24.svg', - '../images/icons/v2/video-solid-24.svg' - ); + @include normal-button('../images/icons/v2/video-outline-24.svg', 24px); } &--audio { @include normal-button( '../images/icons/v2/phone-right-outline-24.svg', - '../images/icons/v2/phone-right-solid-24.svg' + 24px ); } &--search { - @include normal-button( - '../images/icons/v2/search-24.svg', - '../images/icons/v2/search-24.svg' - ); + @include normal-button('../images/icons/v2/search-24.svg', 24px); } &--more { - @include normal-button( - '../images/icons/v2/chevron-down-24.svg', - '../images/icons/v2/chevron-down-24.svg' - ); + @include normal-button('../images/icons/v2/chevron-down-20.svg', 20px); } &--join-call { diff --git a/stylesheets/components/ScrollDownButton.scss b/stylesheets/components/ScrollDownButton.scss new file mode 100644 index 000000000..390efa554 --- /dev/null +++ b/stylesheets/components/ScrollDownButton.scss @@ -0,0 +1,68 @@ +// Copyright 2018-2022 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only + +.ScrollDownButton { + z-index: $z-index-scroll-down-button; + position: absolute; + right: 16px; + bottom: 12px; + + &__button { + position: relative; + + height: 36px; + width: 36px; + + display: flex; + border-radius: 18px; + border: none; + outline: none; + align-items: center; + justify-content: center; + + box-shadow: 0px 0px 2px $color-black-alpha-20, + 0px 2px 6px $color-black-alpha-12; + + @include light-theme { + background-color: $color-white; + } + @include dark-theme { + background-color: $color-gray-75; + } + + &__icon { + @include light-theme { + @include color-svg( + '../images/icons/v2/chevron-down-20.svg', + $color-gray-75 + ); + } + + @include dark-theme { + @include color-svg( + '../images/icons/v2/chevron-down-20.svg', + $color-gray-15 + ); + } + + height: 20px; + width: 20px; + } + + &__badge { + position: absolute; + top: -8px; + height: 16px; + min-width: 16px; + border-radius: 8px; + padding: 1px 4px; + background-color: $color-ultramarine; + color: $color-white; + + font-size: 10px; + line-height: 14px; + + box-shadow: 0px 1px 4px $color-black-alpha-24; + } + } +} diff --git a/stylesheets/manifest.scss b/stylesheets/manifest.scss index 864548711..f29c059c9 100644 --- a/stylesheets/manifest.scss +++ b/stylesheets/manifest.scss @@ -96,6 +96,7 @@ @import './components/ReactionPickerPicker.scss'; @import './components/SafetyNumberChangeDialog.scss'; @import './components/SafetyNumberViewer.scss'; +@import './components/ScrollDownButton.scss'; @import './components/SearchInput.scss'; @import './components/SearchResultsLoadingFakeHeader.scss'; @import './components/SearchResultsLoadingFakeRow.scss'; diff --git a/ts/components/CompositionArea.tsx b/ts/components/CompositionArea.tsx index 54397a0d7..1b6226325 100644 --- a/ts/components/CompositionArea.tsx +++ b/ts/components/CompositionArea.tsx @@ -380,22 +380,24 @@ export const CompositionArea = ({ ); const micButtonFragment = shouldShowMicrophone ? ( - { - onSendMessage({ voiceNoteAttachment }); - }} - startRecording={startRecording} - /> +
+ { + onSendMessage({ voiceNoteAttachment }); + }} + startRecording={startRecording} + /> +
) : null; const isRecording = recordingState === RecordingState.Recording; @@ -412,19 +414,17 @@ export const CompositionArea = ({ ); const sendButtonFragment = ( -
-
+ <> +
+
+
+ ); const stickerButtonPlacement = large ? 'top-start' : 'top-end'; @@ -664,7 +664,12 @@ export const CompositionArea = ({ )} > {!large ? leftHandSideButtonsFragment : null} -
+
= {}): Props => ({ i18n, - withNewMessages: boolean( - 'withNewMessages', - overrideProps.withNewMessages || false - ), scrollDown: action('scrollDown'), conversationId: 'fake-conversation-id', + ...overrideProps, }); export default { title: 'Components/Conversation/ScrollDownButton', -}; - -export const NoNewMessages = (): JSX.Element => { - const props = createProps(); - - return ; -}; - -export const NewMessages = (): JSX.Element => { - const props = createProps({ withNewMessages: true }); - - return ; + component: ScrollDownButton, + argTypes: { + unreadCount: { + control: { type: 'radio' }, + options: { + None: undefined, + Some: 5, + Plenty: 85, + 'Please Stop': 1000, + }, + }, + }, +} as Meta; + +const Template: Story = args => ; + +export const Default = Template.bind({}); +Default.args = createProps({}); +Default.story = { + name: 'Default', }; diff --git a/ts/components/conversation/ScrollDownButton.tsx b/ts/components/conversation/ScrollDownButton.tsx index b50d8aecb..1313b6163 100644 --- a/ts/components/conversation/ScrollDownButton.tsx +++ b/ts/components/conversation/ScrollDownButton.tsx @@ -2,12 +2,11 @@ // SPDX-License-Identifier: AGPL-3.0-only import React from 'react'; -import classNames from 'classnames'; import type { LocalizerType } from '../../types/Util'; export type Props = { - withNewMessages: boolean; + unreadCount?: number; conversationId: string; scrollDown: (conversationId: string) => void; @@ -17,26 +16,35 @@ export type Props = { export const ScrollDownButton = ({ conversationId, - withNewMessages, + unreadCount, i18n, scrollDown, }: Props): JSX.Element => { - const altText = withNewMessages ? i18n('messagesBelow') : i18n('scrollDown'); + const altText = unreadCount ? i18n('messagesBelow') : i18n('scrollDown'); + + let badgeText: string | undefined; + if (unreadCount) { + if (unreadCount < 100) { + badgeText = unreadCount.toString(); + } else { + badgeText = '99+'; + } + } return ( -
+
); diff --git a/ts/components/conversation/Timeline.tsx b/ts/components/conversation/Timeline.tsx index e3b2a0415..139644731 100644 --- a/ts/components/conversation/Timeline.tsx +++ b/ts/components/conversation/Timeline.tsx @@ -1185,7 +1185,7 @@ export class Timeline extends React.Component< {shouldShowScrollDownButton ? (