[NEW] Custom scroll (#19701)

Co-authored-by: Guilherme Gazzo <guilherme@gazzo.xyz>
Co-authored-by: Guilherme Gazzo <guilhermegazzo@gmail.com>
pull/19721/head
Martin Schoeler 6 years ago committed by GitHub
parent 451dc84790
commit 7149b283ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      app/ui-utils/client/lib/ReactionListContent.js
  2. 2
      client/channel/Discussions/ContextualBar/List.js
  3. 2
      client/channel/Threads/ContextualBar/List.js
  4. 11
      client/components/GenericTable/index.js
  5. 10
      client/components/basic/Page.tsx
  6. 21
      client/components/basic/ScrollableContentWrapper.tsx
  7. 8
      client/components/basic/Sidebar.js
  8. 27
      client/hooks/useDir.js
  9. 2
      client/sidebar/RoomList.js
  10. 2
      client/sidebar/search/SearchList.js
  11. 7
      client/views/setupWizard/SetupWizardPage.js
  12. 7
      client/views/setupWizard/SideBar.js
  13. 71
      package-lock.json
  14. 5
      package.json

@ -1,18 +1,19 @@
import React from 'react';
import { Box, Tag, Modal, ButtonGroup, Button, Scrollable } from '@rocket.chat/fuselage';
import { Box, Tag, Modal, ButtonGroup, Button } from '@rocket.chat/fuselage';
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
import { useTranslation } from '../../../../client/contexts/TranslationContext';
import { useSetting } from '../../../../client/contexts/SettingsContext';
import { useSession } from '../../../../client/contexts/SessionContext';
import Emoji from '../../../../client/components/basic/Emoji';
import ScrollableContentWrapper from '../../../../client/components/basic/ScrollableContentWrapper';
import { openUserCard } from '../../../ui/client/lib/UserCard';
import { openProfileTabOrOpenDM } from '../../../ui/client/views/app/room';
export function Reactions({ reactions, roomInstance, onClose }) {
const useRealName = useSetting('UI_Use_Real_Name');
return <Scrollable>
return <ScrollableContentWrapper>
<Box>
{Object.entries(reactions).map(([reaction, { names = [], usernames }]) => <Box key={reaction}>
<Box display='flex' flexWrap='wrap' overflowX='hidden' mb='x8'>
@ -29,7 +30,7 @@ export function Reactions({ reactions, roomInstance, onClose }) {
</Box>
</Box>)}
</Box>
</Scrollable>;
</ScrollableContentWrapper>;
}
export function Username({ username, displayName, roomInstance, onClose }) {

@ -21,6 +21,7 @@ import { useUserRoom } from '../../hooks/useUserRoom';
import { useSetting } from '../../../contexts/SettingsContext';
import DiscussionListMessage from './components/Message';
import { clickableItem } from '../../helpers/clickableItem';
import ScrollableContentWrapper from '../../../components/basic/ScrollableContentWrapper';
function mapProps(WrappedComponent) {
return ({ msg, username, tcount, ts, ...props }) => <WrappedComponent replies={tcount} username={username} msg={msg} ts={ts} {...props}/>;
@ -219,6 +220,7 @@ export function DiscussionList({ total = 10, discussions = [], loadMoreItems, lo
loadMoreItems={ loading ? () => {} : loadMoreItems}
>
{({ onItemsRendered, ref }) => (<List
outerElementType={ScrollableContentWrapper}
height={blockSize}
width={inlineSize}
itemCount={total}

@ -19,6 +19,7 @@ import { MessageSkeleton } from '../../components/Message';
import ThreadListMessage from './components/Message';
import { getConfig } from '../../../../app/ui-utils/client/config';
import { useEndpoint } from '../../../contexts/ServerContext';
import ScrollableContentWrapper from '../../../components/basic/ScrollableContentWrapper';
function mapProps(WrappedComponent) {
return ({ msg, username, replies, tcount, ts, ...props }) => <WrappedComponent replies={tcount} participants={replies.length} username={username} msg={msg} ts={ts} {...props}/>;
@ -261,6 +262,7 @@ export function ThreadList({ total = 10, threads = [], room, unread = [], unread
loadMoreItems={ loading ? () => {} : loadMoreItems}
>
{({ onItemsRendered, ref }) => (<List
outerElementType={ScrollableContentWrapper}
height={blockSize}
width={inlineSize}
itemCount={total}

@ -1,4 +1,4 @@
import { Box, Pagination, Table, Tile, Scrollable } from '@rocket.chat/fuselage';
import { Box, Pagination, Table, Tile } from '@rocket.chat/fuselage';
import { useDebouncedValue } from '@rocket.chat/fuselage-hooks';
import React, { useState, useEffect, useCallback, forwardRef } from 'react';
import flattenChildren from 'react-keyed-flatten-children';
@ -6,6 +6,7 @@ import flattenChildren from 'react-keyed-flatten-children';
import { useTranslation } from '../../contexts/TranslationContext';
import HeaderCell from './HeaderCell';
import LoadingRow from './LoadingRow';
import ScrollableContentWrapper from '../basic/ScrollableContentWrapper';
const GenericTable = ({
children,
@ -49,8 +50,8 @@ const GenericTable = ({
{t('No_data_found')}
</Tile>
: <>
<Scrollable>
<Box mi='neg-x24' pi='x24' flexGrow={1} ref={ref}>
<Box mi='neg-x24' pi='x24' flexShrink={1} flexGrow={1} ref={ref} overflow='hidden'>
<ScrollableContentWrapper>
<Table fixed={fixed} sticky>
{header && <Table.Head>
<Table.Row>
@ -66,8 +67,8 @@ const GenericTable = ({
{children && (results ? results.map(children) : <Loading />)}
</Table.Body>
</Table>
</Box>
</Scrollable>
</ScrollableContentWrapper>
</Box>
<Pagination
divider
current={current}

@ -1,7 +1,8 @@
import { Box, Scrollable, ScrollableProps } from '@rocket.chat/fuselage';
import { Box, ScrollableProps } from '@rocket.chat/fuselage';
import { useMediaQuery } from '@rocket.chat/fuselage-hooks';
import React, { createContext, useContext, useState, FC, Dispatch, SetStateAction } from 'react';
import ScrollableContentWrapper from './ScrollableContentWrapper';
import { useSidebar } from '../../contexts/SidebarContext';
import BurgerMenuButton from './burger/BurgerMenuButton';
import { useSession } from '../../contexts/SessionContext';
@ -84,10 +85,9 @@ type PageScrollableContentProps = {
onScrollContent?: ScrollableProps['onScrollContent'];
};
const PageScrollableContent: FC<PageScrollableContentProps> = ({ onScrollContent, ...props }) =>
<Scrollable onScrollContent={onScrollContent} >
<Box p='x16' display='flex' flexDirection='column' flexGrow={1} {...props} />
</Scrollable>;
const PageScrollableContent: FC<PageScrollableContentProps> = React.forwardRef(({ onScrollContent, ...props }, ref) => <Box display='flex' flexShrink={1} flexGrow={1} overflow='hidden'>
<ScrollableContentWrapper onScroll={onScrollContent} ref={ref}><Box p='x16' display='flex' flexDirection='column' flexGrow={1} {...props} /></ScrollableContentWrapper>
</Box>);
const PageScrollableContentWithShadow: FC<PageScrollableContentProps> = ({ onScrollContent, ...props }) => {
const [, setBorder] = useContext(PageContext);

@ -0,0 +1,21 @@
import React, { FC } from 'react';
import SimpleBar from 'simplebar-react';
import 'simplebar/src/simplebar.css';
import { useDir } from '../../hooks/useDir';
const style = {
maxHeight: '100%', flexGrow: 1,
};
type CustomScrollbarsProps = {
onScroll?: Function;
ref: React.Ref<unknown>;
}
const ScrollableContentWrapper: FC<CustomScrollbarsProps> = React.memo(React.forwardRef(({ onScroll, children }, ref) => {
const dir = useDir();
return <SimpleBar data-simplebar-direction={dir} direction={dir} style={style} scrollableNodeProps={{ ref, onScroll }} children={children}/>;
}));
export default ScrollableContentWrapper;

@ -1,19 +1,21 @@
import React, { useMemo } from 'react';
import { css } from '@rocket.chat/css-in-js';
import { Box, Scrollable, Icon, ActionButton } from '@rocket.chat/fuselage';
import { Box, Icon, ActionButton } from '@rocket.chat/fuselage';
import { useTranslation } from '../../contexts/TranslationContext';
import { useRoutePath } from '../../contexts/RouterContext';
import ScrollableContentWrapper from './ScrollableContentWrapper';
const Sidebar = ({ children, ...props }) => <Box display='flex' flexDirection='column' h='full' {...props}>
{children}
</Box>;
const Content = ({ children, ...props }) => <Scrollable {...props}>
const Content = ({ children, ...props }) => <ScrollableContentWrapper {...props}>
<Box display='flex' flexDirection='column' h='full'>
{children}
</Box>
</Scrollable>;
</ScrollableContentWrapper>;
const Header = ({ title, onClose, children = undefined, ...props }) => <Box is='header' display='flex' flexDirection='column' pb='x16' {...props}>
{(title || onClose) && <Box display='flex' flexDirection='row' alignItems='center' pi='x24' justifyContent='space-between' flexGrow={1}>

@ -0,0 +1,27 @@
import { useEffect, useState } from 'react';
import { Emitter } from '@rocket.chat/emitter';
const ee = new Emitter();
const getDir = () => document.documentElement.getAttribute('dir') || 'ltr';
const config = { attributes: true, childList: false, subtree: false };
const callback = function(mutationsList) {
for (const mutation of mutationsList) {
if (mutation.type === 'attributes' && mutation.attributeName === 'dir') {
ee.emit('change', getDir());
}
}
};
const observer = new MutationObserver(callback);
observer.observe(document.documentElement, config);
export const useDir = () => {
const [dir, setDir] = useState(getDir);
useEffect(() => {
ee.on('change', setDir);
return () => ee.off('change', setDir);
}, []);
return dir;
};

@ -19,6 +19,7 @@ import { useShortcutOpenMenu } from './hooks/useShortcutOpenMenu';
import { useAvatarTemplate } from './hooks/useAvatarTemplate';
import { useRoomList } from './hooks/useRoomList';
import { useSidebarPaletteColor } from './hooks/useSidebarPaletteColor';
import ScrollableContentWrapper from '../components/basic/ScrollableContentWrapper';
const sections = {
Omnichannel,
@ -130,6 +131,7 @@ export default () => {
return <Box h='full' w='full' ref={ref}>
<List
outerElementType={ScrollableContentWrapper}
height={blockSize}
itemCount={roomsList.length}
itemSize={(index) => (typeof roomsList[index] === 'string' ? (sections[roomsList[index]] && sections[roomsList[index]].size) || 40 : itemSize)}

@ -16,6 +16,7 @@ import { useUserPreference, useUserSubscriptions } from '../../contexts/UserCont
import { itemSizeMap, SideBarItemTemplateWithData } from '../RoomList';
import { useTemplateByViewMode } from '../hooks/useTemplateByViewMode';
import { useAvatarTemplate } from '../hooks/useAvatarTemplate';
import ScrollableContentWrapper from '../../components/basic/ScrollableContentWrapper';
const createItemData = memoize((items, t, SideBarItemTemplate, AvatarTemplate, useRealName, extended) => ({
items,
@ -274,6 +275,7 @@ const SearchList = React.forwardRef(function SearchList({ onClose }, ref) {
</Sidebar.TopBar.Section>
<Box aria-expanded='true' role='listbox' id={listId} tabIndex={-1} flexShrink={1} h='full' w='full' ref={boxRef} data-qa='sidebar-search-result' onClick={onClose} aria-busy={status !== AsyncState.DONE}>
<List
outerElementType={ScrollableContentWrapper}
height={blockSize}
itemCount={items?.length}
itemSize={itemSize}

@ -1,10 +1,11 @@
import { Box, Margins, Scrollable, Tile } from '@rocket.chat/fuselage';
import { Box, Margins, Tile } from '@rocket.chat/fuselage';
import { useMediaQuery } from '@rocket.chat/fuselage-hooks';
import React from 'react';
import { useTranslation } from '../../contexts/TranslationContext';
import { useWipeInitialPageLoading } from '../../hooks/useWipeInitialPageLoading';
import ConnectionStatusAlert from '../../components/connectionStatus/ConnectionStatusAlert';
import ScrollableContentWrapper from '../../components/basic/ScrollableContentWrapper';
import { finalStep } from './SetupWizardState';
import FinalStep from './steps/FinalStep';
import SideBar from './SideBar';
@ -59,7 +60,7 @@ function SetupWizardPage({ currentStep = 1 }) {
display='flex'
flexDirection='column'
>
<Scrollable>
<ScrollableContentWrapper>
<Margins all='x16'>
<Tile is='section' flexGrow={1} flexShrink={1}>
<AdminUserInformationStep step={1} title={t('Admin_Info')} active={currentStep === 1} />
@ -68,7 +69,7 @@ function SetupWizardPage({ currentStep = 1 }) {
<RegisterServerStep step={4} title={t('Register_Server')} active={currentStep === 4} />
</Tile>
</Margins>
</Scrollable>
</ScrollableContentWrapper>
</Box>
</>}
</Box>

@ -1,10 +1,11 @@
import { Box, Margins, Scrollable } from '@rocket.chat/fuselage';
import { Box, Margins } from '@rocket.chat/fuselage';
import { useMediaQuery } from '@rocket.chat/fuselage-hooks';
import React from 'react';
import { useTranslation } from '../../contexts/TranslationContext';
import Logo from '../../components/basic/Logo';
import './SideBar.css';
import ScrollableContentWrapper from '../../components/basic/ScrollableContentWrapper';
function SideBar({
logoSrc = 'images/logo/logo.svg',
@ -60,7 +61,7 @@ function SideBar({
</Box>
</Box>
{!small && <Scrollable>
{!small && <ScrollableContentWrapper>
<Box
flexGrow={1}
marginBlockEnd='x16'
@ -96,7 +97,7 @@ function SideBar({
)}
</Box>
</Box>
</Scrollable>}
</ScrollableContentWrapper>}
</Box>;
}

71
package-lock.json generated

@ -5064,9 +5064,9 @@
}
},
"@rocket.chat/fuselage": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/@rocket.chat/fuselage/-/fuselage-0.19.0.tgz",
"integrity": "sha512-zZaXeylSLuinH7Cutc7UleRZDTHsTp6bYYNmwamloHt8Z6KlHIUL2wgmZntkRsJgJE6BSpdQowxDzEVEK20GHw==",
"version": "0.6.3-dev.141",
"resolved": "https://registry.npmjs.org/@rocket.chat/fuselage/-/fuselage-0.6.3-dev.141.tgz",
"integrity": "sha512-OQB7SFtjYvWx+HbuTYSyJxMbtxYDoRlXhRbtSY5csrprh1MXv0ErbBiezgBwNYm64Ch2G3zKRCPHsRrfApCokg==",
"requires": {
"@rocket.chat/css-in-js": "^0.19.0",
"@rocket.chat/fuselage-tokens": "^0.19.0",
@ -5101,9 +5101,9 @@
"integrity": "sha512-y/201Fdagj01++tnFhiwY7vueBERSoD9MrY2/1rDu/qqqstRFE28wxuEeBlp53p4oHi/a7ZpKhOPfGv1R5Kpnw=="
},
"@rocket.chat/fuselage-ui-kit": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-ui-kit/-/fuselage-ui-kit-0.19.0.tgz",
"integrity": "sha512-SX1rns6XWnI8vC5G4NPqcED5GFpyOxDSHEfKY2QUKzN5H8232QI1UXc1NJ74FXVXU1RTV+OqcNXarM6DydHcZw==",
"version": "0.6.3-dev.141",
"resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-ui-kit/-/fuselage-ui-kit-0.6.3-dev.141.tgz",
"integrity": "sha512-sZBahrIwkK57OlsW+5muhEHXm1+pYdd1ELXUGtlBrvXU5icOkBwCbMy0Xb55bxoKe7rLSO9oBwRNmTpTo3SiCw==",
"requires": {
"@rocket.chat/fuselage-polyfills": "^0.19.0"
}
@ -5625,6 +5625,30 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
"dev": true
},
"simplebar": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/simplebar/-/simplebar-4.2.3.tgz",
"integrity": "sha512-9no0pK7/1y+8/oTF3sy/+kx0PjQ3uk4cYwld5F1CJGk2gx+prRyUq8GRfvcVLq5niYWSozZdX73a2wIr1o9l/g==",
"dev": true,
"requires": {
"can-use-dom": "^0.1.0",
"core-js": "^3.0.1",
"lodash.debounce": "^4.0.8",
"lodash.memoize": "^4.1.2",
"lodash.throttle": "^4.1.1",
"resize-observer-polyfill": "^1.5.1"
}
},
"simplebar-react": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/simplebar-react/-/simplebar-react-1.2.3.tgz",
"integrity": "sha512-1EOWJzFC7eqHUp1igD1/tb8GBv5aPQA5ZMvpeDnVkpNJ3jAuvmrL2kir3HuijlxhG7njvw9ssxjjBa89E5DrJg==",
"dev": true,
"requires": {
"prop-types": "^15.6.1",
"simplebar": "^4.2.3"
}
}
}
},
@ -12850,8 +12874,7 @@
"can-use-dom": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/can-use-dom/-/can-use-dom-0.1.0.tgz",
"integrity": "sha1-IsxKNKCrxDlQ9CxkEQJKP2NmtFo=",
"dev": true
"integrity": "sha1-IsxKNKCrxDlQ9CxkEQJKP2NmtFo="
},
"caniuse-lite": {
"version": "1.0.30000989",
@ -22898,8 +22921,7 @@
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
"dev": true
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
},
"lodash.defaults": {
"version": "4.2.0",
@ -22979,8 +23001,7 @@
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
"integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
"dev": true
"integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4="
},
"lodash.merge": {
"version": "4.6.2",
@ -23031,8 +23052,7 @@
"lodash.throttle": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=",
"dev": true
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
},
"lodash.trim": {
"version": "4.5.1",
@ -30785,10 +30805,9 @@
}
},
"simplebar": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/simplebar/-/simplebar-4.2.3.tgz",
"integrity": "sha512-9no0pK7/1y+8/oTF3sy/+kx0PjQ3uk4cYwld5F1CJGk2gx+prRyUq8GRfvcVLq5niYWSozZdX73a2wIr1o9l/g==",
"dev": true,
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/simplebar/-/simplebar-5.3.0.tgz",
"integrity": "sha512-LgrGdIWpwHLLlI9HqfnGql62H/iZlF0KDZ7w3ZNbd2ZLwh9NKsODLHPzQgUlqQ8aZe7Y6/1xJMXK1PU5e810+w==",
"requires": {
"can-use-dom": "^0.1.0",
"core-js": "^3.0.1",
@ -30799,21 +30818,19 @@
},
"dependencies": {
"core-js": {
"version": "3.6.5",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz",
"integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==",
"dev": true
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.0.tgz",
"integrity": "sha512-W2VYNB0nwQQE7tKS7HzXd7r2y/y2SVJl4ga6oH/dnaLFzM0o2lB2P3zCkWj5Wc/zyMYjtgd5Hmhk0ObkQFZOIA=="
}
}
},
"simplebar-react": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/simplebar-react/-/simplebar-react-1.2.3.tgz",
"integrity": "sha512-1EOWJzFC7eqHUp1igD1/tb8GBv5aPQA5ZMvpeDnVkpNJ3jAuvmrL2kir3HuijlxhG7njvw9ssxjjBa89E5DrJg==",
"dev": true,
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/simplebar-react/-/simplebar-react-2.3.0.tgz",
"integrity": "sha512-ZhWEe4UkshSJ9xPG1F/W58UMJdA3fzgtXGrYsya3hxdMbIYoKUKEhdBsqdMoeaLGyn/5dbMPqDLinkLeg0W0cQ==",
"requires": {
"prop-types": "^15.6.1",
"simplebar": "^4.2.3"
"simplebar": "^5.3.0"
}
},
"slash": {

@ -139,10 +139,10 @@
"@rocket.chat/apps-engine": "1.20.0",
"@rocket.chat/css-in-js": "^0.19.0",
"@rocket.chat/emitter": "^0.19.0",
"@rocket.chat/fuselage": "^0.19.0",
"@rocket.chat/fuselage": "^0.6.3-dev.141",
"@rocket.chat/fuselage-hooks": "^0.19.0",
"@rocket.chat/fuselage-polyfills": "^0.19.0",
"@rocket.chat/fuselage-ui-kit": "^0.19.0",
"@rocket.chat/fuselage-ui-kit": "^0.6.3-dev.141",
"@rocket.chat/icons": "^0.19.0",
"@rocket.chat/mp3-encoder": "^0.19.0",
"@rocket.chat/ui-kit": "^0.19.0",
@ -244,6 +244,7 @@
"redis": "^2.8.0",
"semver": "^5.7.1",
"sharp": "^0.22.1",
"simplebar-react": "^2.3.0",
"speakeasy": "^2.0.0",
"stream-buffers": "^3.0.2",
"string-strip-html": "^4.5.1",

Loading…
Cancel
Save