Redesign: Implement new navigation in advanced (multi-column) layout (#40522)

This commit is contained in:
diondiondion
2026-09-15 14:49:32 +00:00
committed by GitHub
parent 9b63f47629
commit e1adc7c1af
6 changed files with 87 additions and 19 deletions

View File

@@ -5,9 +5,11 @@ import classNames from 'classnames';
import { useDebouncedCallback } from 'use-debounce';
import { getColumnSkipLinkId } from '@/mastodon/features/ui/components/skip_links';
import { isRedesignEnabled } from '@/mastodon/utils/environment';
import { scrollTop } from 'mastodon/scroll';
import { ColumnContext, useColumnIndexContext } from './context';
import classes from './styles.module.scss';
interface ColumnProps {
children?: React.ReactNode;
@@ -66,7 +68,10 @@ export const Column: React.FC<ColumnProps> = ({
role='region'
ref={nodeRef}
onScroll={handleScroll}
className={classNames('column', className)}
className={classNames(
isRedesignEnabled() ? classes.root : 'column',
className,
)}
aria-label={label}
aria-labelledby={
label === undefined ? getColumnSkipLinkId(columnIndex) : undefined

View File

@@ -0,0 +1,19 @@
:global(.layout-multiple-columns) .root {
box-sizing: border-box;
position: relative;
display: flex;
flex-direction: column;
flex: 0 0 auto;
--available-width: calc(
100% - var(--multi-column-navigation-width) - var(--multi-column-gap)
);
width: clamp(
360px,
(var(--available-width) / 4 - var(--multi-column-gap)),
400px
);
padding: 0;
background: var(--color-bg-primary);
}

View File

@@ -4,6 +4,7 @@ import type { List, Record } from 'immutable';
import { ColumnIndexContext } from '@/mastodon/components/column/context';
import { useAppSelector } from '@/mastodon/store';
import { isRedesignEnabled } from '@/mastodon/utils/environment';
import {
Compose,
@@ -76,6 +77,10 @@ export const MultiColumnContent: React.FC<{
const uuid = column.get('uuid');
const id = column.get('id');
if (isRedesignEnabled() && id === 'COMPOSE') {
return null;
}
return (
<ColumnIndexContext.Provider value={index} key={uuid}>
<Bundle

View File

@@ -6,7 +6,6 @@
--navigation-max-width: 320px;
box-sizing: border-box;
display: flex;
width: 100%;
height: 100%;
min-height: 100vh;
@@ -33,6 +32,19 @@
--navigation-min-width: 0;
}
.multiColumnRoot {
--multi-column-navigation-width: 320px;
--multi-column-gap: var(--space-xs);
position: relative;
display: flex;
flex: 1 1 auto;
justify-content: flex-start;
gap: var(--multi-column-gap);
padding-inline-end: var(--multi-column-gap);
overflow-x: auto;
}
.navigationWrapper {
position: sticky;
top: 0;
@@ -41,6 +53,14 @@
height: 100dvh;
padding-bottom: env(safe-area-inset-bottom);
.multiColumnRoot & {
height: initial;
min-width: var(--multi-column-navigation-width);
inset-inline-start: 0;
z-index: 100;
background: var(--color-bg-blend);
}
@media (max-width: ($mobile-menu-breakpoint - 1)) {
display: none;
}
@@ -58,12 +78,6 @@
color: var(--color-text-primary);
background-color: var(--color-bg-primary);
:global(.column) {
width: 100%;
height: 100%;
padding: 0;
}
:global(.scrollable) {
contain: content;
overflow: visible;

View File

@@ -3,13 +3,13 @@ import classNames from 'classnames';
import { ComposeRedesignButton } from '@/mastodon/features/compose/redesign/trigger';
import { RedesignNavigationPanel } from '@/mastodon/features/navigation_panel/redesign';
import { RedesignMobileNavigation } from '@/mastodon/features/navigation_panel/redesign/mobile_nav';
import { useAppSelector } from '@/mastodon/store';
import { Footer } from 'mastodon/features/custom_homepage/components/footer';
import { useBreakpoint } from '../../hooks/useBreakpoint';
import { MultiColumnContent } from './multi_column_content';
import classes from './redesign.module.scss';
import multiColClasses from './redesign_multicol.module.scss';
export const ColumnsAreaRedesign: React.FC<{
singleColumn?: boolean;
@@ -17,14 +17,11 @@ export const ColumnsAreaRedesign: React.FC<{
children: React.ReactElement | React.ReactElement[];
ref?: React.Ref<HTMLDivElement>;
}> = ({ children, minimalShell, singleColumn, ref }) => {
const isModalOpen = useAppSelector(
(state) => !state.modal.get('stack').isEmpty(),
);
const isMobile = useBreakpoint('openable');
if (minimalShell) {
return (
<div className={classNames(classes.root, classes.rootMinimal)}>
<div ref={ref} className={classNames(classes.root, classes.rootMinimal)}>
{isMobile && <RedesignMobileNavigation />}
<div className={classes.main}>
<div>{children}</div>
@@ -37,7 +34,7 @@ export const ColumnsAreaRedesign: React.FC<{
if (singleColumn) {
return (
<div className={classes.root}>
<div ref={ref} className={classes.root}>
<div className={classes.navigationWrapper}>
<RedesignNavigationPanel />
</div>
@@ -49,11 +46,11 @@ export const ColumnsAreaRedesign: React.FC<{
}
return (
<main
className={classNames('columns-area', { unscrollable: isModalOpen })}
ref={ref}
tabIndex={isModalOpen ? undefined : 0}
>
<main ref={ref} className={multiColClasses.root}>
<div className={multiColClasses.navigationWrapper}>
<RedesignNavigationPanel />
</div>
<ComposeRedesignButton />
<MultiColumnContent>{children}</MultiColumnContent>
</main>
);

View File

@@ -0,0 +1,28 @@
@use '@/styles/mastodon/variables' as *;
.root {
--multi-column-navigation-width: 320px;
--multi-column-gap: var(--space-xs);
position: relative;
display: flex;
flex: 1 1 auto;
justify-content: flex-start;
gap: var(--multi-column-gap);
padding-inline-end: var(--multi-column-gap);
overflow-x: auto;
}
.navigationWrapper {
position: sticky;
inset-inline-start: 0;
top: 0;
z-index: 100;
min-width: var(--multi-column-navigation-width);
padding-bottom: env(safe-area-inset-bottom);
background: var(--color-bg-blend);
@media (max-width: ($mobile-menu-breakpoint - 1)) {
display: none;
}
}