fix scroll on mobile (#2585)
* fix scrolling issues on mobile * resolve conflict
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { Button, Dropdown, Menu } from 'antd';
|
import { Button, Dropdown, Menu } from 'antd';
|
||||||
|
import classNames from 'classnames';
|
||||||
import { EllipsisOutlined, HeartOutlined, BellOutlined } from '@ant-design/icons';
|
import { EllipsisOutlined, HeartOutlined, BellOutlined } from '@ant-design/icons';
|
||||||
import styles from './ActionButtonMenu.module.scss';
|
import styles from './ActionButtonMenu.module.scss';
|
||||||
import { ExternalAction } from '../../../interfaces/external-action';
|
import { ExternalAction } from '../../../interfaces/external-action';
|
||||||
@@ -14,6 +15,7 @@ export type ActionButtonMenuProps = {
|
|||||||
externalActionSelected: (action: ExternalAction) => void;
|
externalActionSelected: (action: ExternalAction) => void;
|
||||||
notifyItemSelected: () => void;
|
notifyItemSelected: () => void;
|
||||||
followItemSelected: () => void;
|
followItemSelected: () => void;
|
||||||
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ActionButtonMenu: FC<ActionButtonMenuProps> = ({
|
export const ActionButtonMenu: FC<ActionButtonMenuProps> = ({
|
||||||
@@ -23,6 +25,7 @@ export const ActionButtonMenu: FC<ActionButtonMenuProps> = ({
|
|||||||
followItemSelected,
|
followItemSelected,
|
||||||
showFollowItem,
|
showFollowItem,
|
||||||
showNotifyItem,
|
showNotifyItem,
|
||||||
|
className,
|
||||||
}) => {
|
}) => {
|
||||||
const onMenuClick = a => {
|
const onMenuClick = a => {
|
||||||
if (a.key === NOTIFY_KEY) {
|
if (a.key === NOTIFY_KEY) {
|
||||||
@@ -72,8 +75,15 @@ export const ActionButtonMenu: FC<ActionButtonMenuProps> = ({
|
|||||||
|
|
||||||
const menu = <Menu items={items} onClick={onMenuClick} />;
|
const menu = <Menu items={items} onClick={onMenuClick} />;
|
||||||
|
|
||||||
|
const dropdownClasses = classNames([styles.menu, className]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropdown overlay={menu} placement="bottomRight" trigger={['click']} className={styles.menu}>
|
<Dropdown
|
||||||
|
overlay={menu}
|
||||||
|
placement="bottomRight"
|
||||||
|
trigger={['click']}
|
||||||
|
className={dropdownClasses}
|
||||||
|
>
|
||||||
<div className={styles.buttonWrap}>
|
<div className={styles.buttonWrap}>
|
||||||
<Button
|
<Button
|
||||||
type="default"
|
type="default"
|
||||||
|
|||||||
11
web/components/layouts/Main/Main.module.scss
Normal file
11
web/components/layouts/Main/Main.module.scss
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
@import '../../../styles/mixins.scss';
|
||||||
|
|
||||||
|
.layout {
|
||||||
|
@include screen(tablet) {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,29 +3,36 @@
|
|||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import { FC, useEffect, useRef } from 'react';
|
import { FC, useEffect, useRef } from 'react';
|
||||||
import { useLockBodyScroll } from 'react-use';
|
import { Layout } from 'antd';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import {
|
import {
|
||||||
ClientConfigStore,
|
ClientConfigStore,
|
||||||
isChatAvailableSelector,
|
isChatAvailableSelector,
|
||||||
clientConfigStateAtom,
|
clientConfigStateAtom,
|
||||||
fatalErrorStateAtom,
|
fatalErrorStateAtom,
|
||||||
} from '../stores/ClientConfigStore';
|
} from '../../stores/ClientConfigStore';
|
||||||
import { Header } from '../ui/Header/Header';
|
import { Content } from '../../ui/Content/Content';
|
||||||
import { ClientConfig } from '../../interfaces/client-config.model';
|
import { Header } from '../../ui/Header/Header';
|
||||||
import { DisplayableError } from '../../types/displayable-error';
|
import { ClientConfig } from '../../../interfaces/client-config.model';
|
||||||
import setupNoLinkReferrer from '../../utils/no-link-referrer';
|
import { DisplayableError } from '../../../types/displayable-error';
|
||||||
import { ServerRenderedHydration } from '../ServerRendered/ServerRenderedHydration';
|
import setupNoLinkReferrer from '../../../utils/no-link-referrer';
|
||||||
import { Content } from '../ui/Content/Content';
|
import { TitleNotifier } from '../../TitleNotifier/TitleNotifier';
|
||||||
import { TitleNotifier } from '../TitleNotifier/TitleNotifier';
|
import { ServerRenderedHydration } from '../../ServerRendered/ServerRenderedHydration';
|
||||||
import { PushNotificationServiceWorker } from '../workers/PushNotificationServiceWorker/PushNotificationServiceWorker';
|
import { Theme } from '../../theme/Theme';
|
||||||
import { Theme } from '../theme/Theme';
|
import styles from './Main.module.scss';
|
||||||
|
import { PushNotificationServiceWorker } from '../../workers/PushNotificationServiceWorker/PushNotificationServiceWorker';
|
||||||
|
|
||||||
|
const lockBodyStyle = `
|
||||||
|
body {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
// Lazy loaded components
|
// Lazy loaded components
|
||||||
|
|
||||||
const FatalErrorStateModal = dynamic(
|
const FatalErrorStateModal = dynamic(
|
||||||
() =>
|
() =>
|
||||||
import('../modals/FatalErrorStateModal/FatalErrorStateModal').then(
|
import('../../modals/FatalErrorStateModal/FatalErrorStateModal').then(
|
||||||
mod => mod.FatalErrorStateModal,
|
mod => mod.FatalErrorStateModal,
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
@@ -42,8 +49,6 @@ export const Main: FC = () => {
|
|||||||
const layoutRef = useRef<HTMLDivElement>(null);
|
const layoutRef = useRef<HTMLDivElement>(null);
|
||||||
const { chatDisabled } = clientConfig;
|
const { chatDisabled } = clientConfig;
|
||||||
|
|
||||||
useLockBodyScroll(true);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setupNoLinkReferrer(layoutRef.current);
|
setupNoLinkReferrer(layoutRef.current);
|
||||||
}, []);
|
}, []);
|
||||||
@@ -79,7 +84,10 @@ export const Main: FC = () => {
|
|||||||
<meta name="msapplication-TileImage" content="/img/favicon/ms-icon-144x144.png" />
|
<meta name="msapplication-TileImage" content="/img/favicon/ms-icon-144x144.png" />
|
||||||
<meta name="theme-color" content="#ffffff" />
|
<meta name="theme-color" content="#ffffff" />
|
||||||
|
|
||||||
<style>{customStyles}</style>
|
<style>
|
||||||
|
{customStyles}
|
||||||
|
{lockBodyStyle}
|
||||||
|
</style>
|
||||||
<base target="_blank" />
|
<base target="_blank" />
|
||||||
</Head>
|
</Head>
|
||||||
|
|
||||||
@@ -125,13 +133,13 @@ export const Main: FC = () => {
|
|||||||
<PushNotificationServiceWorker />
|
<PushNotificationServiceWorker />
|
||||||
<TitleNotifier name={name} />
|
<TitleNotifier name={name} />
|
||||||
<Theme />
|
<Theme />
|
||||||
<div ref={layoutRef} style={{ minHeight: '100vh' }}>
|
<Layout ref={layoutRef} className={styles.layout}>
|
||||||
<Header name={title || name} chatAvailable={isChatAvailable} chatDisabled={chatDisabled} />
|
<Header name={title || name} chatAvailable={isChatAvailable} chatDisabled={chatDisabled} />
|
||||||
<Content />
|
<Content />
|
||||||
{fatalError && (
|
{fatalError && (
|
||||||
<FatalErrorStateModal title={fatalError.title} message={fatalError.message} />
|
<FatalErrorStateModal title={fatalError.title} message={fatalError.message} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</Layout>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -42,13 +42,8 @@
|
|||||||
.lowerSectionMobile {
|
.lowerSectionMobile {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
flex-shrink: 0;
|
||||||
padding: 0.3em;
|
padding: 0.3em;
|
||||||
// Enable overflow scrolling within a tab (∩`-´)⊃━☆゚.*・。゚
|
|
||||||
height: 100vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs {
|
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,3 +62,45 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
grid-template-rows: 1fr auto;
|
grid-template-rows: 1fr auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.replacementBar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: start;
|
||||||
|
|
||||||
|
@include screen(tablet) {
|
||||||
|
height: var(--replacement-bar-height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.defaultTabBar {
|
||||||
|
width: 85%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.defaultTabBar,
|
||||||
|
.actionButtonMenu {
|
||||||
|
@include screen(tablet) {
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
padding-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
@include screen(tablet) {
|
||||||
|
position: relative;
|
||||||
|
> :global(.ant-tabs-content-holder) {
|
||||||
|
position: absolute;
|
||||||
|
height: calc(100% - var(--replacement-bar-height));
|
||||||
|
top: var(--replacement-bar-height);
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
> :global(.ant-tabs-content-holder .ant-tabs-content) {
|
||||||
|
padding-top: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -188,9 +188,10 @@ const MobileContent = ({
|
|||||||
];
|
];
|
||||||
|
|
||||||
const replacementTabBar = (props, DefaultTabBar) => (
|
const replacementTabBar = (props, DefaultTabBar) => (
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'start' }}>
|
<div className={styles.replacementBar}>
|
||||||
<DefaultTabBar {...props} style={{ width: '85%' }} />
|
<DefaultTabBar {...props} className={styles.defaultTabBar} />
|
||||||
<ActionButtonMenu
|
<ActionButtonMenu
|
||||||
|
className={styles.actionButtonMenu}
|
||||||
showFollowItem={supportFediverseFeatures}
|
showFollowItem={supportFediverseFeatures}
|
||||||
showNotifyItem={supportsBrowserNotifications}
|
showNotifyItem={supportsBrowserNotifications}
|
||||||
actions={actions}
|
actions={actions}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ReactElement } from 'react';
|
import { ReactElement } from 'react';
|
||||||
import { Main } from '../components/layouts/Main';
|
import { Main } from '../components/layouts/Main/Main';
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return <Main />;
|
return <Main />;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
--header-height: 5.375rem; // needed for making main content scrollable;
|
--header-height: 5.375rem; // needed for making main content scrollable;
|
||||||
--footer-height: 2.5rem; // needed for making main content scrollable;
|
--footer-height: 2.5rem; // needed for making main content scrollable;
|
||||||
--content-height: calc(100vh - var(--header-height));
|
--content-height: calc(100vh - var(--header-height));
|
||||||
|
--replacement-bar-height: 46px; // needed for making main content scrollable on mobile;
|
||||||
}
|
}
|
||||||
|
|
||||||
::selection {
|
::selection {
|
||||||
|
|||||||
Reference in New Issue
Block a user