2024-12-09 14:06:00 -08:00

1533 lines
30 KiB
CSS

:root {
/* Make it easy for stuff to match the width of <body> */
--width-body-margins: 30%;
/**********
* Colors
**********/
--color-twitter-blue: hsl(204, 78%, 49%);
--color-twitter-blue-light: hsl(204, 87%, 73%);
--color-twitter-blue-extra-light: hsl(204, 95%, 85%);
--color-twitter-off-white: hsl(180, 14%, 97%);
--color-twitter-off-white-dark: hsl(180, 17%, 88%);
--color-outline-gray: hsl(204, 0%, 86%);
--color-twitter-text-gray: hsl(204, 15%, 38%);
--color-twitter-danger-red: hsl(356, 91%, 54%);
--color-twitter-danger-red2: hsl(356, 78%, 49%);
--color-twitter-danger-red2-light: hsl(356, 87%, 73%);
--color-twitter-danger-red2-hover: hsl(356, 75%, 80%);
--color-space-purple: hsl(246, 96%, 80%);
--color-space-purple-outline: hsl(246, 97%, 65%);
}
/***************************************************************************************************
*
* Base styles
* -----------
*
* Page global / default styles. Should only use tag selectors or attribute selectors. No ID or
* class selectors; those are purpose-specific, i.e., non-default.
*
***************************************************************************************************/
html {
/*
* Force scrollbar, even when it fits on 1 page. Prevents viewport from resizing -> flickering
* and stuff moving between page loads
*/
overflow-y: scroll;
}
body {
/* So that toasts can be positioned relative to `body` (rather than `html`).
* This is useful because it wil then use the `body`'s width (i.e., accounting for the big fat margins).
*/
position: relative;
margin: 0 var(--width-body-margins);
min-height: 100vh;
border-color: var(--color-twitter-off-white-dark);
border-right-style: solid;
border-left-style: solid;
border-width: 1px;
font-family: "Titillium Web";
}
input, select {
font-family: inherit;
font-size: 1em;
padding: 0.2em 0.6em;
box-sizing: border-box;
border-radius: 0.5em;
}
input[type="submit"] {
background-color: var(--color-twitter-blue-light);
width: 10em;
border-radius: 1em;
font-size: 1em;
cursor: pointer;
}
a {
text-decoration: none;
color: inherit;
cursor: pointer;
}
ul {
list-style: none;
}
h1 {
margin: 0.5em 0;
text-align: center;
}
h3 {
margin: 0.5em 0;
}
/***************************************************************************************************
*
* Utility styles
* --------------
*
* Generic or reusable styles. Should use only class selectors. Should *not* actually be modules
* (anything application specific).
*
***************************************************************************************************/
.row {
display: flex;
flex-direction: row;
align-items: center;
}
.row--spread {
justify-content: space-between;
}
/* A list of items separated by interpuncts */
.inline-dotted-list {
margin: 0;
& > * {
display: inline;
}
& > *:after {
content: " ⋅";
}
& > *:last-child:after {
content: "";
}
}
.rounded-gray-outline {
outline-color: lightgray;
outline-style: solid;
outline-width: 1px;
overflow: hidden;
border-radius: 1.5em;
}
.circle-outline {
display: flex;
border-radius: 50%;
outline: 1px solid #777;
margin: 0 0.4em;
font-size: 0.8em;
padding: 0.2em;
box-sizing: border-box;
}
.button {
display: flex; /* Prevent <a class="button"><img></a> from having extra space at the bottom, looking weird*/
padding: 0.5em;
margin: 0.2em;
border-radius: 100em; /* any large amount, just don't use % because then it makes an ellipse */
cursor: pointer;
&:hover {
background-color: var(--color-twitter-blue-light);
}
&:active {
transform: translate(0.1em, 0.1em);
background-color: var(--color-twitter-blue);
}
&.button--danger {
background-color: var(--color-twitter-danger-red2);
&:hover {
background-color: var(--color-twitter-danger-red2-light);
}
&:active {
background-color: var(--color-twitter-danger-red2);
}
}
}
.labelled-icon {
display: flex;
flex-direction: row;
align-items: center;
& label {
padding: 0 0.3em;
white-space: nowrap;
cursor: unset; /* <label> sets cursor to "default" by default */
}
}
.svg-icon {
width: 1.5em;
height: auto;
}
.disappearing {
transition: opacity 2s ease;
opacity: 0;
}
/***************************************************************************************************
*
* Layout styles
* -------------
*
* Major page elements. Can use semantic HTML tag names and IDs. Class selectors are for modules.
*
***************************************************************************************************/
header {
/* Sticky to top of page */
position: fixed;
z-index: 2; /* Pin icon in a pinned tweet has z-index=1 */
/* Match layout width of `body` */
left: var(--width-body-margins);
right: var(--width-body-margins);
height: 4em;
padding: 0.5em 1em;
border: 1px solid var(--color-outline-gray);
box-sizing: border-box;
background-color: white;
}
main {
/* Space taken up by the header search bar */
padding-top: 4em;
}
#nav-sidebar {
display: flex;
flex-direction: column;
position: fixed;
transform: translate(-100%, 0);
font-size: 1.4em;
}
/**
* Layout for the Messages page
*/
.messages-page {
display: flex;
flex-direction: row;
/** Setup to allow the two panes to scroll independently **/
height: 100vh;
padding-top: 4em;
margin-top: -4em;
box-sizing: border-box;
.chat-list {
flex-basis: 0;
flex-grow: 4;
display: flex;
flex-direction: column;
overflow-y: scroll;
}
#chat-view {
flex-basis: 0;
flex-grow: 7;
border-left: 1px solid var(--color-outline-gray);
box-sizing: border-box;
display: flex;
flex-direction: column;
/* To position the participants list page */
position: relative;
.chat-messages {
flex-grow: 1;
overflow-y: auto;
padding: 0 0.5em;
}
}
}
/**
* Layout for the Login page
*/
.login-page {
width: 60%;
margin: 5% auto;
& hr {
margin: 3em 2em;
}
}
/***************************************************************************************************
*
* Module styles
* -------------
*
* Normal page elements. Should only use classes; no IDs or tag names.
*
***************************************************************************************************/
/******************************************************
* General modules
******************************************************/
/**
* Toast notification popup that gets sent on HTTP 500
*/
.toast {
border-radius: 1em;
padding: 1em;
text-align: center;
word-wrap: break-word;
margin: 1em;
width: 90%;
/* Default: use "success" toast */
background-color: #efe;
border: 1px solid green;
color: green;
&.toast--error {
color: red;
background-color: #fee;
border-color: red;
}
&.toast--warning {
color: hsl(50.59deg 75% 40%);
background-color: #ffe;
border-color: hsl(50.59deg 75% 40%);
}
}
.toasts {
position: fixed;
left: var(--width-body-margins);
top: 10em;
right: var(--width-body-margins);
display: flex;
flex-direction: column;
align-items: center;
}
/**
* HTMX spinner module
*/
.htmx-spinner {
/* Hidden by default, unless `.htmx-request` is active on parent component */
display: none;
/* Cover the parent element completely */
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 2; /* On top of the search bar, which is z-index of 1 */
font-size: 3em;
/* When `.htmx-request` is applied to the parent element, show the spinner */
.htmx-request > & {
display: revert;
}
.htmx-spinner__fullscreen-forcer {
/*
* This can optionally be stuck inside a `.htmx-spinner` to make its contents sticky to
* full-screen size. Child elements will be positioned according to this rather than to the
* `.htmx-spinner` element.
*/
position: fixed;
top: 0;
height: 100vh;
left: var(--width-body-margins);
right: var(--width-body-margins);
}
.htmx-spinner__background {
opacity: 0.3;
background-color: #7cc5f6;
width: 100%;
height: 100%;
}
.htmx-spinner__icon {
/* Put the icon in the middle of the HTMX overlay */
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
/* https://codepen.io/sosuke/pen/Pjoqqp */
filter: invert(54%) sepia(17%) saturate(4210%) hue-rotate(176deg) brightness(89%) contrast(98%);
}
}
/**
* Image carousel module
*/
.image-carousel {
border-radius: 2em;
border: 0.3em solid var(--color-twitter-blue);
box-shadow: 0 0 1em var(--color-twitter-blue);
outline: none;
overflow: visible;
padding: 0;
line-height: 0;
.image-carousel__padding {
padding: 1.4em;
}
&::backdrop {
background: hsla(204, 87%, 73%, 0.3); /* based on --color-twitter-blue-light */
}
.image-carousel__close-button {
position: absolute;
right: -1.3em;
top: -1.5em;
width: 1em;
line-height: 1em;
font-size: 2em;
justify-content: center;
border: 0.1em solid black;
}
.image-carousel__close-button:not(:hover):not(:active) {
background-color: var(--color-twitter-blue-extra-light);
}
.image-carousel__active-image {
max-height: 85vh;
max-width: 90vw;
}
}
/**
* Tabs module
*/
.tabs {
margin-top: 2px;
border-top: 1px solid var(--color-outline-gray);
border-bottom: 1px solid var(--color-outline-gray);
.tabs__tab {
flex-grow: 1;
text-align: center;
font-size: 1.1em;
font-weight: bold;
color: var(--color-twitter-text-gray);
padding: 0.8em;
&:hover {
color: var(--color-twitter-blue);
}
}
.tabs__tab--active {
color: var(--color-twitter-blue);
border-bottom: 0.2em solid var(--color-twitter-blue);
}
}
/**
* Clickable entities
*/
.entity {
color: var(--color-twitter-blue);
}
/**
* Text module. For both Tweets and DM messages
*/
.text {
display: block;
margin-bottom: 0.5em;
margin-top: 0;
overflow-wrap: anywhere;
cursor: text;
/* Prevent empty paragraphs from being collapsed into each other (i.e., `margin-bottom`s overlapping) */
padding-bottom: 0.1em;
&:last-child {
margin-bottom: 0;
}
}
/**
* Profile image module
*/
.profile-image {
line-height: 0;
.profile-image__image {
border-radius: 50%;
width: 3em;
height: 3em;
display: inline;
border: 0.1em solid var(--color-outline-gray);
}
}
/**
* Author info module
*/
.author-info {
display: flex;
align-items: center;
cursor: default;
.author-info__name-and-handle {
padding: 0 0.6em !important; /* !important to make the ".button .span" rule in the login button not overrule it */
}
.author-info__display-name {
font-weight: bold;
white-space: nowrap;
}
.author-info__handle {
color: var(--color-twitter-text-gray);
}
}
/**
* List (i.e.,, of users) module
*/
.users-list {
display: flex;
flex-direction: column;
border-color: var(--color-twitter-off-white-dark);
border-top-style: double;
border-width: 4px;
.author-info .profile-image__image {
width: 4em;
height: 4em;
}
.user {
border-color: var(--color-twitter-off-white-dark);
border-bottom-style: solid;
border-width: 1px;
padding: 1em;
}
.user p.bio {
margin: 0 5.3em;
font-size: 0.9em;
color: var(--color-twitter-text-gray);
}
}
/******************************************************
* Tweets
******************************************************/
/**
* Tweet module
*/
.tweet, .notification {
padding: 0 1.5em;
position: relative;
z-index: 0; /* Dunno why, but without it, hovering a tweet with a Poll hides the poll fill bars */
overflow: hidden; /* Otherwise HTMX spinner sticks over the rounded edges in a quoted tweet */
/**
* Set padding and borders around the tweet based on what type of tweet it is, and where it occurs
*/
.timeline &, .tweet__quoted-tweet &, .dm-message & {
/* Timeline tweets and quoted tweets, but not tweets in a thread */
/* TODO: what about DM tweet-previews? */
padding-top: 0.6em;
padding-bottom: 0.6em;
}
/**
* Create some extra space for the pin icon at the top of a pinned tweet
*/
.pinned-tweet & {
margin-top: -2em;
padding-top: 1.5em;
}
.timeline > &, .pinned-tweet & {
/* not for nested (i.e., quoted) tweets */
border-bottom: 1px solid var(--color-twitter-off-white-dark);
}
/**
* Mouse-over effects
*/
:not(.focused-tweet) > &:hover:not(:has(&:hover)) {
/* Add mouse-over background effect */
background-color: var(--color-twitter-off-white);
}
:not(.focused-tweet) > & {
/* Clickable tweets should make the cursor indicate an on-click action ("pointer" cursor) */
cursor: pointer;
}
.tweet__header-container {
display: flex;
align-items: center;
}
.tweet__vertical-container {
flex-grow: 1;
flex-shrink: 1;
}
/**
* Tweet content
*/
.tweet__embedded-image {
max-width: 95%;
max-height: 30em;
width: auto;
height: auto;
}
& video {
max-height: 25em;
max-width: 100%;
}
.tombstone {
outline: 1px solid var(--color-outline-gray);
background-color: var(--color-twitter-off-white);
padding: 0.5em 1em;
border-radius: 0.5em;
color: var(--color-twitter-text-gray);
}
.tweet__quoted-tweet {
margin: 1em 0;
}
}
/**
* Video module
*/
.video {
position: relative;
display: flex;
width: fit-content;
border-radius: 1.5em;
overflow: hidden;
.video__gif-controls {
position: absolute;
bottom: 1.2em;
left: 1em;
background-color: #999;
font-weight: bold;
padding: 0 0.2em 0 0.4em;
border-radius: 0.3em;
border: 1px solid #444;
.svg-icon {
font-size: 0.6em;
}
}
}
/**
* Retweet info module
*/
.retweet-info {
margin-left: 3.5em;
display: flex;
align-items: center;
opacity: 0.8;
cursor: default;
.retweet-info__retweeted-by-label {
margin: 0 0.2em 0 0.5em;
}
.svg-icon {
width: 1.2em; /* override default from .svg-icon of 1.5em */
opacity: 0.6; /* Probably not the right way to change the color from black to gray */
}
}
/**
* Reply-mentions module
*/
.reply-mentions {
display: flex;
align-items: center;
cursor: default;
flex-grow: 1;
justify-content: center;
flex-wrap: wrap;
.reply-mentions__list {
padding: 0 0.5em;
}
.reply-mentions__dm-message__replying-to-label {
color: var(--color-twitter-text-gray);
}
}
/**
* Embedded link module
*/
.embedded-link {
padding: 1.3em;
margin-top: 1em;
display: flex;
flex-direction: column;
background-color: var(--color-twitter-off-white);
.embedded-link__preview-image {
border-radius: 1em;
max-width: 100%;
height: auto; /* preserve aspect ratio */
}
.embedded-link__description {
color: var(--color-twitter-text-gray);
font-size: 0.8em;
margin: 0;
}
.embedded-link__domain {
margin-top: 0.2em;
}
.embedded-link__domain__contents {
margin-left: 0.3em;
}
}
/**
* Poll module
*/
.poll {
padding: 1em;
.poll__choice {
position: relative;
margin: 0.3em 0;
}
.poll__choice-info {
width: 100%;
line-height: 2em;
margin: 0 0.5em;
}
.poll__choice-label {
width: 50%;
}
.poll__choice-votes {
width: 50%;
}
.poll__choice-fill-bar {
position: absolute;
height: 100%;
z-index: -1;
background-color: var(--color-twitter-off-white-dark);
&.poll__choice-fill-bar--winner {
background-color: var(--color-twitter-blue-light);
}
}
.poll__metadata {
color: var(--color-twitter-text-gray);
margin: 0;
font-size: 0.9em;
}
}
/**
* Space module
*/
.space {
outline: 1px solid var(--color-space-purple-outline);
background-color: var(--color-space-purple);
border-radius: 1.5em;
padding: 1.5em;
.space__title {
padding-top: 0.5em;
}
.space__host__label {
color: var(--color-space-purple-outline);
}
.space__date {
color: var(--color-space-purple-outline);
font-size: 0.8em;
}
.space__info__list {
padding: 0;
}
.space__layout-spacer {
flex-grow: 1;
}
.space__participants-list {
padding: 0;
/* List items */
& > * {
padding: 0.5em 0;
display: inline-block;
width: 24%;
font-size: 0.9em;
line-height: 1.2em;
}
}
}
/**
* Posted-at module
*/
.posted-at {
flex-grow: 1;
min-width: 5em;
width: fit-content;
.posted-at__text {
float: right;
color: var(--color-twitter-text-gray);
font-size: 0.875em;
white-space: nowrap;
}
}
/**
* Interactions bar module
*/
.interactions {
display: flex;
flex-direction: row;
margin: 0.5em 0;
.interactions__stat {
flex-grow: 1;
display: flex;
& span {
line-height: 1.5em;
padding: 0 0.5em;
}
}
/* Empty <div> used to make the spacing more good */
.interactions__dummy {
flex-grow: 5;
}
.interactions__like-icon {
cursor: pointer;
&.liked, &:hover {
filter: invert(20%) sepia(97%) saturate(4383%) hue-rotate(321deg) brightness(101%) contrast(95%);
}
}
/* Make the buttons slightly smaller */
.button {
margin: 0;
font-size: 0.8em;
}
}
/******************************************************
* Conversation thread / tweet detail
******************************************************/
.tweet-detail {
& :first-child > .tweet {
/* The tweet at the top of a thread should have some top-padding */
padding-top: 1em;
}
}
/**
* Focused tweets
*/
.focused-tweet {
& > .tweet {
border-bottom: 1px solid var(--color-twitter-off-white-dark);
padding-bottom: 0.5em;
}
/* Make font bigger in focused tweets, unless it's in a quoted tweet */
.text {
font-size: 1.4em;
}
.tweet__quoted-tweet .text {
font-size: unset;
}
}
.reply-chain > :last-child > .tweet {
/* Last tweet in a reply chain should have bottom-padding */
padding-bottom: 1em;
border-bottom: 1px solid var(--color-twitter-off-white-dark);
}
/**
* Threaded conversation string (visual thread indicator) module
*/
.string-box {
width: 3em;
margin-right: 0.5em;
flex-grow: 0;
flex-shrink: 0;
/* Make the .string take up 100% of vertical space */
flex-direction: column;
align-self: stretch;
/* Only show it in parent threads and reply chains */
display: none;
.thread-parent-tweet &, .reply-chain & {
/* Not if it's in a quoted tweet */
&:not(.tweet__quoted-tweet &) {
display: flex; /* Show it */
}
}
.string {
width: 2px;
flex-grow: 1;
margin: auto;
background-color: var(--color-twitter-off-white-dark);
/* All parent tweets, and all but the last reply */
display: none;
.thread-parent-tweet &, .reply-chain > :not(:last-child) & {
display: revert;
}
}
}
/******************************************************
* Timeline
******************************************************/
/**
* Show more button and EOF indicator module
*/
.show-more {
text-align: center;
font-size: 1.2em;
padding: 1em 0;
.show-more__eof-label {
color: var(--color-twitter-text-gray);
}
.show-more__button {
padding: 0em 0.8em;
display: inline-block;
border: 2px solid var(--color-twitter-blue);
color: var(--color-twitter-text-gray);
font-size: 0.9em;
&:not(:hover):not(:active) {
/* TODO: maybe this should be a reusable button style */
background-color: var(--color-twitter-blue-extra-light);
}
}
}
/******************************************************
* Notifications
******************************************************/
.notifications-header {
border-bottom: 1px solid var(--color-outline-gray);
}
/**
* Notification module
*/
.notification {
.notification__users {
font-size: 0.8em; /* Make the profile images smaller */
}
}
/******************************************************
* Navigation and base page
******************************************************/
/**
* Nav-sidebar module
*/
.nav-sidebar {
.nav-sidebar__buttons {
display: flex;
flex-direction: column;
align-items: flex-start;
padding: 0 2em;
}
/* Enable positioning the notifications indicator relative to this */
.labelled-icon {
position: relative;
}
.nav-sidebar__notifications-count {
position: absolute;
left: 0.3em;
top: 0.3em;
background-color: var(--color-twitter-blue);
min-width: 1em;
line-height: 1em;
/* height: 1.2em; */
border-radius: 1em;
font-size: 0.7em;
color: white;
text-align: center;
padding: 0.2em;
}
#logged-in-user-info {
font-size: 0.8em;
margin-top: 1em;
display: flex;
flex-direction: column;
align-items: center;
}
.button .author-info {
pointer-events: none;
}
}
/**
* Search bar module
*/
.search-bar {
.search-bar__back-button {
flex-grow: 0;
border-radius: 50%;
border: 2px solid black;
width: 2em;
position: relative;
height: 2em;
box-sizing: border-box;
cursor: pointer;
& img {
color: rgb(239, 243, 244);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
.search-bar__form {
margin-left: 1em;
flex-grow: 1;
display: flex;
}
.search-bar__input {
flex-grow: 1;
}
}
/******************************************************
* User feeds
******************************************************/
/**
* User-feed header module
*/
.user-header {
border-bottom: 1px solid var(--color-outline-gray);
.user-header__profile-banner-image {
width: 100%;
}
.user-header__info-container {
padding: 2em;
}
.user-header__bio {
margin: 1.5em 0;
}
/* Special settings for profile images in user headers */
.author-info {
font-size: 1.3em;
padding: 1em;
}
.profile-image__image {
width: 8em;
height: 8em;
}
}
/**
* Followers + followees module
*/
.followers-followees {
margin-top: 1em;
gap: 4em;
.followers-followees__count {
font-weight: bold;
}
& label {
color: var(--color-twitter-text-gray);
cursor: unset;
}
.spacer {
flex-grow: 1;
}
}
/**
* Pinned tweet mini-module
*/
.pinned-tweet__pin-container {
margin: 0.5em 0em 0em 3em;
z-index: 1; /* Otherwise it disappears behind the tweet background color on mouse-over */
position: relative; /* z-index is ignored if `position` is "static" */
width: fit-content;
.pinned-tweet__pin-icon {
filter: invert(43%) saturate(30%);
width: 1em;
height: auto;
}
}
/******************************************************
* Search page
******************************************************/
/**
* Search page sort-order module
*/
.sort-order {
padding: 1em 1em 1em 3em;
border-bottom: 1px solid var(--color-outline-gray);
.sort-order__label {
font-weight: bold;
}
.sort-order__dropdown {
text-transform: capitalize;
margin: 0 1em;
}
}
/******************************************************
* Login page
******************************************************/
/**
* Login form module
*/
.login-form {
.login-form__field-container {
padding: 0.5em 0;
}
.login-form__submit-container {
text-align: right;
}
.login-form__error-label {
color: #C0392B;
font-weight: bold;
& + input {
border-color: #C0392B;
border-width: 2px;
}
}
.login-form__input {
width: 100%;
border-radius: 0.5em;
padding: 0.5em 0.6em;
flex-grow:;
}
& input[type="submit"] {
padding: 1em;
}
}
.choose-session {
margin-top: 2em;
.choose-session__form-contents {
padding-top: 1em;
gap: 3em;
}
.choose-session__dropdown {
flex-grow: 1;
}
}
/******************************************************
* Lists pages
******************************************************/
.list-of-lists {
border-color: var(--color-twitter-off-white-dark);
border-top-style: double;
border-width: 4px;
}
/**
* List preview module
*/
.list-preview {
padding: 0.5em 1em;
border-color: var(--color-twitter-off-white-dark);
border-bottom-style: solid;
border-width: 1px;
.list-preview__info-container{
display: flex;
align-items: center;
font-size: 1.5em;
cursor: pointer;
}
.list-preview__num-users {
margin-left: 1em;
color: var(--color-twitter-text-gray);
}
.list-preview__first-N-profile-images {
display: flex;
align-items: flex-end;
margin-left: 1.5em;
.profile-image {
/* Make profile images in the list preview stack up on each other */
margin-right: -1.2em;
}
.ellipsis {
/* Counteract the above; the ellipsis should be spaced normally */
margin-left: 1.5em;
}
}
}
/******************************************************
* Bookmarks pages
******************************************************/
.bookmarks-feed-header {
border-bottom: 1px solid var(--color-outline-gray);
}
.add-users-container {
padding: 1em;
text-align: center;
}
/******************************************************
* DMs / Messages
******************************************************/
/**
* Chat list entry module
*/
.chat-list-entry {
border-bottom: 1px solid var(--color-outline-gray);
padding: 1em 1em 0 1em;
box-sizing: border-box;
cursor: pointer;
&.chat-list-entry--active-chat {
color: var(--color-twitter-blue);
border-left: 0.2em solid var(--color-twitter-blue);
background-color: var(--color-twitter-off-white);
.profile-image__image {
box-shadow: 0 0 1em 0em var(--color-twitter-blue);
}
}
.chat-list-entry__header {
display: flex;
align-items: center;
justify-content: space-between;
}
.chat-list-entry__preview-and-unread-container {
justify-content: space-between;
}
.chat-list-entry__message-preview {
font-size: 0.9em;
color: var(--color-twitter-text-gray);
padding: 0 1em;
border-left: 1px solid var(--color-outline-gray);
.chat-list-entry--unread & {
font-weight: bold;
}
}
.chat-list-entry__unread-indicator {
display: none;
background-color: var(--color-twitter-blue);
height: 0.5em;
width: 0.5em;
border-radius: 50%;
flex: auto 0 0; /* Otherwise it gets squished if the message preview is long */
.chat-list-entry--unread & {
display: revert;
}
}
.chat-list-entry__preview-no-text {
font-style: italic;
}
.posted-at__text {
margin: 0;
}
}
/**
* Groupchat info module (like Author Info but for group chats)
*/
.groupchat-info {
.groupchat-info__display-name {
padding: 0.6em;
font-style: italic;
font-weight: bold; /* TODO: redundancy check `.author-info__display-name` */
white-space: nowrap;
cursor: default; /* TODO: redundancy check `.author-info` */
}
}
.chat-header {
border-bottom: 1px solid var(--color-outline-gray);
padding: 0.5em;
display: flex;
justify-content: space-around;
background-color: var(--color-twitter-off-white);
}
.groupchat-participants-list {
position: absolute;
background-color: white;
top: 4.2em; /* TODO: wtf is this number */
left: 0;
right: 0;
bottom: 0;
overflow-y: scroll;
display: none;
&.unhidden {
display: revert;
}
}
/**
* DM message module
*/
.dm-message {
display: flex;
flex-direction: column;
margin: 1em 0;
/**
* Compact mode:
* margin: 0.5em 0;
*/
/* When a replying-to box is clicked, it scrolls that message into view and highlights it for a second */
transition: background-color 2s ease;
&.highlighted {
background-color: var(--color-twitter-off-white-dark);
transition: background-color 0.5s ease;
}
.dm-message__row {
align-items: stretch;
.our-message & {
flex-direction: row-reverse;
}
.dm-message__button-container {
display: flex;
flex-direction: column;
justify-content: center;
}
}
.dm-message__sender-profile-img {
display: flex;
align-items: flex-end;
}
.dm-message__sender-profile-img a {
line-height: 0; /* TODO: This is redundant with ".author-info a" rule above */
}
.dm-message__contents {
display: flex;
flex-direction: column;
align-items: flex-start;
max-width: 80%;
margin: 0 0.5em;
.our-message & {
align-items: flex-end;
}
}
.dm-message__tweet-preview {
border-radius: 1em;
overflow: hidden; /* TODO: redundancy check-- why is this necessary? check .rounded-gray-outline */
border: 1px solid var(--color-outline-gray);
max-width: 100%;
}
.dm-message__embedded-image, .dm-message__embedded-video {
max-width: 100%;
height: auto; /* preserve aspect ratio */
cursor: pointer;
}
.dm-message__text-content {
display: inline-block;
padding: 1em;
background-color: #ddd;
border-radius: 1em;
margin: 0;
/**
* Compact mode:
*
display: inline-block;
padding: 0.5em 1em;
background-color: #ddd;
border-radius: 1em;
margin: auto;
min-height: 2em;
display: flex;
flex-direction: column;
justify-content: space-around;
*/
.our-message & {
background-color: var(--color-twitter-blue-light);
}
}
.sent-at {
flex-grow: 1;
min-width: 5em;
width: fit-content;
.sent-at__text {
float: right;
color: var(--color-twitter-text-gray);
font-size: 0.875em;
white-space: nowrap;
}
}
.sent-at__text {
margin: 0 4.5em;
}
.dm-message__reactions {
display: flex;
padding: 0 3.5em;
cursor: default;
.our-message & {
flex-direction: row-reverse;
}
}
.dm-message__reacc {
width: 1.5em;
height: 1.5em;
text-align: center;
&.dm-message__reacc--ours {
border-radius: 50%;
text-shadow: 0 0 3px black;
outline: 1px solid var(--color-twitter-blue);
background-color: var(--color-twitter-blue-extra-light);
}
}
&.our-message {
align-items: flex-end;
}
}
.dm-replying-to {
background-color: #f0f0f0f0;
border-radius: 1em 1em 1em 0em;
padding: 0.5em 1.2em 2em 1.2em;
margin: 0 0 -2em 0.2em;
font-size: 0.9em;
.our-message & {
border-radius: 1em 1em 0em 1em;
margin: 0 0.2em -2em;
}
.dm-replying-to__label {
font-size: 0.8em;
color: var(--color-twitter-text-gray);
& img.svg-icon {
width: 1em;
}
}
.dm-replying-to__preview-text, .dm-replying-to__username {
cursor: pointer;
}
}
/**
* Messages page DM composer module
*/
.dm-composer {
& form {
display: flex;
gap: 1em;
padding: 0.8em 1em;
align-items: center;
border-top: 1px solid var(--color-outline-gray);
background-color: white;
}
[role="textbox"] {
flex-grow: 1;
border: 1px solid #ccc;
font-family: inherit;
font-size: inherit;
padding: 1px 6px;
max-height: 10em;
min-height: 3em;
overflow-wrap: anywhere;
overflow-y: auto; /* scrollbar only if needed */
border: 2px solid var(--color-outline-gray);
border-radius: 0.5em;
}
& input[type="submit"] {
flex-shrink: 0;
flex-grow: 0;
height: 3em;
width: 6em;
}
.dm-composer__replying-to-container {
display: none;
&.unhidden {
display: revert;
}
/* This is gross; it's to counter the left margin on `dm-replying-to`, which is meant for the one on DMs specifically */
margin-left: -0.2em;
.dm-composer__replying-to {
position: absolute;
top: 0;
transform: translate(0, -100%);
width: 100%;
}
}
}