fix(frontend): no_footer scrollbar regression introduced in v1.16.0 (#2076)

* fix(frontend): no_footer scrollbar regression introduced in v1.16.0

Two unrelated changes in v1.16.0 combined to surface a scrollbar in
no_footer=true mode:

1. c26f45e5 removed the deprecated `scrolling="no"` iframe attribute
   on the grounds that "overflow is already hidden via CSS". That CSS
   (`overflow: hidden` in createIframe styles) is on the iframe ELEMENT
   in the parent page; it has no effect on the iframe DOCUMENT's own
   scrollbars. The spec-correct replacement is `overflow: hidden` on
   the iframe document's body — added here to global.css.

2. The negative `margin-bottom: -24px` on `.thread:last-child` was a
   trick to tighten the gap to the footer (combined with the footer's
   `margin-top: 48px` it collapsed to a 24px net gap). With no_footer
   the negative margin had no positive-margin sibling to collapse
   against and instead propagated up through .root, leaving body
   ~24px shorter than the visual content. The iframe height calc
   (`body.offsetHeight + 12`) then sized the iframe below the visible
   bottom of the last thread → scrollbar.

   Replace the negative-margin trick with a straight `margin-top: 24px`
   on `.copyright`. Same 24px visual gap when the footer is shown, no
   propagation when it isn't. The mix={styles.thread} on Thread becomes
   a dead reference and is dropped.

Closes #2073

* fix(frontend): drop dead Thread.mix prop after root.tsx removed its only caller

Both Copilot and umputun flagged this in PR review: after the parent
commit on this branch dropped `mix={styles.thread}` from root.tsx, the
`mix?: string` prop and the corresponding entry in the clsx() call in
thread.tsx are dead code — no caller passes it (the recursive Thread
render in thread.tsx:82 never did either). Remove the prop, the
destructure, and the clsx entry.
This commit is contained in:
Dmitry Verkhoturov
2026-05-28 13:02:25 -05:00
committed by GitHub
parent 39408dffe8
commit 198efddb54
4 changed files with 11 additions and 14 deletions
@@ -31,18 +31,12 @@
margin: 0 auto;
}
.thread {
&:last-child {
margin-bottom: -24px;
}
}
.threads {
margin-top: 4px;
}
.copyright {
margin: 48px 0 0;
margin: 24px 0 0;
font-size: 12px;
text-align: right;
}
@@ -301,9 +301,7 @@ function Comments({ isLoading, topComments, commentsShown, showMore }: CommentsP
) : (
<>
{topComments.length > 0 &&
renderComments.map((id) => (
<Thread key={`thread-${id}`} id={id} mix={styles.thread} level={0} getPreview={getPreview} />
))}
renderComments.map((id) => <Thread key={`thread-${id}`} id={id} level={0} getPreview={getPreview} />)}
{isShowMoreButtonVisible && (
<Button className={styles.moreComments} onClick={showMore}>
<FormattedMessage id="root.show-more" defaultMessage="Show more" />
@@ -19,7 +19,6 @@ interface Props {
id: CommentInterface['id'];
childs?: CommentInterface['id'][];
level: number;
mix?: string;
getPreview(text: string): Promise<string>;
}
@@ -34,7 +33,7 @@ const commentSelector = (id: string) => (state: StoreState) => {
return { comment, childs, collapsed, theme };
};
export const Thread: FunctionComponent<Props> = ({ id, level, mix, getPreview }) => {
export const Thread: FunctionComponent<Props> = ({ id, level, getPreview }) => {
const dispatch = useAppDispatch();
const intl = useIntl();
const { collapsed, comment, childs, theme } = useAppSelector(commentSelector(id), shallowEqual);
@@ -53,8 +52,7 @@ export const Thread: FunctionComponent<Props> = ({ id, level, mix, getPreview })
styles.root,
indented && styles.indented,
level === 6 && styles.level6,
theme === 'dark' && styles.themeDark,
mix
theme === 'dark' && styles.themeDark
)}
role={['listitem'].concat(!collapsed && !!repliesCount ? 'list' : []).join(' ')}
aria-expanded={!collapsed}
@@ -8,6 +8,13 @@ body {
color: rgb(var(--primary-text-color));
background: transparent;
box-sizing: border-box;
/* parent resizes the iframe element to fit content via postMessage, so the
iframe document never needs its own scrollbar. spec-correct replacement
for the deprecated `scrolling="no"` attribute removed in c26f45e5 — the
`overflow:hidden` on the iframe ELEMENT doesn't control the iframe
DOCUMENT's scrollbars, that has to be set inside the document. */
overflow: hidden;
}
input,