From 6aec81cab04f0c90911cffd8f768830981f5a13f Mon Sep 17 00:00:00 2001 From: Echo Date: Tue, 11 Aug 2026 14:08:00 +0200 Subject: [PATCH] Refactors column component (#40112) --- app/javascript/mastodon/components/column.tsx | 60 -------------- .../back_button.tsx} | 4 +- .../mastodon/components/column/context.ts | 12 +++ .../{column_header.tsx => column/header.tsx} | 25 +++--- .../mastodon/components/column/index.tsx | 80 +++++++++++++++++++ .../search_header.tsx} | 0 .../mastodon/features/about/index.jsx | 2 +- .../account_edit/components/column.tsx | 2 +- .../features/account_featured/index.tsx | 4 +- .../features/account_gallery/index.tsx | 4 +- .../features/account_timeline/index.tsx | 2 +- .../mastodon/features/blocks/index.jsx | 15 ++-- .../features/bookmarked_statuses/index.tsx | 15 +--- .../features/collections/detail/index.tsx | 4 +- .../features/collections/editor/index.tsx | 4 +- .../mastodon/features/collections/index.tsx | 4 +- .../features/community_timeline/index.jsx | 16 +--- .../mastodon/features/compose/index.tsx | 4 +- .../features/direct_timeline/index.jsx | 15 ++-- .../mastodon/features/directory/index.tsx | 16 +--- .../mastodon/features/domain_blocks/index.tsx | 15 +--- .../mastodon/features/explore/index.tsx | 15 +--- .../features/favourited_statuses/index.tsx | 15 +--- .../mastodon/features/favourites/index.jsx | 4 +- .../mastodon/features/firehose/index.jsx | 13 ++- .../features/follow_requests/index.jsx | 6 +- .../mastodon/features/followed_tags/index.tsx | 15 +--- .../features/followers/components/list.tsx | 2 +- .../features/getting_started/index.tsx | 2 +- .../features/hashtag_timeline/index.jsx | 16 +--- .../mastodon/features/home_timeline/index.jsx | 16 +--- .../features/keyboard_shortcuts/index.jsx | 4 +- .../mastodon/features/link_timeline/index.tsx | 16 ++-- .../mastodon/features/list_timeline/index.jsx | 16 +--- .../mastodon/features/lists/index.tsx | 4 +- .../mastodon/features/lists/members.tsx | 6 +- .../mastodon/features/lists/new.tsx | 4 +- .../mastodon/features/mutes/index.jsx | 14 ++-- .../notifications_permission_banner.tsx | 2 +- .../features/notifications/request.jsx | 15 ++-- .../features/notifications/requests.jsx | 15 ++-- .../features/notifications_v2/index.tsx | 28 +++---- .../mastodon/features/onboarding/follows.tsx | 6 +- .../mastodon/features/onboarding/profile.tsx | 4 +- .../features/pinned_statuses/index.jsx | 20 ++--- .../features/privacy_policy/index.tsx | 2 +- .../features/public_timeline/index.jsx | 16 +--- .../mastodon/features/quotes/index.tsx | 19 +++-- .../mastodon/features/reblogs/index.jsx | 15 ++-- .../mastodon/features/search/index.tsx | 15 +--- .../mastodon/features/status/index.jsx | 4 +- .../features/terms_of_service/index.tsx | 2 +- .../ui/components/__tests__/column-test.jsx | 33 -------- .../components/bundle_column_error/index.tsx | 2 +- .../features/ui/components/column.jsx | 77 ------------------ .../features/ui/components/column_loading.tsx | 6 +- .../features/ui/components/columns_area.tsx | 6 +- app/javascript/mastodon/scroll.ts | 8 +- 58 files changed, 284 insertions(+), 482 deletions(-) delete mode 100644 app/javascript/mastodon/components/column.tsx rename app/javascript/mastodon/components/{column_back_button.tsx => column/back_button.tsx} (91%) create mode 100644 app/javascript/mastodon/components/column/context.ts rename app/javascript/mastodon/components/{column_header.tsx => column/header.tsx} (93%) create mode 100644 app/javascript/mastodon/components/column/index.tsx rename app/javascript/mastodon/components/{column_search_header.tsx => column/search_header.tsx} (100%) delete mode 100644 app/javascript/mastodon/features/ui/components/__tests__/column-test.jsx delete mode 100644 app/javascript/mastodon/features/ui/components/column.jsx diff --git a/app/javascript/mastodon/components/column.tsx b/app/javascript/mastodon/components/column.tsx deleted file mode 100644 index 2abe3425e4c..00000000000 --- a/app/javascript/mastodon/components/column.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { forwardRef, useRef, useImperativeHandle } from 'react'; -import type { Ref } from 'react'; - -import classNames from 'classnames'; - -import { scrollTop } from 'mastodon/scroll'; - -export interface ColumnRef { - scrollTop: () => void; - node: HTMLDivElement | null; -} - -interface ColumnProps { - children?: React.ReactNode; - label?: string; - bindToDocument?: boolean; - className?: string; -} - -export const Column = forwardRef( - ({ children, label, bindToDocument, className }, ref: Ref) => { - const nodeRef = useRef(null); - - useImperativeHandle(ref, () => ({ - node: nodeRef.current, - - scrollTop() { - let scrollable = null; - - if (bindToDocument) { - scrollable = document.scrollingElement; - } else { - scrollable = nodeRef.current?.querySelector('.scrollable'); - } - - if (!scrollable) { - return; - } - - scrollTop(scrollable); - }, - })); - - return ( -
- {children} -
- ); - }, -); - -Column.displayName = 'Column'; - -// eslint-disable-next-line import/no-default-export -export default Column; diff --git a/app/javascript/mastodon/components/column_back_button.tsx b/app/javascript/mastodon/components/column/back_button.tsx similarity index 91% rename from app/javascript/mastodon/components/column_back_button.tsx rename to app/javascript/mastodon/components/column/back_button.tsx index bb6939e24c6..72fc0443b5f 100644 --- a/app/javascript/mastodon/components/column_back_button.tsx +++ b/app/javascript/mastodon/components/column/back_button.tsx @@ -7,9 +7,9 @@ import { Icon } from 'mastodon/components/icon'; import { getColumnSkipLinkId } from 'mastodon/features/ui/components/skip_links'; import { ButtonInTabsBar } from 'mastodon/features/ui/util/columns_context'; -import { useColumnIndexContext } from '../features/ui/components/columns_area'; +import { useAppHistory } from '../router'; -import { useAppHistory } from './router'; +import { useColumnIndexContext } from './context'; type OnClickCallback = () => void; diff --git a/app/javascript/mastodon/components/column/context.ts b/app/javascript/mastodon/components/column/context.ts new file mode 100644 index 00000000000..79ab231847c --- /dev/null +++ b/app/javascript/mastodon/components/column/context.ts @@ -0,0 +1,12 @@ +import { createContext, useContext } from 'react'; + +export const ColumnIndexContext = createContext(1); +export const useColumnIndexContext = () => useContext(ColumnIndexContext); + +export const ColumnContext = createContext({ + scrollTop: () => { + // Implemented in index.tsx + }, +}); + +export const useColumn = () => useContext(ColumnContext); diff --git a/app/javascript/mastodon/components/column_header.tsx b/app/javascript/mastodon/components/column/header.tsx similarity index 93% rename from app/javascript/mastodon/components/column_header.tsx rename to app/javascript/mastodon/components/column/header.tsx index 77cba09fbe7..dd8d8fca36a 100644 --- a/app/javascript/mastodon/components/column_header.tsx +++ b/app/javascript/mastodon/components/column/header.tsx @@ -16,11 +16,11 @@ import { Icon } from 'mastodon/components/icon'; import { ButtonInTabsBar } from 'mastodon/features/ui/util/columns_context'; import { useIdentity } from 'mastodon/identity_context'; -import { useColumnIndexContext } from '../features/ui/components/columns_area'; -import { getColumnSkipLinkId } from '../features/ui/components/skip_links'; +import { getColumnSkipLinkId } from '../../features/ui/components/skip_links'; +import { NavigationFocusTarget } from '../navigation_focus_target'; +import { useAppHistory } from '../router'; -import { NavigationFocusTarget } from './navigation_focus_target'; -import { useAppHistory } from './router'; +import { useColumn, useColumnIndexContext } from './context'; export const messages = defineMessages({ show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' }, @@ -73,7 +73,7 @@ const BackButton: React.FC<{ ); }; -export interface Props { +export interface ColumnHeaderProps { title?: React.ReactNode; icon?: string; iconComponent?: IconProp; @@ -87,12 +87,13 @@ export interface Props { placeholder?: boolean; appendContent?: React.ReactNode; collapseIssues?: boolean; + scrollTopOnClick?: boolean; onClick?: () => void; onMove?: (arg0: number) => void; onPin?: () => void; } -export const ColumnHeader: React.FC = ({ +export const ColumnHeader: React.FC = ({ title, icon, iconComponent, @@ -106,6 +107,7 @@ export const ColumnHeader: React.FC = ({ placeholder, appendContent, collapseIssues, + scrollTopOnClick, onClick, onMove, onPin, @@ -125,9 +127,13 @@ export const ColumnHeader: React.FC = ({ [setCollapsed, setAnimating], ); + const { scrollTop } = useColumn(); const handleTitleClick = useCallback(() => { onClick?.(); - }, [onClick]); + if (scrollTopOnClick) { + scrollTop(); + } + }, [onClick, scrollTop, scrollTopOnClick]); const handleMoveLeft = useCallback(() => { onMove?.(-1); @@ -290,7 +296,7 @@ export const ColumnHeader: React.FC = ({ as='h1' className='column-header__title-wrapper' > - {onClick ? ( + {onClick || scrollTopOnClick ? (