UX: implements new composer design (#21588)

This is only the first steps of a redesign

- redesigns the buttons to have a larger hitzone
- generally bigger composer
- clicking near textarea focuses the input
- relies on the fact that safe-area-inset-bottom is set globally and doesn’t need to be set in sub components
This commit is contained in:
Joffrey JAFFEUX
2023-05-16 17:17:12 +02:00
committed by GitHub
parent f6670aecfd
commit f45d1e6791
11 changed files with 101 additions and 87 deletions

View File

@ -1,11 +1,14 @@
{{#if @buttons.length}} {{#if @buttons.length}}
<DButton <Chat::Composer::Button
@disabled={{@isDisabled}} {{on "click" this.toggleExpand}}
@class="chat-composer-dropdown__trigger-btn btn-flat btn-icon" @icon="plus"
@title="chat.composer.toggle_toolbar" title={{i18n "chat.composer.toggle_toolbar"}}
@icon={{if @hasActivePanel "times" "plus"}} disabled={{@isDisabled}}
@action={{this.toggleExpand}}
{{did-insert this.setupTrigger}} {{did-insert this.setupTrigger}}
class={{concat-class
"chat-composer-dropdown__trigger-btn"
(if @hasActivePanel "has-active-panel")
}}
/> />
{{#if this.isExpanded}} {{#if this.isExpanded}}
@ -22,7 +25,7 @@
button.id button.id
}} }}
@icon={{button.icon}} @icon={{button.icon}}
@action={{(fn this.onButtonClick button)}} @action={{fn this.onButtonClick button}}
@label={{button.label}} @label={{button.label}}
/> />
</li> </li>

View File

@ -1,4 +1,6 @@
{{! template-lint-disable no-down-event-binding }} {{! template-lint-disable no-down-event-binding }}
{{! template-lint-disable no-invalid-interactive }}
<div class="chat-composer__wrapper"> <div class="chat-composer__wrapper">
{{#if this.shouldRenderMessageDetails}} {{#if this.shouldRenderMessageDetails}}
<ChatComposerMessageDetails <ChatComposerMessageDetails
@ -40,7 +42,10 @@
@onCloseActivePanel={{this.chatEmojiPickerManager.close}} @onCloseActivePanel={{this.chatEmojiPickerManager.close}}
/> />
<div class="chat-composer__input-container"> <div
class="chat-composer__input-container"
{{on "click" this.focusTextarea}}
>
<DTextarea <DTextarea
id={{this.composerId}} id={{this.composerId}}
value={{readonly this.currentMessage.message}} value={{readonly this.currentMessage.message}}
@ -62,12 +67,12 @@
/> />
</div> </div>
<DButton <Chat::Composer::Button
@action={{this.onSend}} {{on "click" this.onSend}}
@icon="paper-plane" @icon="paper-plane"
class="chat-composer__send-btn icon-only" class="chat-composer__send-btn"
@title="chat.composer.send" title="chat.composer.send"
@disabled={{or this.disabled (not this.sendEnabled)}} disabled={{or this.disabled (not this.sendEnabled)}}
tabindex={{if this.sendEnabled 0 -1}} tabindex={{if this.sendEnabled 0 -1}}
{{on "focus" (fn this.computeIsFocused true)}} {{on "focus" (fn this.computeIsFocused true)}}
{{on "blur" (fn this.computeIsFocused false)}} {{on "blur" (fn this.computeIsFocused false)}}
@ -77,7 +82,6 @@
<ChatComposerInlineButtons @buttons={{this.inlineButtons}} /> <ChatComposerInlineButtons @buttons={{this.inlineButtons}} />
{{/unless}} {{/unless}}
</div> </div>
</div> </div>
</div> </div>

View File

@ -174,6 +174,11 @@ export default class ChatComposer extends Component {
}); });
} }
@action
focusTextarea() {
this.textareaInteractor.focus();
}
@action @action
uploadClicked() { uploadClicked() {
document.querySelector(`#${this.fileUploadElementId}`).click(); document.querySelector(`#${this.fileUploadElementId}`).click();

View File

@ -0,0 +1,5 @@
<div class="chat-composer-button">
<button type="button" class="chat-composer-button__btn" ...attributes>
{{d-icon @icon}}
</button>
</div>

View File

@ -0,0 +1,3 @@
import Component from "@glimmer/component";
export default class ChatComposerButton extends Component {}

View File

@ -0,0 +1,14 @@
.chat-composer-button {
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
&__btn {
box-sizing: border-box;
width: 50px;
border: 0;
height: 100%;
background: none;
}
}

View File

@ -7,32 +7,27 @@
} }
.chat-composer-dropdown__trigger-btn { .chat-composer-dropdown__trigger-btn {
padding: 5px !important; // overwrite ios rule
border-radius: 100%;
background: var(--primary-med-or-secondary-high);
border: 1px solid transparent;
display: flex;
.d-icon { .d-icon {
color: var(--secondary-very-high); padding: 5px;
transition: transform 0.1s ease-in-out;
color: var(--primary-high);
background: var(--secondary-very-high);
border-radius: 100%;
} }
&:focus { .no-touch & {
border-color: var(--tertiary); &:hover,
} &:focus {
cursor: pointer;
.discourse-no-touch &:hover { .d-icon {
background: var(--primary-high); color: var(--primary);
.d-icon { }
color: var(--primary-low);
} }
} }
.chat-composer.is-disabled & { &.has-active-panel {
background: var(--primary-400); .d-icon {
transform: rotate(45deg);
&:hover {
cursor: not-allowed;
} }
} }
} }

