diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2022-09-09 12:06:54 +0200 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2022-09-15 17:24:53 +0200 |
| commit | 5b0c56c4c703596bc604671387ccdbd10f13882e (patch) | |
| tree | 26d7821f14540ecc83cec9e1049bae08d10bc370 /gui | |
| parent | f7ebb3cd624440714ccc0138b83707d5303732c4 (diff) | |
| download | mullvadvpn-5b0c56c4c703596bc604671387ccdbd10f13882e.tar.xz mullvadvpn-5b0c56c4c703596bc604671387ccdbd10f13882e.zip | |
Simplify notification banner implementation
Diffstat (limited to 'gui')
| -rw-r--r-- | gui/src/renderer/components/NotificationArea.tsx | 4 | ||||
| -rw-r--r-- | gui/src/renderer/components/NotificationBanner.tsx | 35 |
2 files changed, 10 insertions, 29 deletions
diff --git a/gui/src/renderer/components/NotificationArea.tsx b/gui/src/renderer/components/NotificationArea.tsx index 4d59109ea8..acd1aaf2df 100644 --- a/gui/src/renderer/components/NotificationArea.tsx +++ b/gui/src/renderer/components/NotificationArea.tsx @@ -73,7 +73,7 @@ export default function NotificationArea(props: IProps) { if (notification) { return ( - <NotificationBanner className={props.className} visible> + <NotificationBanner className={props.className}> <NotificationIndicator type={notification.indicator} /> <NotificationContent role="status" aria-live="polite"> <NotificationTitle>{notification.title}</NotificationTitle> @@ -89,7 +89,7 @@ export default function NotificationArea(props: IProps) { } } - return <NotificationBanner className={props.className} visible={false} aria-hidden={true} />; + return <NotificationBanner className={props.className} aria-hidden={true} />; } interface INotificationActionWrapperProps { diff --git a/gui/src/renderer/components/NotificationBanner.tsx b/gui/src/renderer/components/NotificationBanner.tsx index e26b42ea26..82cf92e129 100644 --- a/gui/src/renderer/components/NotificationBanner.tsx +++ b/gui/src/renderer/components/NotificationBanner.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'; +import React, { useEffect, useLayoutEffect, useRef, useState } from 'react'; import styled from 'styled-components'; import { colors } from '../../config.json'; @@ -98,20 +98,10 @@ export const NotificationIndicator = styled.div((props: INotificationIndicatorPr interface ICollapsibleProps { alignBottom: boolean; - contentHeight?: number; - collapsibleHeight?: number; + height?: number; } -const TRANSITION_DURATION = 350; -// 52px is the height of the banner when the notification contains a title and subtitle which are -// one line each. -const TRANSITION_BASE_DISTANCE = 52; - const Collapsible = styled.div({}, (props: ICollapsibleProps) => { - // Calculate the transition duration based on travel distance. - const distance = Math.abs((props.collapsibleHeight ?? 0) - (props.contentHeight ?? 0)); - const duration = Math.ceil(TRANSITION_DURATION * (distance / TRANSITION_BASE_DISTANCE)); - return { display: 'flex', flexDirection: 'column', @@ -119,8 +109,8 @@ const Collapsible = styled.div({}, (props: ICollapsibleProps) => { backgroundColor: 'rgba(25, 38, 56, 0.95)', overflow: 'hidden', // Using auto as the initial value prevents transition if a notification is visible on mount. - height: props.contentHeight === undefined ? 'auto' : `${props.contentHeight}px`, - transition: `height ${duration}ms ease-in-out`, + height: props.height === undefined ? 'auto' : `${props.height}px`, + transition: 'height 250ms ease-in-out', }; }); @@ -134,7 +124,6 @@ const Content = styled.section({ interface INotificationBannerProps { children?: React.ReactNode; // Array<NotificationContent | NotificationActions>, className?: string; - visible: boolean; } export function NotificationBanner(props: INotificationBannerProps) { @@ -142,7 +131,6 @@ export function NotificationBanner(props: INotificationBannerProps) { const [alignBottom, setAlignBottom] = useState(false); const contentRef = useRef() as React.RefObject<HTMLDivElement>; - const collapsibleRef = useRef() as React.RefObject<HTMLDivElement>; // Save last non-undefined children to be able to show them during the hide-transition. const prevChildren = useRef<React.ReactNode>(); @@ -150,10 +138,9 @@ export function NotificationBanner(props: INotificationBannerProps) { prevChildren.current = props.children ?? prevChildren.current; }, [props.children]); - const onTransitionEnd = useCallback(() => setAlignBottom(false), []); - useLayoutEffect(() => { - const newHeight = props.visible ? contentRef.current?.getBoundingClientRect().height ?? 0 : 0; + const newHeight = + props.children !== undefined ? contentRef.current?.getBoundingClientRect().height ?? 0 : 0; if (newHeight !== contentHeight) { setContentHeight(newHeight); setAlignBottom((alignBottom) => alignBottom || contentHeight === 0 || newHeight === 0); @@ -161,14 +148,8 @@ export function NotificationBanner(props: INotificationBannerProps) { }); return ( - <Collapsible - ref={collapsibleRef} - alignBottom={alignBottom} - contentHeight={contentHeight} - collapsibleHeight={collapsibleRef.current?.getBoundingClientRect().height ?? 0} - className={props.className} - onTransitionEnd={onTransitionEnd}> - <Content ref={contentRef}>{props.visible ? props.children : prevChildren.current}</Content> + <Collapsible height={contentHeight} className={props.className} alignBottom={alignBottom}> + <Content ref={contentRef}>{props.children ?? prevChildren.current}</Content> </Collapsible> ); } |
