Redesign: Update column header on many pages (#40362)

This commit is contained in:
diondiondion
2026-09-02 15:56:01 +00:00
committed by GitHub
parent 379542d59c
commit 171438e185
19 changed files with 498 additions and 79 deletions

View File

@@ -35,9 +35,16 @@ export const WithBackButton: Story = {
},
};
export const WithUnreadMarker: Story = {
args: {
withUnreadMarker: true,
},
};
export const WithButtons: Story = {
args: {
withBackButton: true,
withUnreadMarker: false,
extraButtons: (
<>
<ColumnHeaderButton icon={DotsThreeIcon}>Options</ColumnHeaderButton>

View File

@@ -0,0 +1,46 @@
import { FormattedMessage } from 'react-intl';
import { DotsThreeIcon } from '@phosphor-icons/react';
import { ColumnHeaderButton } from '@/mastodon/components/column_header';
import { Menu, MenuList, MenuTrigger } from '@/mastodon/components/menu';
import type { IconButtonProps } from '../button/redesign';
type ColumnSettingsMenuProps = {
icon?: IconButtonProps['icon'];
children: React.ReactNode;
} & (
| {
labelPrefix?: never;
label: React.ReactNode;
}
| {
labelPrefix: React.ReactNode;
label?: never;
}
);
export const ColumnSettingsMenu: React.FC<ColumnSettingsMenuProps> = ({
label,
labelPrefix,
icon = DotsThreeIcon,
children,
}) => {
return (
<Menu>
<MenuTrigger as={ColumnHeaderButton} icon={icon}>
{labelPrefix}
{label ?? (
<FormattedMessage
id='column.settings'
defaultMessage='Column Settings'
/>
)}
</MenuTrigger>
<MenuList placement='bottom-end' strategy='absolute'>
{children}
</MenuList>
</Menu>
);
};

View File

@@ -3,6 +3,7 @@ import { useCallback } from 'react';
import { FormattedMessage } from 'react-intl';
import classNames from 'classnames';
import { useLocation } from 'react-router';
import { ArrowLeftIcon, ListIcon } from '@phosphor-icons/react';
@@ -17,13 +18,19 @@ import type { IconButtonProps } from '../button/redesign';
import { Button, IconButton } from '../button/redesign';
import { useColumn, useColumnIndexContext } from '../column/context';
import { NavigationFocusTarget } from '../navigation_focus_target';
import type { LocationState } from '../router';
import { useAppHistory } from '../router';
import classes from './styles.module.scss';
export { ColumnSettingsMenu } from './column_settings_menu';
export interface ColumnHeaderProps {
title: string;
withBackButton?: boolean;
// Set to auto to display the back button based on
// the `fromMastodon` location state
withBackButton?: boolean | 'auto';
withUnreadMarker?: boolean;
extraButtons?: React.ReactNode;
className?: string;
}
@@ -31,17 +38,26 @@ export interface ColumnHeaderProps {
export const ColumnHeader: React.FC<ColumnHeaderProps> = ({
title,
withBackButton,
withUnreadMarker,
extraButtons,
className,
...props
}: ColumnHeaderProps) => {
const { scrollTop } = useColumn();
const columnIndex = useColumnIndexContext();
const location = useLocation<LocationState>();
const hasBackButton =
withBackButton === true ||
(withBackButton === 'auto' && location.state?.fromMastodon);
return (
<RenderIntoTabsBarPortal>
<header {...props} className={classNames(className, classes.root)}>
{withBackButton ? <BackButton /> : <MobileMenuButton />}
<header
{...props}
className={classNames(className, classes.root)}
data-has-unread={withUnreadMarker}
>
{hasBackButton ? <BackButton /> : <MobileMenuButton />}
<NavigationFocusTarget className={classes.title}>
<button
type='button'
@@ -49,6 +65,15 @@ export const ColumnHeader: React.FC<ColumnHeaderProps> = ({
id={getColumnSkipLinkId(columnIndex)}
>
{title}
{withUnreadMarker && (
<span className='sr-only'>
{' '}
<FormattedMessage
id='column.has_unread_content'
defaultMessage='(has unread content)'
/>
</span>
)}
</button>
</NavigationFocusTarget>
{hasReactChildren(extraButtons) && (

View File

@@ -0,0 +1,74 @@
import { useCallback } from 'react';
import { FormattedMessage } from 'react-intl';
import { useHistory } from 'react-router';
import { MenuItem, MenuItemDivider } from '@/mastodon/components/menu';
interface MultiColumnMenuItemsProps {
withDivider?: boolean;
pinned: boolean;
onPin: () => void;
onMove?: (direction: number) => void;
}
export const MultiColumnMenuItems: React.FC<MultiColumnMenuItemsProps> = ({
withDivider = false,
onPin,
onMove,
pinned,
}) => {
const history = useHistory();
const togglePin = useCallback(() => {
if (!pinned) {
history.replace('/');
}
onPin();
}, [history, pinned, onPin]);
const moveLeft = useCallback(() => {
onMove?.(-1);
}, [onMove]);
const moveRight = useCallback(() => {
onMove?.(1);
}, [onMove]);
return (
<>
{withDivider && <MenuItemDivider />}
<MenuItem onClick={togglePin} keepMenuOpenOnClick>
{pinned ? (
<FormattedMessage
id='column_header.unpin_column'
defaultMessage='Unpin column'
/>
) : (
<FormattedMessage
id='column_header.pin_column'
defaultMessage='Pin column'
/>
)}
</MenuItem>
{pinned && onMove && (
<>
<MenuItem onClick={moveLeft} keepMenuOpenOnClick>
<FormattedMessage
id='column_header.move_column_left'
defaultMessage='Move column left'
/>
</MenuItem>
<MenuItem onClick={moveRight} keepMenuOpenOnClick>
<FormattedMessage
id='column_header.move_column_right'
defaultMessage='Move column right'
/>
</MenuItem>
</>
)}
</>
);
};

View File

@@ -1,4 +1,5 @@
@use '@/styles/mastodon/mixins';
@use '@/styles/mastodon/variables';
.root {
position: relative;
@@ -12,8 +13,6 @@
align-items: center;
min-height: 40px;
padding: var(--space-sm);
border-top-left-radius: var(--radius-xl);
border-top-right-radius: var(--radius-xl);
text-align: center;
color: var(--color-text-primary);
background: linear-gradient(
@@ -21,12 +20,29 @@
var(--color-bg-primary) var(--column-header-gradient-start, 55%),
transparent
);
@media (width >= variables.$mobile-menu-breakpoint) {
border-top-left-radius: var(--radius-xl);
border-top-right-radius: var(--radius-xl);
}
&[data-has-unread='true']::after {
content: '';
grid-row: 1;
grid-column: 2;
width: var(--space-xs);
height: var(--space-xs);
background-color: var(--color-text-brand);
border-radius: var(--radius-round);
justify-self: center;
align-self: end;
}
}
.title {
@include mixins.type-heading-sm;
grid-column: 2;
grid-area: 1 / 2;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
@@ -43,10 +59,12 @@
}
.leftButton {
grid-area: 1 / 1;
justify-self: start;
}
.rightButtons {
grid-area: 1 / 3;
display: flex;
align-items: center;
justify-self: end;

View File

@@ -200,13 +200,15 @@ function useAssertMenuType(componentName: string) {
}
}
export type MenuItemRadioChangeHandler = (change: { value: string }) => void;
interface MenuItemRadioProps extends Omit<
MenuItemProps<'button'>,
'as' | 'onChange' | 'icon'
> {
checked: boolean;
value: string;
onChange?: (change: { value: string }) => void;
onChange?: MenuItemRadioChangeHandler;
}
export const MenuItemRadio: React.FC<MenuItemRadioProps> = ({
@@ -236,9 +238,14 @@ export const MenuItemRadio: React.FC<MenuItemRadioProps> = ({
);
};
export type MenuItemCheckboxChangeHandler = (change: {
value: string;
checked: boolean;
}) => void;
interface MenuItemCheckboxProps extends Omit<MenuItemRadioProps, 'onChange'> {
icon?: IconProp;
onChange?: (change: { value: string; checked: boolean }) => void;
onChange?: MenuItemCheckboxChangeHandler;
}
export const MenuItemCheckbox: React.FC<MenuItemCheckboxProps> = ({

View File

@@ -11,6 +11,7 @@
overflow: hidden;
z-index: calc(infinity);
max-width: var(--_max-card-width, 100vw);
text-align: start;
&[data-elevation='2'] {
@include mixins.elevation-2;

View File

@@ -15,10 +15,14 @@ import { Account } from '@/mastodon/components/account';
import { Column } from '@/mastodon/components/column';
import { LoadingIndicator } from '@/mastodon/components/loading_indicator';
import ScrollableList from '@/mastodon/components/scrollable_list';
import { ColumnHeader } from '@/mastodon/components/column/header';
import { ColumnHeader as LegacyColumnHeader } from '@/mastodon/components/column/header';
import { isRedesignEnabled } from '@/mastodon/utils/environment';
import { ColumnHeader } from '@/mastodon/components/column_header';
import { Helmet } from '@unhead/react/helmet';
const messages = defineMessages({
heading: { id: 'column.blocks', defaultMessage: 'Blocked users' },
heading_redesign: { id: 'column.blocked_accounts', defaultMessage: 'Blocked Accounts' },
});
const mapStateToProps = state => ({
@@ -62,7 +66,11 @@ class Blocks extends ImmutablePureComponent {
return (
<Column bindToDocument={!multiColumn}>
<ColumnHeader icon='ban' iconComponent={BlockIcon} title={intl.formatMessage(messages.heading)} showBackButton />
{isRedesignEnabled() ? (
<ColumnHeader withBackButton={multiColumn && 'auto'} title={intl.formatMessage(messages.heading_redesign)} />
) : (
<LegacyColumnHeader icon='ban' iconComponent={BlockIcon} title={intl.formatMessage(messages.heading)} showBackButton />
)}
<ScrollableList
scrollKey='blocks'
onLoadMore={this.handleLoadMore}
@@ -75,6 +83,13 @@ class Blocks extends ImmutablePureComponent {
<Account key={id} id={id} defaultAction='block' />,
)}
</ScrollableList>
<Helmet>
<title>
{intl.formatMessage(isRedesignEnabled() ? messages.heading_redesign : messages.heading)}
</title>
<meta name='robots' content='noindex' />
</Helmet>
</Column>
);
}

View File

@@ -6,7 +6,11 @@ import { Helmet } from '@unhead/react/helmet';
import { Column } from '@/mastodon/components/column';
import { ColumnHeader as LegacyColumnHeader } from '@/mastodon/components/column/header';
import { ColumnHeader } from '@/mastodon/components/column_header';
import {
ColumnHeader,
ColumnSettingsMenu,
} from '@/mastodon/components/column_header';
import { MultiColumnMenuItems } from '@/mastodon/components/column_header/multicolumn_settings';
import { isRedesignEnabled } from '@/mastodon/utils/environment';
import BookmarksIcon from '@/material-icons/400-24px/bookmarks-fill.svg?react';
import {
@@ -20,7 +24,7 @@ import { useAppDispatch, useAppSelector } from 'mastodon/store';
const messages = defineMessages({
heading: { id: 'column.bookmarks', defaultMessage: 'Bookmarks' },
headingRedesign: { id: 'column.saved_posts', defaultMessage: 'Saved Posts' },
heading_redesign: { id: 'column.saved_posts', defaultMessage: 'Saved Posts' },
});
const Bookmarks: React.FC<{
@@ -78,7 +82,23 @@ const Bookmarks: React.FC<{
label={intl.formatMessage(messages.heading)}
>
{isRedesignEnabled() ? (
<ColumnHeader title={intl.formatMessage(messages.headingRedesign)} />
<ColumnHeader
title={intl.formatMessage(messages.heading_redesign)}
withBackButton={multiColumn && !pinned && 'auto'}
extraButtons={
multiColumn && (
<ColumnSettingsMenu
labelPrefix={intl.formatMessage(messages.heading_redesign)}
>
<MultiColumnMenuItems
pinned={pinned}
onPin={handlePin}
onMove={handleMove}
/>
</ColumnSettingsMenu>
)
}
/>
) : (
<LegacyColumnHeader
icon='bookmarks'
@@ -107,7 +127,7 @@ const Bookmarks: React.FC<{
<Helmet>
<title>
{isRedesignEnabled()
? intl.formatMessage(messages.headingRedesign)
? intl.formatMessage(messages.heading_redesign)
: intl.formatMessage(messages.heading)}
</title>
<meta name='robots' content='noindex' />

View File

@@ -5,8 +5,14 @@ import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { Helmet } from '@unhead/react/helmet';
import { Column } from '@/mastodon/components/column';
import { ColumnHeader } from '@/mastodon/components/column/header';
import { ColumnHeader as LegacyColumnHeader } from '@/mastodon/components/column/header';
import {
ColumnHeader,
ColumnSettingsMenu,
} from '@/mastodon/components/column_header';
import { MultiColumnMenuItems } from '@/mastodon/components/column_header/multicolumn_settings';
import { useAppDispatch } from '@/mastodon/store';
import { isRedesignEnabled } from '@/mastodon/utils/environment';
import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react';
import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns';
import {
@@ -20,6 +26,7 @@ import { ConversationsList } from './components/conversations_list';
const messages = defineMessages({
title: { id: 'column.direct', defaultMessage: 'Private mentions' },
title_redesign: { id: 'tab_bar.messages', defaultMessage: 'Messages' },
});
interface ColumnBase {
@@ -64,16 +71,36 @@ const DirectTimeline: React.FC<ColumnBase> = ({ columnId, multiColumn }) => {
bindToDocument={!multiColumn}
label={intl.formatMessage(messages.title)}
>
<ColumnHeader
icon='at'
iconComponent={AlternateEmailIcon}
title={intl.formatMessage(messages.title)}
onPin={handlePin}
onMove={handleMove}
pinned={pinned}
multiColumn={multiColumn}
scrollTopOnClick
/>
{isRedesignEnabled() ? (
<ColumnHeader
title={intl.formatMessage(messages.title_redesign)}
withBackButton={multiColumn && !pinned && 'auto'}
extraButtons={
multiColumn && (
<ColumnSettingsMenu
labelPrefix={intl.formatMessage(messages.title_redesign)}
>
<MultiColumnMenuItems
onPin={handlePin}
onMove={handleMove}
pinned={pinned}
/>
</ColumnSettingsMenu>
)
}
/>
) : (
<LegacyColumnHeader
icon='at'
iconComponent={AlternateEmailIcon}
title={intl.formatMessage(messages.title)}
onPin={handlePin}
onMove={handleMove}
pinned={pinned}
multiColumn={multiColumn}
scrollTopOnClick
/>
)}
<ConversationsList
trackScroll={!pinned}
@@ -109,7 +136,11 @@ const DirectTimeline: React.FC<ColumnBase> = ({ columnId, multiColumn }) => {
/>
<Helmet>
<title>{intl.formatMessage(messages.title)}</title>
<title>
{intl.formatMessage(
isRedesignEnabled() ? messages.title_redesign : messages.title,
)}
</title>
<meta name='robots' content='noindex' />
</Helmet>
</Column>

View File

@@ -6,7 +6,8 @@ import { NavLink, Switch, Route } from 'react-router-dom';
import { Helmet } from '@unhead/react/helmet';
import { Column } from '@/mastodon/components/column';
import { ColumnHeader } from '@/mastodon/components/column/header';
import { ColumnHeader as LegacyColumnHeader } from '@/mastodon/components/column/header';
import { ColumnHeader } from '@/mastodon/components/column_header';
import { isRedesignEnabled } from '@/mastodon/utils/environment';
import TrendingUpIcon from '@/material-icons/400-24px/trending_up.svg?react';
import { SymbolLogo } from 'mastodon/components/logo';
@@ -22,6 +23,7 @@ import Tags from './tags';
const messages = defineMessages({
title: { id: 'explore.title', defaultMessage: 'Trending' },
titleRedesign: { id: 'tabs_bar.explore', defaultMessage: 'Explore' },
});
const Explore: React.FC<{ multiColumn: boolean }> = ({ multiColumn }) => {
@@ -34,13 +36,20 @@ const Explore: React.FC<{ multiColumn: boolean }> = ({ multiColumn }) => {
bindToDocument={!multiColumn}
label={intl.formatMessage(messages.title)}
>
<ColumnHeader
icon={'explore'}
iconComponent={logoRequired ? SymbolLogo : TrendingUpIcon}
title={intl.formatMessage(messages.title)}
multiColumn={multiColumn}
scrollTopOnClick
/>
{isRedesignEnabled() ? (
<ColumnHeader
withBackButton={multiColumn && 'auto'}
title={intl.formatMessage(messages.titleRedesign)}
/>
) : (
<LegacyColumnHeader
icon={'explore'}
iconComponent={logoRequired ? SymbolLogo : TrendingUpIcon}
title={intl.formatMessage(messages.title)}
multiColumn={multiColumn}
scrollTopOnClick
/>
)}
<div
className={classNames(
@@ -97,7 +106,11 @@ const Explore: React.FC<{ multiColumn: boolean }> = ({ multiColumn }) => {
</Switch>
<Helmet>
<title>{intl.formatMessage(messages.title)}</title>
<title>
{intl.formatMessage(
isRedesignEnabled() ? messages.titleRedesign : messages.title,
)}
</title>
<meta name='robots' content='all' />
</Helmet>
</Column>

View File

@@ -1,3 +1,4 @@
.searchHeader {
display: flex !important;
border-inline: none;
}

View File

@@ -5,7 +5,13 @@ import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { Helmet } from '@unhead/react/helmet';
import { Column } from '@/mastodon/components/column';
import { ColumnHeader } from '@/mastodon/components/column/header';
import { ColumnHeader as LegacyColumnHeader } from '@/mastodon/components/column/header';
import {
ColumnHeader,
ColumnSettingsMenu,
} from '@/mastodon/components/column_header';
import { MultiColumnMenuItems } from '@/mastodon/components/column_header/multicolumn_settings';
import { isRedesignEnabled } from '@/mastodon/utils/environment';
import StarIcon from '@/material-icons/400-24px/star-fill.svg?react';
import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns';
import {
@@ -18,6 +24,10 @@ import { useAppDispatch, useAppSelector } from 'mastodon/store';
const messages = defineMessages({
heading: { id: 'column.favourites', defaultMessage: 'Favorites' },
heading_redesign: {
id: 'navigation_bar.liked_posts',
defaultMessage: 'Liked Posts',
},
});
const Favourites: React.FC<{ columnId: string; multiColumn: boolean }> = ({
@@ -74,16 +84,36 @@ const Favourites: React.FC<{ columnId: string; multiColumn: boolean }> = ({
bindToDocument={!multiColumn}
label={intl.formatMessage(messages.heading)}
>
<ColumnHeader
icon='star'
iconComponent={StarIcon}
title={intl.formatMessage(messages.heading)}
onPin={handlePin}
onMove={handleMove}
pinned={pinned}
multiColumn={multiColumn}
scrollTopOnClick
/>
{isRedesignEnabled() ? (
<ColumnHeader
title={intl.formatMessage(messages.heading_redesign)}
withBackButton={multiColumn && !pinned && 'auto'}
extraButtons={
multiColumn && (
<ColumnSettingsMenu
labelPrefix={intl.formatMessage(messages.heading_redesign)}
>
<MultiColumnMenuItems
onPin={handlePin}
onMove={handleMove}
pinned={pinned}
/>
</ColumnSettingsMenu>
)
}
/>
) : (
<LegacyColumnHeader
icon='star'
iconComponent={StarIcon}
title={intl.formatMessage(messages.heading)}
onPin={handlePin}
onMove={handleMove}
pinned={pinned}
multiColumn={multiColumn}
scrollTopOnClick
/>
)}
<StatusList
trackScroll={!pinned}

View File

@@ -13,7 +13,7 @@ import { changeSetting } from 'mastodon/actions/settings';
import { connectPublicStream, connectCommunityStream } from 'mastodon/actions/streaming';
import { expandPublicTimeline, expandCommunityTimeline } from 'mastodon/actions/timelines';
import { Column } from '@/mastodon/components/column';
import { ColumnHeader } from '@/mastodon/components/column/header';
import { ColumnHeader as LegacyColumnHeader } from '@/mastodon/components/column/header';
import { DismissableBanner } from 'mastodon/components/dismissable_banner';
import { localLiveFeedAccess, remoteLiveFeedAccess, domain } from 'mastodon/initial_state';
import { canViewFeed } from 'mastodon/permissions';
@@ -21,6 +21,9 @@ import { useAppDispatch, useAppSelector } from 'mastodon/store';
import SettingToggle from '../notifications/components/setting_toggle';
import StatusListContainer from '../ui/containers/status_list_container';
import { isRedesignEnabled } from '@/mastodon/utils/environment';
import { ColumnHeader, ColumnSettingsMenu } from '@/mastodon/components/column_header';
import { MultiColumnMenuItems } from '@/mastodon/components/column_header/multicolumn_settings';
const messages = defineMessages({
title: { id: 'column.firehose', defaultMessage: 'Live feeds' },
@@ -32,6 +35,7 @@ const messages = defineMessages({
id: 'column.firehose_singular',
defaultMessage: 'Live feed',
},
title_redesign: { id: 'tabs_bar.fediverse_feeds', defaultMessage: 'Fediverse Feeds' },
});
const ColumnSettings = () => {
@@ -178,17 +182,30 @@ const Firehose = ({ feedType, multiColumn }) => {
return (
<Column bindToDocument={!multiColumn} label={intl.formatMessage(messages.title)}>
<ColumnHeader
icon='globe'
iconComponent={PublicIcon}
active={hasUnread}
title={intl.formatMessage(title)}
onPin={handlePin}
multiColumn={multiColumn}
scrollTopOnClick
>
<ColumnSettings />
</ColumnHeader>
{isRedesignEnabled ? (
<ColumnHeader
title={intl.formatMessage(messages.title_redesign)}
withBackButton={multiColumn && 'auto'}
withUnreadMarker={hasUnread}
extraButtons={multiColumn &&
<ColumnSettingsMenu labelPrefix={intl.formatMessage(messages.title_redesign)}>
<MultiColumnMenuItems onPin={handlePin} />
</ColumnSettingsMenu>
}
/>
) : (
<LegacyColumnHeader
icon='globe'
iconComponent={PublicIcon}
active={hasUnread}
title={intl.formatMessage(title)}
onPin={handlePin}
multiColumn={multiColumn}
scrollTopOnClick
>
<ColumnSettings />
</LegacyColumnHeader>
)}
{(canViewFeed(signedIn, permissions, localLiveFeedAccess) && canViewFeed(signedIn, permissions, remoteLiveFeedAccess)) && (
<div className='account__section-headline'>

View File

@@ -0,0 +1,79 @@
import { useCallback } from 'react';
import { FormattedMessage } from 'react-intl';
import { SlidersHorizontalIcon } from '@phosphor-icons/react';
import { ColumnSettingsMenu } from '@/mastodon/components/column_header';
import { MenuItemCheckbox } from '@/mastodon/components/menu';
import type { MenuItemCheckboxChangeHandler } from '@/mastodon/components/menu/items';
import { useAppSelector, useAppDispatch } from 'mastodon/store';
import { changeSetting } from '../../../actions/settings';
export const HomeColumnSettings: React.FC<{
children?: React.ReactNode;
}> = ({ children }) => {
const dispatch = useAppDispatch();
const settings = useAppSelector((state) => state.settings.get('home'));
const onChange = useCallback<MenuItemCheckboxChangeHandler>(
({ value, checked }) => {
dispatch(changeSetting(['home', 'shows', value], checked));
},
[dispatch],
);
/* eslint-disable @typescript-eslint/no-unsafe-call */
// @ts-expect-error settings isn't typed yet
const showBoosts = settings.getIn(['shows', 'reblog']) as boolean;
// @ts-expect-error settings isn't typed yet
const showQuotes = settings.getIn(['shows', 'quote']) as boolean;
// @ts-expect-error settings isn't typed yet
const showReplies = settings.getIn(['shows', 'reply']) as boolean;
/* eslint-enable @typescript-eslint/no-unsafe-call */
return (
<ColumnSettingsMenu
icon={SlidersHorizontalIcon}
label={
<FormattedMessage id='home.settings' defaultMessage='Home Settings' />
}
>
<MenuItemCheckbox
value='reblog'
checked={showBoosts}
onChange={onChange}
keepMenuOpenOnClick
>
<FormattedMessage
id='home.column_settings.show_reblogs'
defaultMessage='Show boosts'
/>
</MenuItemCheckbox>
<MenuItemCheckbox
value='quote'
checked={showQuotes}
onChange={onChange}
keepMenuOpenOnClick
>
<FormattedMessage
id='home.column_settings.show_quotes'
defaultMessage='Show quotes'
/>
</MenuItemCheckbox>
<MenuItemCheckbox
value='reply'
checked={showReplies}
onChange={onChange}
keepMenuOpenOnClick
>
<FormattedMessage
id='home.column_settings.show_replies'
defaultMessage='Show replies'
/>
</MenuItemCheckbox>
{children}
</ColumnSettingsMenu>
);
};

View File

@@ -11,7 +11,7 @@ import { connect } from 'react-redux';
import CampaignIcon from '@/material-icons/400-24px/campaign.svg?react';
import HomeIcon from '@/material-icons/400-24px/home-fill.svg?react';
import { Column } from '@/mastodon/components/column';
import { ColumnHeader } from '@/mastodon/components/column/header';
import { ColumnHeader as LegacyColumnHeader } from '@/mastodon/components/column/header';
import { injectIntl } from '@/mastodon/components/intl';
import { SymbolLogo } from 'mastodon/components/logo';
import { fetchAnnouncements, toggleShowAnnouncements } from 'mastodon/actions/announcements';
@@ -28,6 +28,10 @@ import { ColumnSettings } from './components/column_settings';
import { CriticalUpdateBanner } from './components/critical_update_banner';
import { Announcements } from './components/announcements';
import { AnnualReportTimeline } from '../annual_report/timeline';
import { isRedesignEnabled } from '@/mastodon/utils/environment';
import { ColumnHeader } from '@/mastodon/components/column_header';
import { HomeColumnSettings } from './components/column_settings_redesign';
import { MultiColumnMenuItems } from '@/mastodon/components/column_header/multicolumn_settings';
const messages = defineMessages({
title: { id: 'column.home', defaultMessage: 'Home' },
@@ -143,21 +147,40 @@ class HomeTimeline extends PureComponent {
return (
<Column bindToDocument={!multiColumn} label={intl.formatMessage(messages.title)}>
<ColumnHeader
icon='home'
iconComponent={matchesBreakpoint ? SymbolLogo : HomeIcon}
active={hasUnread}
title={intl.formatMessage(messages.title)}
onPin={this.handlePin}
onMove={this.handleMove}
pinned={pinned}
multiColumn={multiColumn}
extraButton={announcementsButton}
appendContent={hasAnnouncements && showAnnouncements && <Announcements />}
scrollTopOnClick
>
<ColumnSettings />
</ColumnHeader>
{isRedesignEnabled() ? (
<ColumnHeader
title={intl.formatMessage(messages.title)}
withUnreadMarker={hasUnread}
extraButtons={
<HomeColumnSettings>
{multiColumn &&
<MultiColumnMenuItems
withDivider
onPin={this.handlePin}
onMove={this.handleMove}
pinned={pinned}
/>
}
</HomeColumnSettings>
}
/>
) : (
<LegacyColumnHeader
icon='home'
iconComponent={matchesBreakpoint ? SymbolLogo : HomeIcon}
active={hasUnread}
title={intl.formatMessage(messages.title)}
onPin={this.handlePin}
onMove={this.handleMove}
pinned={pinned}
multiColumn={multiColumn}
extraButton={announcementsButton}
appendContent={hasAnnouncements && showAnnouncements && <Announcements />}
scrollTopOnClick
>
<ColumnSettings />
</LegacyColumnHeader>
)}
{signedIn ? (
<StatusListContainer

View File

@@ -100,7 +100,7 @@ export const NavigationAccountCardAndMenu: React.FC = () => {
<MenuItemLink to='/favourites' icon={HeartIcon}>
<FormattedMessage
id='navigation_bar.liked_posts'
defaultMessage='Liked posts'
defaultMessage='Liked Posts'
/>
</MenuItemLink>

View File

@@ -449,6 +449,7 @@
"collections.visibility_unlisted": "Unlisted",
"collections.visibility_unlisted_hint": "Visible to anyone with a link. Hidden from search results and recommendations.",
"column.about": "About",
"column.blocked_accounts": "Blocked Accounts",
"column.blocks": "Blocked users",
"column.bookmarks": "Bookmarks",
"column.community": "Local timeline",
@@ -462,6 +463,7 @@
"column.firehose_local": "Live feed for this server",
"column.firehose_singular": "Live feed",
"column.follow_requests": "Follow requests",
"column.has_unread_content": "(has unread content)",
"column.home": "Home",
"column.list_members": "Manage list members",
"column.lists": "Lists",
@@ -471,14 +473,19 @@
"column.pins": "Pinned posts",
"column.public": "Federated timeline",
"column.saved_posts": "Saved Posts",
"column.settings": "Column Settings",
"column.your_collections": "Your Collections",
"column_back_button.label": "Back",
"column_header.hide_settings": "Hide settings",
"column_header.moveLeft_settings": "Move column to the left",
"column_header.moveRight_settings": "Move column to the right",
"column_header.move_column_left": "Move column left",
"column_header.move_column_right": "Move column right",
"column_header.pin": "Pin",
"column_header.pin_column": "Pin column",
"column_header.show_settings": "Show settings",
"column_header.unpin": "Unpin",
"column_header.unpin_column": "Unpin column",
"column_search.cancel": "Cancel",
"combobox.close_results": "Close results",
"combobox.loading": "Loading",
@@ -853,6 +860,7 @@
"home.pending_critical_update.body": "Please update your Mastodon server as soon as possible!",
"home.pending_critical_update.link": "See updates",
"home.pending_critical_update.title": "Critical security update available!",
"home.settings": "Home Settings",
"home.show_announcements": "Show announcements",
"ignore_notifications_modal.bots_title": "Ignore notifications from bots?",
"ignore_notifications_modal.disclaimer": "Mastodon cannot inform users that you've ignored their notifications. Ignoring notifications will not stop the messages themselves from being sent.",
@@ -979,7 +987,7 @@
"navigation_bar.administration": "Administration",
"navigation_bar.advanced_interface": "Open in advanced web interface",
"navigation_bar.automated_deletion": "Automated post deletion",
"navigation_bar.blocked_accounts": "Blocked accounts",
"navigation_bar.blocked_accounts": "Blocked Accounts",
"navigation_bar.blocks": "Blocked users",
"navigation_bar.bookmarks": "Bookmarks",
"navigation_bar.collections": "Collections",
@@ -992,7 +1000,7 @@
"navigation_bar.followers_and_following": "Followers & Following",
"navigation_bar.follows_and_followers": "Follows and followers",
"navigation_bar.import_export": "Import and export",
"navigation_bar.liked_posts": "Liked posts",
"navigation_bar.liked_posts": "Liked Posts",
"navigation_bar.lists": "Lists",
"navigation_bar.live_feed_local": "Live feed (local)",
"navigation_bar.live_feed_public": "Live feed (public)",
@@ -1403,6 +1411,7 @@
"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}",
"tab_bar.messages": "Messages",
"tabs_bar.create_custom_feed": "Create feed",
"tabs_bar.custom_feeds": "Custom Feeds",
"tabs_bar.custom_feeds_empty": "You have no custom feeds yet.",

View File

@@ -8044,9 +8044,12 @@ a.status-card {
display: flex;
flex-shrink: 0;
[data-redesign='true'] & {
border-inline: none;
}
@media screen and (max-width: ($no-gap-breakpoint - 1px)) {
border-right: 0;
border-left: 0;
border-inline: none;
}
button {