zulip/web/styles/message_row.css

431 lines
19 KiB
CSS

$avatar_column_width: 46px;
$distance_of_text_elements_from_message_box_top: 8.5px;
$distance_of_non_text_elements_from_message_box_top: 6px;
$sender_name_distance_below_flex_center: 3px;
/* The time column usually just needs enough space to display the
timestamp. The minimum width here is enough for "22:22 PM", which
is roughly the widest this will be in English; this is nice as the
timestamps and message controls will be vertically aligned.
But in some locales, the time encoding is wider, (especially where
the "PM" abbreviation is longer), so we allow the column to be
wider for individual messages if required, to prevent ugly
line-wrapping. In practice, it's unlikely we'll see anything wider
than 60px; so the precise value of $time_column_max_width should be
unimportant. */
$time_column_min_width: 50px; /* + padding */
$time_column_max_width: 150px;
.message_row {
display: grid;
/* 2x2 grid:
date_unread_marker date_row
message_unread_marker messagebox */
grid-template: "date_unread_marker date_row" auto "message_unread_marker messagebox" auto / 2px 1fr;
border-left: 1px solid var(--color-message-list-border);
border-right: 1px solid var(--color-message-list-border);
background-color: var(--color-background-stream-message-content);
&.direct_mention {
background-color: var(--color-background-direct-mention);
}
&.group_mention {
background-color: var(--color-background-group-mention);
}
.date_row {
grid-area: date_row;
/* We only want padding for the date rows between recipient blocks */
padding-bottom: 0;
& span {
font-size: calc(12em / 14);
font-style: normal;
font-weight: 600;
line-height: 17px; /* identical to box height, or 131% */
text-align: right;
letter-spacing: 0.04em;
color: var(--color-date);
/* To match time in message row and date in recipient row. */
padding-right: 6px;
}
}
.unread_marker {
margin-left: var(--unread-marker-left);
opacity: 0;
transition: all 0.3s ease-out;
&.slow_fade {
transition: all 2s ease-out;
}
&.fast_fade {
transition: all 0.3s ease-out;
}
&.date_unread_marker {
grid-area: date_unread_marker;
.unread-marker-fill {
border-radius: 0 !important;
height: 100% !important;
}
}
&.message_unread_marker {
grid-area: message_unread_marker;
}
}
.unread-marker-fill {
height: 100%;
width: 2px;
background: linear-gradient(
90deg,
var(--color-unread-marker) 30%,
hsl(217deg 64% 59% / 0%)
);
}
&.unread .unread_marker {
transition: all 0.3s ease-out;
opacity: 1;
}
.messagebox {
grid-area: messagebox;
word-wrap: break-word;
cursor: pointer;
border: none;
/* The left padding value accounts for a 2px
unread marker, ensuring a uniform 5px of
padding on either side of the message box. */
padding: 0 5px 0 3px;
&:hover .message_controls,
&:focus-within .message_controls,
&:hover .message_failed,
&:focus-within .message_failed {
.empty-star:hover {
cursor: pointer;
}
> div {
opacity: 1;
visibility: visible;
}
}
}
.messagebox .messagebox-content {
/* Total 868px
1 56px 2 697px 3 55px 4 60px(min) 5
1 |‾‾‾‾‾‾‾‾‾‾‾:‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾:‾‾‾‾‾‾‾‾‾‾‾‾‾‾:‾‾‾‾‾‾‾‾‾‾‾‾|
| : TEXT : + ⋮ ☆ : 10:00 AM |
| : TEXT : : |
| EDITED : TEXT : : |
| : TEXT : : |
| : TEXT : : |
2,3 |_ _ _ _ _ _:_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ : _ _ _ _ _ _ _:_ _ _ _ _ _ |
| : : : |
| : [EXPAND / COLLAPSE] : : |
4 |_ _ _ _ _ _:_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ : _ _ _ _ _ _ _:_ _ _ _ _ _ |
| : : : |
| : [Message Reactions] : : |
5 |___________:____________________________________________________________________________________________________:______________:____________|
*/
display: grid;
align-items: start;
padding-left: 10px;
grid-template-rows: repeat(4, auto);
grid-template-columns: $avatar_column_width auto 55px fit-content(
$time_column_max_width
);
@media (width < $sm_min) {
grid-template-columns: $avatar_column_width auto max-content fit-content(
$time_column_max_width
);
}
.message_controls {
grid-row-start: 1;
grid-column-start: 3;
line-height: 1;
justify-self: end;
/* We need to position it from top and not vertically centered since we want it
to have the same position from top when user is editing the message. */
position: relative;
top: $distance_of_non_text_elements_from_message_box_top;
padding: 0;
@media (width < $sm_min) {
padding: 0 4px;
/* This is intended to target the first message_controls child
when there are 3 displayed. 4 = 3 + hidden message_failed element. */
.message_control_button:nth-last-child(4) {
display: none;
}
}
}
.message_edit_notice {
grid-row-start: 1;
position: relative;
top: $distance_of_text_elements_from_message_box_top;
}
.message_time {
line-height: 1;
justify-self: end;
padding-right: 5px;
min-width: $time_column_min_width;
text-align: end;
grid-row-start: 1;
grid-column-start: 4;
position: relative;
top: $distance_of_text_elements_from_message_box_top;
&.notvisible {
/* This happens when message failed to send. We don't want to
display time but still want it to occupy space. */
width: 45px !important;
position: unset !important;
}
}
.slow-send-spinner {
display: none;
justify-self: end;
margin-right: 10px;
text-align: end;
grid-row-start: 1;
grid-column-start: 4;
position: relative;
top: $distance_of_text_elements_from_message_box_top;
}
.message_content {
grid-row-start: 1;
grid-column-start: 2;
/*
Space between two single line messages in a paragraph is 10px.
There is 3px margin above and below a message. So, having a 2px
padding above and below the message will make the space between
all single paragraphs the same.
*/
padding: 2px 0;
}
.message_reactions {
grid-row-start: 4;
grid-column-start: 2;
margin-top: -1px;
}
.message_edit {
grid-row-start: 2;
grid-column-start: 2;
}
.alert-msg {
grid-row-start: 1;
grid-column: 3 / 5;
margin-top: 4px;
}
.message_length_controller {
grid-row-start: 3;
grid-column-start: 2;
}
}
&.include-sender {
/*
1 2 3 4 5
1 |‾‾‾‾‾‾‾‾‾‾‾:‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾:‾‾‾‾‾‾‾‾‾‾‾‾‾‾:‾‾‾‾‾‾‾‾‾‾‾‾|
| ((((\\\ : Sender Name EDITED : + ⋮ ☆ : 10:00 AM |
2 | 9_9 3)) :_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ : _ _ _ _ _ _ _:_ _ _ _ _ _ |
| \= (( : TEXT : : |
| : TEXT : : |
| : TEXT : : |
| : TEXT : : |
| : TEXT : : |
3 |_ _ _ _ _ _:_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ : _ _ _ _ _ _ _:_ _ _ _ _ _ |
| : : : |
| : [EXPAND / COLLAPSE] : : |
4 |_ _ _ _ _ _:_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ : _ _ _ _ _ _ _:_ _ _ _ _ _ |
| : : : |
| : [Message Reactions] : : |
5 |___________:____________________________________________________________________________________________________:______________:____________|
*/
.messagebox .messagebox-content {
grid-template-rows: 25px repeat(3, auto);
.message_content {
padding-top: 0;
grid-row-start: 2;
}
.message_time {
align-self: center;
position: unset;
margin-top: 1px;
}
.slow-send-spinner {
align-self: center;
position: unset;
margin-top: 1px;
}
.message_edit_notice {
align-self: center;
top: 2px;
}
.message_controls {
align-self: center;
position: unset;
}
.message_sender {
overflow: hidden;
text-overflow: ellipsis;
grid-column: 1 / 3;
grid-row: 1 / 2;
.zulip-icon.zulip-icon-bot {
align-self: center;
padding: $sender_name_distance_below_flex_center 0 0 5px;
}
&.is_me_message {
/*
1 2 3 4 5
1,2 |‾‾‾‾‾‾‾‾‾‾‾:‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾:‾‾‾‾‾‾‾‾‾‾‾‾‾‾:‾‾‾‾‾‾‾‾‾‾‾‾|
| ((((\\\ : : : |
| 9_9 3)) : Sender Name is excited to write this multiline message that goes to the next line and takes the : + ⋮ ☆ : 10:00 AM |
| \= (( : edit status with it to the next line. EDITED : : |
3 |_ _ _ _ _ _:_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ : _ _ _ _ _ _ _:_ _ _ _ _ _ |
| : : : |
| : [EXPAND / COLLAPSE] : : |
4 |_ _ _ _ _ _:_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ : _ _ _ _ _ _ _:_ _ _ _ _ _ |
| : : : |
| : [Message Reactions] : : |
5 |___________:____________________________________________________________________________________________________:______________:____________|
*/
min-height: $avatar_column_width;
grid-row: 1 / 3;
display: grid;
grid-template-columns: $avatar_column_width auto;
grid-template-rows: auto;
& ~ .alert-msg,
& ~ .message_time,
& ~ .slow-send-spinner,
& ~ .message_controls {
grid-row: 1 / 3;
}
.sender-status {
display: inline;
margin: 0;
margin-top: 13px;
.message_edit_notice {
position: relative;
top: -1px;
}
}
}
> span {
display: flex;
}
.inline_profile_picture {
flex-shrink: 0;
/* Let user profile picture take extra height without
having any affect on height of the container. */
position: absolute;
margin-top: $distance_of_non_text_elements_from_message_box_top;
}
.sender_name {
margin-top: $sender_name_distance_below_flex_center;
}
.sender_name,
.sender_name-in-status {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
/* It is important to use line-height `normal` here since user's name can
be in any language and `line-height: 1` doesn't work to accommodate text
from start and end vertically in all languages. */
line-height: normal;
outline: none;
}
.sender_name_padding {
/* Add padding to align user name with the content. This region is
important to ensure that the hover region for the sender name
and avatar are continuous with each other. */
padding-left: $avatar_column_width;
}
.sender_name-in-status .sender_name_padding {
margin-left: -$avatar_column_width;
}
}
&.content_edit_mode {
.is_me_message {
& ~ .alert-msg,
& ~ .message_time,
& ~ .message_controls {
grid-row: 1 / 2;
}
}
}
}
}
/* Locally echoed messages. */
&.locally-echoed .message_time {
opacity: 0;
/* Don't show pointer when message_time doesn't has a link. */
cursor: default;
}
/* Show the spinner only for messages that are still locally echoed. */
&.locally-echoed .slow-send-spinner {
display: unset !important;
cursor: default;
}
}
.recipient_row {
/* See https://stackoverflow.com/questions/2717480/css-selector-for-first-element-with-class/8539107#8539107
for details on how this works */
.message_row.unread {
.date_unread_marker {
display: none;
}
}
/* Select all but the first .message_row.unread,
and remove the properties set from the previous rule. */
.message_row.unread ~ .message_row.unread {
.date_unread_marker {
display: block;
}
}
}