From 9b63f47629e09af01325100e3fdd89c3fa3cbed1 Mon Sep 17 00:00:00 2001 From: Echo Date: Tue, 15 Sep 2026 14:18:41 +0000 Subject: [PATCH] Status redesign: View Full Post button (#40516) --- .../mastodon/components/status/action_bar.tsx | 4 +- .../mastodon/components/status/content.tsx | 69 +++++++++++-------- .../components/status/styles.module.scss | 36 +++------- app/javascript/mastodon/locales/en.json | 1 + 4 files changed, 56 insertions(+), 54 deletions(-) diff --git a/app/javascript/mastodon/components/status/action_bar.tsx b/app/javascript/mastodon/components/status/action_bar.tsx index 05cd8a01ee9..78e9ea08ae4 100644 --- a/app/javascript/mastodon/components/status/action_bar.tsx +++ b/app/javascript/mastodon/components/status/action_bar.tsx @@ -6,7 +6,7 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { ArrowsClockwiseIcon, BookmarkSimpleIcon, - ChatCircleTextIcon, + ChatCircleIcon, DotsThreeIcon, HeartIcon, QuotesIcon, @@ -218,7 +218,7 @@ export const StatusActionBar: React.FC = ({ clipPadding variant='ghost' title={intl.formatMessage(messages.replyAll)} - leadingIcon={ChatCircleTextIcon} + leadingIcon={ChatCircleIcon} onClick={handleReplyClick} > {withCounters && status.replies_count} diff --git a/app/javascript/mastodon/components/status/content.tsx b/app/javascript/mastodon/components/status/content.tsx index 3e4bdb8abb5..0a1038e1823 100644 --- a/app/javascript/mastodon/components/status/content.tsx +++ b/app/javascript/mastodon/components/status/content.tsx @@ -18,7 +18,7 @@ import { EmojiHTML } from '../emoji/html'; import { useHandlersForStatus } from './hooks'; import classes from './styles.module.scss'; -const MAX_HEIGHT = 706; // 22px * 32 (+ 2px padding at the top) +const MAX_LINES = 35; export const StatusContent: React.FC< { @@ -46,8 +46,12 @@ export const StatusContent: React.FC< return; } + const { lineHeight } = getComputedStyle(node); + const lineHeightPx = parseFloat(lineHeight); + const maxHeight = lineHeightPx * MAX_LINES; + setCollapsed( - (node.clientHeight > MAX_HEIGHT || + (node.clientHeight > maxHeight || node.scrollWidth > node.clientWidth) && !status.spoiler_text, ); @@ -61,41 +65,52 @@ export const StatusContent: React.FC< const isCollapsed = !!onReadMore && collapsible && collapsed; - return ( -
- + const style = { + '--max-height': `${MAX_LINES}lh`, + ...props.style, + } as React.CSSProperties; - {children} + return ( + <> +
+ + + {children} +
{isCollapsed && ( )} -
+ ); }; diff --git a/app/javascript/mastodon/components/status/styles.module.scss b/app/javascript/mastodon/components/status/styles.module.scss index e630fefc46a..99d7f44bcea 100644 --- a/app/javascript/mastodon/components/status/styles.module.scss +++ b/app/javascript/mastodon/components/status/styles.module.scss @@ -40,7 +40,8 @@ .footer, .root :global(.status__prepend), .root :global(.content-warning), -.translate { +.translate, +.contentReadMore { grid-column: var(--content-col); } @@ -57,28 +58,20 @@ } .content { + --mask-height: 80px; + display: flex; flex-direction: column; gap: var(--space-xs); &.collapsed { - position: relative; - max-height: 15lh; + max-height: var(--max-height); // Set via JS. overflow-y: clip; - - &::after { - content: ''; - position: absolute; - inset-inline: 0; - inset-block-end: 0; - height: calc(var(--space-4xl) * 2); - background: linear-gradient( - to bottom, - transparent, - var(--color-bg-blend) - ); - pointer-events: none; - } + mask-image: linear-gradient( + to bottom, + black calc(100% - var(--mask-height)), + transparent + ); } } @@ -109,14 +102,7 @@ } .contentReadMore { - position: absolute; - inset-block-end: 0; - inset-inline-start: 0; - z-index: 1; -} - -.footer { - overflow: hidden; + width: max-content; } .hashtagsWrapper, diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 3b6d153596a..5fcf6536da2 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -1456,6 +1456,7 @@ "status.uncached_media_warning": "Preview not available", "status.unmute_conversation": "Unmute conversation", "status.unpin": "Unpin from profile", + "status.view_post": "View full post", "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.", "subscribed_languages.save": "Save changes", "subscribed_languages.target": "Change subscribed languages for {target}",