diff --git a/app/javascript/mastodon/components/learn_more_link.tsx b/app/javascript/mastodon/components/learn_more_link.tsx
new file mode 100644
index 000000000..b5337794c
--- /dev/null
+++ b/app/javascript/mastodon/components/learn_more_link.tsx
@@ -0,0 +1,63 @@
+import { useState, useRef, useCallback, useId } from 'react';
+
+import { FormattedMessage } from 'react-intl';
+
+import Overlay from 'react-overlays/Overlay';
+
+export const LearnMoreLink: React.FC<{ children: React.ReactNode }> = ({
+ children,
+}) => {
+ const accessibilityId = useId();
+ const [open, setOpen] = useState(false);
+ const triggerRef = useRef(null);
+
+ const handleClick = useCallback(() => {
+ setOpen(!open);
+ }, [open, setOpen]);
+
+ return (
+ <>
+
+
+
+ {({ props }) => (
+
+
{children}
+
+
+
+
+
+ )}
+
+ >
+ );
+};
diff --git a/app/javascript/mastodon/components/status_content.jsx b/app/javascript/mastodon/components/status_content.jsx
index 5f0f7079a..38d24921c 100644
--- a/app/javascript/mastodon/components/status_content.jsx
+++ b/app/javascript/mastodon/components/status_content.jsx
@@ -138,6 +138,16 @@ class StatusContent extends PureComponent {
onCollapsedToggle(collapsed);
}
+
+ // Remove quote fallback link from the DOM so it doesn't
+ // mess with paragraph margins
+ if (!!status.get('quote')) {
+ const inlineQuote = node.querySelector('.quote-inline');
+
+ if (inlineQuote) {
+ inlineQuote.remove();
+ }
+ }
}
handleMouseEnter = ({ currentTarget }) => {
diff --git a/app/javascript/mastodon/components/status_quoted.tsx b/app/javascript/mastodon/components/status_quoted.tsx
index d3d8b58c3..8d43ea181 100644
--- a/app/javascript/mastodon/components/status_quoted.tsx
+++ b/app/javascript/mastodon/components/status_quoted.tsx
@@ -3,19 +3,15 @@ import { useEffect, useMemo } from 'react';
import { FormattedMessage } from 'react-intl';
import classNames from 'classnames';
-import { Link } from 'react-router-dom';
import type { Map as ImmutableMap } from 'immutable';
-import ArticleIcon from '@/material-icons/400-24px/article.svg?react';
-import ChevronRightIcon from '@/material-icons/400-24px/chevron_right.svg?react';
-import { Icon } from 'mastodon/components/icon';
+import { LearnMoreLink } from 'mastodon/components/learn_more_link';
import StatusContainer from 'mastodon/containers/status_container';
import type { Status } from 'mastodon/models/status';
import type { RootState } from 'mastodon/store';
import { useAppDispatch, useAppSelector } from 'mastodon/store';
-import QuoteIcon from '../../images/quote.svg?react';
import { fetchStatus } from '../actions/statuses';
import { makeGetStatus } from '../selectors';
@@ -31,7 +27,6 @@ const QuoteWrapper: React.FC<{
'status__quote--error': isError,
})}
>
-
{children}
);
@@ -45,27 +40,20 @@ const NestedQuoteLink: React.FC<{
accountId ? state.accounts.get(accountId) : undefined,
);
- const quoteAuthorName = account?.display_name_html;
+ const quoteAuthorName = account?.acct;
if (!quoteAuthorName) {
return null;
}
- const quoteAuthorElement = (
-
- );
- const quoteUrl = `/@${account.get('acct')}/${status.get('id') as string}`;
-
return (
-
+
-
-
-
+
);
};
@@ -112,39 +100,42 @@ export const QuotedStatus: React.FC<{
defaultMessage='Hidden due to one of your filters'
/>
);
- } else if (quoteState === 'deleted') {
- quoteError = (
-
- );
- } else if (quoteState === 'unauthorized') {
- quoteError = (
-
- );
} else if (quoteState === 'pending') {
quoteError = (
-
+ <>
+
+
+
+
+
+
+
+
+
+
+ >
);
- } else if (quoteState === 'rejected' || quoteState === 'revoked') {
+ } else if (
+ !status ||
+ !quotedStatusId ||
+ quoteState === 'deleted' ||
+ quoteState === 'rejected' ||
+ quoteState === 'revoked' ||
+ quoteState === 'unauthorized'
+ ) {
quoteError = (
- );
- } else if (!status || !quotedStatusId) {
- quoteError = (
-
);
}
@@ -168,7 +159,7 @@ export const QuotedStatus: React.FC<{
isQuotedPost
id={quotedStatusId}
contextType={contextType}
- avatarSize={40}
+ avatarSize={32}
>
{canRenderChildQuote && (
[data-popper-placement] {
}
}
-.status--has-quote .quote-inline {
- display: none;
-}
-
.status {
padding: 16px;
min-height: 54px;
@@ -1470,10 +1466,6 @@ body > [data-popper-placement] {
margin-top: 16px;
}
- &--is-quote {
- border: none;
- }
-
&--in-thread {
--thread-margin: calc(46px + 8px);
@@ -1860,79 +1852,99 @@ body > [data-popper-placement] {
// --status-gutter-width is currently only set inside of
// .notification-ungrouped, so everywhere else this will fall back
// to the pixel values
- --quote-margin: var(--status-gutter-width, 36px);
+ --quote-margin: var(--status-gutter-width);
position: relative;
margin-block-start: 16px;
margin-inline-start: calc(var(--quote-margin) + var(--thread-margin, 0px));
- border-radius: 8px;
+ border-radius: 12px;
color: var(--nested-card-text);
- background: var(--nested-card-background);
- border: var(--nested-card-border);
-
- @container (width > 460px) {
- --quote-margin: var(--status-gutter-width, 56px);
- }
+ border: 1px solid var(--surface-border-color);
}
.status__quote--error {
+ box-sizing: border-box;
display: flex;
align-items: center;
+ justify-content: space-between;
gap: 8px;
padding: 12px;
- font-size: 15px;
+ font-size: 14px;
+ line-height: 20px;
+ letter-spacing: 0.25px;
+ min-height: 56px;
+
+ .link-button {
+ font-size: inherit;
+ line-height: inherit;
+ letter-spacing: inherit;
+ }
}
.status__quote-author-button {
position: relative;
overflow: hidden;
- display: inline-flex;
- width: auto;
- margin-block-start: 10px;
- padding: 5px 12px;
+ display: flex;
+ margin-top: 8px;
+ padding: 8px 12px;
align-items: center;
- gap: 6px;
font-family: inherit;
font-size: 14px;
- font-weight: 700;
- line-height: normal;
- letter-spacing: 0;
- text-decoration: none;
- color: $highlight-text-color;
- background: var(--nested-card-background);
- border: var(--nested-card-border);
- border-radius: 4px;
-
- &:active,
- &:focus,
- &:hover {
- border-color: lighten($highlight-text-color, 4%);
- color: lighten($highlight-text-color, 4%);
- }
-
- &:focus-visible {
- outline: $ui-button-icon-focus-outline;
- }
+ font-weight: 400;
+ line-height: 20px;
+ letter-spacing: 0.25px;
+ color: $darker-text-color;
+ background: var(--surface-variant-background-color);
+ border-radius: 8px;
+ cursor: default;
}
-.status__quote-icon {
- position: absolute;
- inset-block-start: 18px;
- inset-inline-start: -40px;
- display: block;
- width: 26px;
- height: 26px;
- padding: 5px;
- color: #6a49ba;
- z-index: 10;
+.status--is-quote {
+ border: none;
+ padding: 12px;
- .status__quote--error & {
- inset-block-start: 50%;
- transform: translateY(-50%);
+ .status__info {
+ padding-bottom: 8px;
}
- @container (width > 460px) {
- inset-inline-start: -50px;
+ .display-name,
+ .status__relative-time {
+ font-size: 14px;
+ line-height: 20px;
+ letter-spacing: 0.1px;
+ }
+
+ .display-name__account {
+ font-size: 12px;
+ line-height: 16px;
+ letter-spacing: 0.5px;
+ }
+
+ .status__content {
+ display: -webkit-box;
+ font-size: 14px;
+ letter-spacing: 0.25px;
+ line-height: 20px;
+ -webkit-line-clamp: 4;
+ line-clamp: 4;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+
+ p {
+ margin-bottom: 20px;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+ }
+
+ .media-gallery,
+ .video-player,
+ .audio-player,
+ .attachment-list,
+ .poll {
+ margin-top: 8px;
}
}
@@ -2152,6 +2164,27 @@ body > [data-popper-placement] {
}
}
+.learn-more__popout {
+ gap: 8px;
+
+ &__content {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+ }
+
+ h6 {
+ font-size: inherit;
+ font-weight: 500;
+ line-height: inherit;
+ letter-spacing: 0.1px;
+ }
+
+ .link-button {
+ font-weight: 500;
+ }
+}
+
.account__wrapper {
display: flex;
gap: 10px;
diff --git a/app/javascript/styles/mastodon/css_variables.scss b/app/javascript/styles/mastodon/css_variables.scss
index 431cdd7a8..16ed033b9 100644
--- a/app/javascript/styles/mastodon/css_variables.scss
+++ b/app/javascript/styles/mastodon/css_variables.scss
@@ -16,6 +16,7 @@
--surface-background-color: #{darken($ui-base-color, 4%)};
--surface-variant-background-color: #{$ui-base-color};
--surface-variant-active-background-color: #{lighten($ui-base-color, 4%)};
+ --surface-border-color: #{lighten($ui-base-color, 8%)};
--on-surface-color: #{color.adjust($ui-base-color, $alpha: -0.5)};
--avatar-border-radius: 8px;
--media-outline-color: #{rgba(#fcf8ff, 0.15)};