UX: chat message thread indicator improvements (#22224)

- gridified the thread message indicator, alleviating some problems with positioning and overflow
participant avatars will overlap/smush on smaller size and mobile
- the excerpt went from 3 > 2 lines of wrapping on smaller size, still 1 line on large size
- dropped the copy of "last reply"
- fixed wrong line height
- moved the "x replies" over to the right near the participants, as that makes more sense
- using a bubble to indicate other participants, instead of copy

This PR introduces the @container query, which is experimental. Nothing will break when it's being viewed in a not-supported browser, but it will be less elegant.
This commit is contained in:
chapoi 2023-06-26 21:47:13 +09:00 committed by GitHub
parent 4dd9487e25
commit 802fb3b194
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 142 additions and 178 deletions

View File

@ -8,50 +8,24 @@
role="button" role="button"
title={{i18n "chat.threads.open"}} title={{i18n "chat.threads.open"}}
> >
{{#unless this.chatStateManager.isDrawerActive}}
<div class="chat-message-thread-indicator__last-reply-avatar">
<ChatUserAvatar
@user={{@message.thread.preview.lastReplyUser}}
@avatarSize="small"
/>
</div>
{{/unless}}
<div class="chat-message-thread-indicator__body">
<div class="chat-message-thread-indicator__last-reply-metadata">
<div class="chat-message-thread-indicator__last-reply-user">
{{#if (or this.site.mobileView this.chatStateManager.isDrawerActive)}}
<span
class="chat-message-thread-indicator__last-reply-avatar -mobile"
>
<ChatUserAvatar
@user={{@message.thread.preview.lastReplyUser}}
@avatarSize="tiny"
/>
</span>
{{/if}}
<span class="chat-message-thread-indicator__last-reply-username">
{{@message.thread.preview.lastReplyUser.username}}
</span>
</div>
<span class="chat-message-thread-indicator__last-reply-container">
{{format-date
@message.thread.preview.lastReplyCreatedAt
leaveAgo="true"
prefix=(i18n "chat.thread.last_reply")
}}
</span>
<span class="separator">|</span>
<span class="chat-message-thread-indicator__replies-count">
{{i18n "chat.thread.replies" count=@message.thread.preview.replyCount}}
</span>
</div> <div class="chat-message-thread-indicator__last-reply-avatar">
<div class="chat-message-thread-indicator__last-reply-excerpt"> <ChatUserAvatar
{{replace-emoji (html-safe @message.thread.preview.lastReplyExcerpt)}} @user={{@message.thread.preview.lastReplyUser}}
</div> @avatarSize="small"
/>
</div> </div>
<div class="chat-message-thread-indicator__participants"> <div class="chat-message-thread-indicator__last-reply-info">
<Chat::Thread::Participants @thread={{@message.thread}} /> <span class="chat-message-thread-indicator__last-reply-username">
{{@message.thread.preview.lastReplyUser.username}}
</span>
<span class="chat-message-thread-indicator__last-reply-timestamp">
{{format-date @message.thread.preview.lastReplyCreatedAt leaveAgo="true"}}
</span>
</div>
<Chat::Thread::Participants @thread={{@message.thread}} />
<div class="chat-message-thread-indicator__last-reply-excerpt">
{{replace-emoji (html-safe @message.thread.preview.lastReplyExcerpt)}}
</div> </div>
</div> </div>

View File

@ -1,4 +1,7 @@
{{#if (gt @thread.preview.participantUsers.length 1)}} {{#if (gt @thread.preview.participantUsers.length 1)}}
<div class="chat-message-thread-indicator__replies-count">
{{i18n "chat.thread.replies" count=@thread.preview.replyCount}}
</div>
<div class="chat-thread-participants"> <div class="chat-thread-participants">
<div class="chat-thread-participants__avatar-group"> <div class="chat-thread-participants__avatar-group">
{{#each @thread.preview.participantUsers as |user|}} {{#each @thread.preview.participantUsers as |user|}}
@ -8,14 +11,11 @@
@showPresence={{false}} @showPresence={{false}}
/> />
{{/each}} {{/each}}
{{#if @thread.preview.otherParticipantCount}}
<div class="chat-thread-participants__other-count">
+{{@thread.preview.otherParticipantCount}}
</div>
{{/if}}
</div> </div>
{{#if @thread.preview.otherParticipantCount}}
<div class="chat-thread-participants__other-count">
{{i18n
"chat.thread.participants_other_count"
count=@thread.preview.otherParticipantCount
}}
</div>
{{/if}}
</div> </div>
{{/if}} {{/if}}

View File

@ -1,14 +1,16 @@
.chat-message {
container-type: inline-size;
}
.chat-message-thread-indicator { .chat-message-thread-indicator {
display: flex;
align-items: center;
gap: 1rem;
cursor: pointer; cursor: pointer;
grid-area: threadindicator; grid-area: threadindicator;
max-width: 1000px; box-sizing: border-box;
display: grid;
grid-template-columns: auto 1fr auto auto;
background-color: var(--primary-very-low); background-color: var(--primary-very-low);
margin: 4px 0 -2px calc(var(--message-left-width) - 0.25rem); margin: 4px 0 -2px calc(var(--message-left-width) - 0.25rem);
padding-block: 0.5rem; padding: 0.5rem;
padding-inline: 0.5rem;
border-radius: 8px; border-radius: 8px;
color: var(--primary); color: var(--primary);
@ -21,6 +23,12 @@
color: var(--primary); color: var(--primary);
} }
&:hover {
.chat-message-thread-indicator__replies-count {
text-decoration: underline;
}
}
.touch & { .touch & {
&.-active { &.-active {
box-shadow: var(--shadow-dropdown); box-shadow: var(--shadow-dropdown);
@ -33,70 +41,52 @@
} }
} }
&__participants {
flex-shrink: 0;
align-self: flex-start;
}
&__last-reply-avatar { &__last-reply-avatar {
align-self: flex-start; grid-area: avatar;
margin-right: 0.5rem;
.chat-user-avatar { .chat-user-avatar {
width: auto !important; width: auto !important;
} }
} }
&__last-reply-metadata {
display: flex;
align-items: flex-end;
gap: 0.25rem;
color: var(--primary-medium);
.separator {
font-size: var(--font-down-1);
}
}
&__last-reply-container {
display: inline-flex;
align-items: flex-end;
font-size: var(--font-down-1);
min-width: 0;
.relative-date {
@include ellipsis;
}
}
&__last-reply-user {
font-weight: bold;
color: var(--secondary-low);
}
&__last-reply-username { &__last-reply-username {
@include ellipsis;
font-weight: bold; font-weight: bold;
color: var(--secondary-low); color: var(--primary-very-high);
margin-right: 0.25rem;
}
&__last-reply-info {
grid-area: info;
display: flex;
align-items: center;
gap: 0.25rem;
}
&__last-reply-timestamp {
color: var(--primary-high);
font-size: var(--font-down-2);
} }
&__last-reply-excerpt { &__last-reply-excerpt {
@include ellipsis; @include ellipsis;
line-height: 1.8rem; grid-area: excerpt;
} }
&__body { .chat-thread-participants {
overflow: hidden; grid-area: participants;
white-space: nowrap; flex-shrink: 0;
flex-shrink: 1; display: flex;
} align-items: center;
justify-content: flex-end;
&:hover { gap: 0.5rem;
.chat-message-thread-indicator__replies-count {
text-decoration: underline;
}
} }
&__replies-count { &__replies-count {
@include ellipsis; @include ellipsis;
color: var(--tertiary); color: var(--tertiary);
font-size: var(--font-down-1); font-size: var(--font-down-1);
text-align: right;
} }
} }

View File

@ -1,14 +1,31 @@
.chat-thread-participants { .chat-thread-participants {
margin-left: 0.5rem;
&__other-count { &__other-count {
display: flex;
align-items: center;
justify-content: center;
width: 22px;
height: 22px;
border: 1px solid rgba(0, 0, 0, 0);
box-sizing: border-box;
font-size: var(--font-down-2); font-size: var(--font-down-2);
text-align: right; color: var(--primary-very-low);
color: var(--primary-medium); background: var(--secondary-high);
padding: 0.21em 0.42em;
border-radius: 1em;
text-align: center;
white-space: nowrap;
} }
&__avatar-group { &__avatar-group {
display: flex; display: flex;
align-items: center;
justify-content: flex-end; justify-content: flex-end;
.chat-user-avatar-container {
padding: 0;
}
.chat-user-avatar { .chat-user-avatar {
width: auto !important; width: auto !important;
@ -20,3 +37,29 @@
} }
} }
} }
@container (max-width: 400px) {
.chat-thread-participants {
&__avatar-group {
flex-direction: row-reverse;
justify-content: flex-start;
.chat-user-avatar {
&:not(:first-child) {
margin-right: -12px;
}
.avatar {
width: 22px;
height: 22px;
border: 1px solid var(--primary-very-low);
}
}
}
&__other-count {
width: 22px;
height: 22px;
margin-right: -12px;
z-index: 1;
border: 1px solid var(--primary-very-low);
}
}
}

View File

@ -1,59 +1,31 @@
.chat-message-thread-indicator { .chat-message-thread-indicator {
max-width: 600px; grid-template-areas:
"avatar info replies participants"
"avatar excerpt excerpt excerpt";
.chat-drawer & { &__replies-count {
align-items: stretch; display: flex;
flex-wrap: wrap; align-self: center;
width: auto;
max-width: 100%;
min-width: auto;
gap: 0.25rem;
} }
}
&__last-reply-avatar { @container (max-width: 400px) {
.chat-drawer & { .chat-message-thread-indicator {
display: inline-block; grid-template-areas:
"avatar info info participants"
"excerpt excerpt excerpt replies";
&__replies-count {
align-self: flex-start;
grid-area: replies;
justify-content: flex-end;
} }
} &__last-reply-excerpt {
&__last-reply-user {
margin-right: 0.25rem;
.chat-drawer & {
display: flex;
align-items: center;
gap: 0.5rem;
margin-right: auto;
}
}
&__last-reply-metadata {
.chat-drawer & {
flex-wrap: wrap;
}
}
&__last-reply-excerpt {
.chat-drawer & {
white-space: wrap; white-space: wrap;
display: -webkit-box; display: -webkit-box;
-webkit-line-clamp: 3; -webkit-line-clamp: 2;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
margin-left: calc(26px + 0.5rem); margin-top: 0.5rem;
} margin-right: 0.25rem;
}
&__body {
.chat-drawer & {
flex-grow: 1;
}
}
&__participants {
margin-left: auto;
.chat-drawer & {
align-self: flex-end;
flex-basis: 100%;
} }
} }
} }

View File

@ -1,39 +1,24 @@
.chat-message-thread-indicator { .chat-message-thread-indicator {
&__participants, grid-template-areas:
&__last-reply-avatar:not(.-mobile) { "avatar info info participants"
display: none; "excerpt excerpt excerpt replies";
}
&__last-reply-metadata { .chat-thread-participants {
display: flex;
align-items: center;
gap: 0.25rem;
margin-bottom: 0.25rem;
}
&__last-reply-user {
display: flex;
align-items: center;
gap: 0.5rem;
margin-right: auto;
}
&__last-reply-avatar {
align-self: center;
.avatar { .avatar {
width: 18px; width: 22px;
height: 18px; height: 22px;
} }
} }
&__last-reply-username {
margin-right: auto;
}
&__last-reply-excerpt { &__last-reply-excerpt {
white-space: wrap; white-space: wrap;
display: -webkit-box; display: -webkit-box;
-webkit-line-clamp: 3; -webkit-line-clamp: 2;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
margin-top: 0.5rem;
margin-right: 0.25rem;
}
&__replies-count {
grid-area: replies;
} }
} }