View File

@ -3,8 +3,8 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
z-index: 3; z-index: 3;
background-color: var(--secondary); background-color: var(--primary-very-low);
margin-top: 0.1rem; padding: 12px 10px 0 10px;
#chat-full-page-uploader, #chat-full-page-uploader,
#chat-widget-uploader { #chat-widget-uploader {
@ -16,10 +16,14 @@
} }
} }
.chat-composer-button,
.chat-composer-separator {
align-self: stretch;
}
&__outer-container { &__outer-container {
display: flex; display: flex;
align-items: center; align-items: center;
padding-inline: 0.25rem;
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
} }
@ -30,11 +34,12 @@
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
flex-direction: row; flex-direction: row;
border: 1px solid var(--primary-low-mid); border: 1px solid var(--primary-medium);
border-radius: 5px; border-radius: 10px;
background-color: var(--secondary); background-color: var(--secondary);
padding-inline: 0.25rem; min-height: 50px;
min-height: 42px; box-shadow: 0px 0px 4px 1px rgba(0, 0, 0, 0.1);
overflow: hidden;
.chat-composer.is-focused & { .chat-composer.is-focused & {
border-color: var(--primary-medium); border-color: var(--primary-medium);
@ -50,8 +55,6 @@
} }
&__send-btn { &__send-btn {
border-radius: 3px;
background: none;
will-change: scale; will-change: scale;
@keyframes sendingScales { @keyframes sendingScales {
@ -65,23 +68,38 @@
transform: scale(0.9); transform: scale(0.9);
} }
} }
.chat-composer.is-sending & { .chat-composer.is-sending & {
animation: sendingScales 1s infinite linear; animation: sendingScales 1s infinite linear;
} }
.d-icon {
background: none !important;
}
.chat-composer.is-send-enabled & { .chat-composer.is-send-enabled & {
background: var(--tertiary-50); .d-icon {
&:focus { color: var(--tertiary);
outline: auto;
} }
.d-icon { &:hover {
color: var(--tertiary) !important; .d-icon {
transform: scale(1.2);
}
}
&:focus {
outline: auto;
} }
} }
.chat-composer.is-send-disabled & { .chat-composer.is-send-disabled & {
cursor: default; cursor: default;
.d-icon {
color: var(--primary-high);
}
&:hover { &:hover {
background: none !important; background: none !important;
} }
@ -89,41 +107,14 @@
.chat-composer.is-disabled & { .chat-composer.is-disabled & {
opacity: 0.4; opacity: 0.4;
&:hover { &:hover {
background: none !important; background: none !important;
} }
} }
> * {
pointer-events: none;
}
.d-icon { .d-icon {
color: var(--primary) !important; color: var(--primary);
}
}
&__close-emoji-picker-btn {
margin-left: 0.2rem;
padding: 5px !important;
border-radius: 100%;
background: var(--primary-med-or-secondary-high);
border: 1px solid transparent;
display: flex;
.d-icon {
color: var(--secondary-very-high);
}
&:focus {
border-color: var(--tertiary);
}
.discourse-no-touch &:hover {
background: var(--primary-high);
.d-icon {
color: var(--primary-low);
}
} }
} }
@ -132,6 +123,8 @@
align-items: center; align-items: center;
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
padding: 0 5px;
align-self: stretch;
} }
&__input { &__input {
@ -144,7 +137,7 @@
max-height: 125px; max-height: 125px;
background: none; background: none;
margin: 0; margin: 0;
padding: 0.25rem 0.5rem; padding: 0;
text-overflow: ellipsis; text-overflow: ellipsis;
cursor: inherit; cursor: inherit;

View File

@ -1,12 +1,7 @@
.chat-replying-indicator-container {
padding: 0 0.5rem;
}
.chat-replying-indicator { .chat-replying-indicator {
color: var(--primary-medium); color: var(--primary-medium);
display: inline-flex; display: inline-flex;
font-size: var(--font-down-2); font-size: var(--font-down-2);
padding-bottom: unquote("max(0px, 0.5rem - env(safe-area-inset-bottom, 0))");
&:before { &:before {
// unicode zero width space character // unicode zero width space character

View File

@ -14,6 +14,7 @@
@import "chat-composer-upload"; @import "chat-composer-upload";
@import "chat-composer-uploads"; @import "chat-composer-uploads";
@import "chat-composer"; @import "chat-composer";
@import "chat-composer-button";
@import "chat-draft-channel"; @import "chat-draft-channel";
@import "chat-drawer"; @import "chat-drawer";
@import "chat-emoji-picker"; @import "chat-emoji-picker";

View File

@ -1,8 +1,4 @@
.chat-composer { .chat-composer {
&__wrapper {
padding: 0;
}
&__input { &__input {
.ios-device & { .ios-device & {
background-color: transparent; background-color: transparent;