mirror of
https://github.com/discourse/discourse.git
synced 2025-06-06 03:06:53 +08:00
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:
@ -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>
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
<div class="chat-composer-button">
|
||||||
|
<button type="button" class="chat-composer-button__btn" ...attributes>
|
||||||
|
{{d-icon @icon}}
|
||||||
|
</button>
|
||||||
|
</div>
|
@ -0,0 +1,3 @@
|
|||||||
|
import Component from "@glimmer/component";
|
||||||
|
|
||||||
|
export default class ChatComposerButton extends Component {}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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";
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
.chat-composer {
|
.chat-composer {
|
||||||
&__wrapper {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__input {
|
&__input {
|
||||||
.ios-device & {
|
.ios-device & {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
Reference in New Issue
Block a user