Skip to content
This repository has been archived by the owner on Feb 1, 2024. It is now read-only.

Commit

Permalink
Merge pull request #2222 from teamleadercrm/FRAF-704-Scroll-shadow-on…
Browse files Browse the repository at this point in the history
…-dialogs

Added scroll shadow at the bottom of dialog if scroll bar is displayed
  • Loading branch information
qubis741 authored Jul 4, 2022
2 parents 830b911 + a188f2d commit 1d28077
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

### Added

- `Dialog`: scroll shadow at the bottom of dialog if scroll bar is displayed ([@qubis741](https://github.com/qubis741)) in [#2222](https://github.com/teamleadercrm/ui/pull/2222))

### Changed

- `Pagination`: always show arrows ([@qubis741](https://github.com/qubis741)) in [#2221](https://github.com/teamleadercrm/ui/pull/2221))
Expand Down
14 changes: 11 additions & 3 deletions src/components/dialog/Body.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { ReactNode, forwardRef, RefObject } from 'react';
import React, { forwardRef, ReactNode, RefObject, UIEventHandler } from 'react';
import { GenericComponent } from '../../@types/types';

import { Box } from '../../index';
Expand All @@ -9,16 +9,24 @@ export interface BodyProps extends Omit<BoxProps, 'ref'> {
children?: ReactNode;
/** If true, the content will be scrollable when it exceeds the available height. */
scrollable?: boolean;
handleShowScrollShadow: (show: boolean) => void;
}

const Body: GenericComponent<BodyProps> = forwardRef<HTMLElement, BodyProps>(
({ scrollable, children, ...rest }, ref) => {
({ scrollable, children, handleShowScrollShadow, ...rest }, ref) => {
if (!scrollable) {
return <div ref={ref as RefObject<HTMLDivElement>}>{children}</div>;
}

const handleWrapperScroll: UIEventHandler<HTMLElement> = (event) => {
if (!event.target) {
return;
}
const element = event.target as HTMLDivElement;
handleShowScrollShadow(element.scrollHeight - element.scrollTop === element.clientHeight);
};
return (
<Box display="flex" flexDirection="column" overflowY="auto" {...rest} ref={ref}>
<Box display="flex" flexDirection="column" overflowY="auto" {...rest} ref={ref} onScroll={handleWrapperScroll}>
{children}
</Box>
);
Expand Down
30 changes: 27 additions & 3 deletions src/components/dialog/Dialog.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { IconDragMediumFilled } from '@teamleader/ui-icons';
import cx from 'classnames';
import omit from 'lodash.omit';
import React, { ReactNode, useRef } from 'react';
import React, { ReactNode, useCallback, useEffect, useRef, useState } from 'react';
import { useResizeDetector } from 'react-resize-detector';
import { GenericComponent } from '../../@types/types';
import { Button, ButtonGroup, DialogBase, Heading3 } from '../../index';
import { DialogBaseProps } from './DialogBase';
Expand Down Expand Up @@ -52,6 +53,25 @@ const Dialog: GenericComponent<DialogProps> = ({
}) => {
const bodyRef = useRef<HTMLElement>(null);
const dragHandleRef = useRef<HTMLDivElement>(null);
const [showScrollShadow, setShowScrollShadow] = useState(true);
const [reachedScrollEnd, setReachedScrollEnd] = useState(false);

const handleScrollShadow = useCallback(() => {
const currentRef = bodyRef.current;
if (currentRef) {
setShowScrollShadow(currentRef.scrollHeight > currentRef.clientHeight);
}
}, [bodyRef]);
useEffect(() => {
handleScrollShadow();
}, [bodyRef, otherProps.active]);

useResizeDetector({
refreshMode: 'throttle',
refreshRate: 250,
onResize: handleScrollShadow,
targetRef: bodyRef,
});

const getHeader = () => {
const dragIcon = (
Expand All @@ -69,7 +89,11 @@ const Dialog: GenericComponent<DialogProps> = ({

const getFooter = () => {
return (
<DialogBase.Footer display="flex" justifyContent={leftAction ? 'space-between' : 'flex-end'}>
<DialogBase.Footer
display="flex"
justifyContent={leftAction ? 'space-between' : 'flex-end'}
className={cx({ [theme['scroll-shadow']]: !reachedScrollEnd && showScrollShadow })}
>
{leftAction && <Button {...leftAction} />}
<ButtonGroup justifyContent="flex-end">
{tertiaryAction && <Button {...tertiaryAction} level="link" />}
Expand Down Expand Up @@ -101,7 +125,7 @@ const Dialog: GenericComponent<DialogProps> = ({
onSubmit={onSubmit}
>
{title && getHeader()}
<DialogBase.Body ref={bodyRef} scrollable={scrollable}>
<DialogBase.Body ref={bodyRef} scrollable={scrollable} handleShowScrollShadow={setReachedScrollEnd}>
{children}
</DialogBase.Body>
{getFooter()}
Expand Down
5 changes: 5 additions & 0 deletions src/components/dialog/theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,8 @@
.close-icon {
margin-left: auto;
}

.scroll-shadow {
box-shadow: 0px 0px 1px rgba(130, 130, 140, 0.09), 0px 0px 0px rgba(130, 130, 140, 0.09),
0px -4px 8px rgba(130, 130, 140, 0.09);
}

0 comments on commit 1d28077

Please sign in to comment.