react-transition-group#Transition TypeScript Examples

The following examples show how to use react-transition-group#Transition. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: TabsOfTruth.tsx    From mStable-apps with GNU Lesser General Public License v3.0 6 votes vote down vote up
TabsOfTruth: FC<
  State & {
    setActiveIndex: (index: number) => void
    className?: string
  }
> = ({ tabs, setActiveIndex, activeTabIndex, className }) => {
  const container = useRef<HTMLDivElement>(undefined as never)
  const prevActiveTabIndex = usePrevious(activeTabIndex)
  const [activePos, setActivePos] = useState<[number, number]>([0, 0])

  useLayoutEffect(() => {
    const { offsetWidth, offsetLeft } = container.current.childNodes.item(activeTabIndex + 1) as HTMLElement
    setActivePos([offsetLeft, offsetWidth])
  }, [activeTabIndex])

  return (
    <TabsContainer ref={container} className={className}>
      <Transition in={activeTabIndex !== prevActiveTabIndex} appear timeout={250} unmountOnExit={false}>
        {className => <ActiveTab pos={activePos} className={className} />}
      </Transition>
      {tabs.map(({ id, title, active }, index) => (
        <TabButton
          active={active}
          key={id}
          onClick={() => {
            setActiveIndex(index)
          }}
        >
          {title}
        </TabButton>
      ))}
    </TabsContainer>
  )
}
Example #2
Source File: LoadProgress.tsx    From NetworkViewPCF with MIT License 6 votes vote down vote up
render() {
    const { progressText, isLoading, cancelRequested, isPaused } = this.props.vm;
    return (
      <>
        <Transition in={isLoading || isPaused} timeout={500} classNames="my-node">
          {state =>
            state != "exited" && (
              <Stack style={progressBoxStyle} className={this.getTransitionClass(state)}>
                <Stack.Item>{progressText}</Stack.Item>
                {isLoading && (
                  <Stack.Item>
                    {!cancelRequested && <DefaultButton text="Cancel" onClick={this.onCancel}></DefaultButton>}
                  </Stack.Item>
                )}
                {isPaused && (
                  <Stack.Item>
                    {!cancelRequested && <DefaultButton text="Resume" onClick={this.onResume}></DefaultButton>}
                  </Stack.Item>
                )}
              </Stack>
            )
          }
        </Transition>
      </>
    );
  }
Example #3
Source File: SlideTransition.tsx    From firetable with Apache License 2.0 5 votes vote down vote up
SlideTransition: React.ForwardRefExoticComponent<
  Pick<TransitionProps, React.ReactText> & React.RefAttributes<any>
> = React.forwardRef(
  ({ children, ...props }: TransitionProps, ref: React.Ref<any>) => {
    const theme = useTheme();

    if (!children) return null;

    const defaultStyle = {
      opacity: 0,
      transform: "translateY(16px)",

      transition: theme.transitions.create(["transform", "opacity"], {
        duration: "300ms",
        easing: "cubic-bezier(0.075, 0.82, 0.165, 1)",
      }),
    };

    const transitionStyles = {
      entering: {
        willChange: "transform, opacity",
      },

      entered: {
        opacity: 1,
        transform: "none",
      },

      exiting: {
        opacity: 0,
        transform: "none",

        transition: theme.transitions.create(["opacity"], {
          duration: theme.transitions.duration.leavingScreen,
        }),
      },

      exited: {
        opacity: 0,
        transform: "none",
        transition: "none",
      },

      unmounted: {},
    };

    return (
      <Transition
        appear
        timeout={{ enter: 0, exit: theme.transitions.duration.leavingScreen }}
        {...props}
      >
        {(state) =>
          React.cloneElement(children as any, {
            style: { ...defaultStyle, ...transitionStyles[state] },
            ref,
          })
        }
      </Transition>
    );
  }
)
Example #4
Source File: SlideTransition.tsx    From firetable with Apache License 2.0 5 votes vote down vote up
SlideTransitionMui = React.forwardRef(function Transition(
  props: MuiTransitionProps & { children?: React.ReactElement<any, any> },
  ref: React.Ref<unknown>
) {
  return <SlideTransition ref={ref} {...props} />;
})
Example #5
Source File: LoadingIndicator.tsx    From tobira with Apache License 2.0 5 votes vote down vote up
LoadingIndicator: React.FC = () => {
    const router = useRouter();

    // If search is active, there is a loading indicator next to the search input.
    if (isSearchActive()) {
        return null;
    }

    const START_DURATION = 1200;
    const EXIT_DURATION = 150;

    // TODO: maybe disable this for `prefers-reduced-motion: reduce`
    return <Transition in={router.isTransitioning} timeout={EXIT_DURATION}>{state => (
        <div css={{
            position: "fixed",
            zIndex: 2000,
            left: 0,
            top: 0,
            height: 4,
            backgroundColor: "var(--accent-color)",
            ...match(state, {
                "entering": () => ({
                    width: "70%",
                    transition: `width ${START_DURATION}ms`,
                }),
                "entered": () => ({
                    width: "70%",
                    transition: `width ${START_DURATION}ms`,
                }),
                "exiting": () => ({
                    width: "100%",
                    opacity: 0,
                    transition: `width ${EXIT_DURATION}ms, `
                        + `opacity ${0.2 * EXIT_DURATION}ms ease ${0.8 * EXIT_DURATION}ms`,
                }),
                "exited": () => ({
                    width: "0%",
                    transition: "none",
                }),
                "unmounted": () => ({}),
            }),
        }} />
    )}</Transition>;
}
Example #6
Source File: Toast.tsx    From viewer with MIT License 5 votes vote down vote up
public render(): JSX.Element {
    const { text, category, type, hasCloseButton, link } = this.props;
    return (
      <Transition
        timeout={240}
        in={this.state.isVisible}
        appear={true}
        unmountOnExit={true}
        onExited={this.props.onRemove}
      >
        {(state) => (
          <div
            className={`itwin-toast-all itwin-toast-${state}`}
            style={{
              height: this.state.height,
              marginBottom: this.state.isVisible ? "0" : -this.state.height,
            }}
          >
            <div ref={this.onRef} style={{ padding: "0px 16px 16px 16px" }}>
              <div className={`itwin-toast-${category}`}>
                <div className="status-icon-container">
                  <div className={"status-icon-background"}>
                    {this.getCategoryIcon()}
                  </div>
                </div>
                <div className="message">{text}</div>
                {link && (
                  <div className="link">
                    {typeof link.url === "string" ? (
                      <a
                        href={link.url}
                        target="_blank"
                        rel="noopener noreferrer"
                      >
                        {link.title}
                      </a>
                    ) : (
                      <a onClick={link.url}>{link.title}</a>
                    )}
                  </div>
                )}
                {(type === "persisting" ||
                  (type === "temporary" && hasCloseButton)) && (
                  <div className="close-icon-container">
                    <Close className="close-icon" onClick={this.close} />
                  </div>
                )}
              </div>
            </div>
          </div>
        )}
      </Transition>
    );
  }
Example #7
Source File: Toast.tsx    From itwin-viewer with MIT License 5 votes vote down vote up
public render() {
    const { text, category, type, hasCloseButton, link } = this.props;
    return (
      <Transition
        timeout={240}
        in={this.state.isVisible}
        appear={true}
        unmountOnExit={true}
        onExited={this.props.onRemove}
      >
        {(state) => (
          <div
            className={`itwin-toast-all itwin-toast-${state}`}
            style={{
              height: this.state.height,
              marginBottom: this.state.isVisible ? "0" : -this.state.height,
            }}
          >
            <div ref={this.onRef} style={{ padding: "0px 16px 16px 16px" }}>
              <div className={`itwin-toast-${category}`}>
                <div className="status-icon-container">
                  <div className={"status-icon-background"}>
                    {this.getCategoryIcon()}
                  </div>
                </div>
                <div className="message">{text}</div>
                {link && (
                  <div className="link">
                    {typeof link.url === "string" ? (
                      <a
                        href={link.url}
                        target="_blank"
                        rel="noopener noreferrer"
                      >
                        {link.title}
                      </a>
                    ) : (
                      <a onClick={link.url}>{link.title}</a>
                    )}
                  </div>
                )}
                {(type === "persisting" ||
                  (type === "temporary" && hasCloseButton)) && (
                  <div className="close-icon-container">
                    <Close className="close-icon" onClick={this.close} />
                  </div>
                )}
              </div>
            </div>
          </div>
        )}
      </Transition>
    );
  }
Example #8
Source File: SlideFadeTransition.tsx    From firecms with MIT License 4 votes vote down vote up
SlideFade = React.forwardRef(function SlideFade(props: SlideProps, ref) {
    const {
        children,
        in: inProp,
        timeout,
        onExitAnimation,
        ...other
    } = props;

    const theme: any = useTheme();
    const childrenRef = React.useRef<any>(null);
    const handleRefIntermediary = useForkRef(children.ref, childrenRef);
    const handleRef = useForkRef(handleRefIntermediary, ref);

    const normalizedTransitionCallback = (callback: any) => (isAppearing: boolean) => {
        if (callback) {
            // onEnterXxx and onExitXxx callbacks have a different arguments.length value.
            if (isAppearing === undefined) {
                callback(childrenRef.current);
            } else {
                callback(childrenRef.current, isAppearing);
            }
        }
    };

    const handleEnter = normalizedTransitionCallback((node: any) => {
        setTranslateValue(node);
        reflow(node);
    });

    const handleEntering = normalizedTransitionCallback((node: any) => {
        const transitionProps = getTransitionProps(
            { timeout },
            {
                mode: "enter"
            }
        );
        node.style.webkitTransition = theme.transitions.create("-webkit-transform", {
            ...transitionProps,
            easing: theme.transitions.easing.easeOut
        });

        node.style.transition = theme.transitions.create("transform", {
            ...transitionProps,
            easing: theme.transitions.easing.easeOut
        });

        node.style.webkitTransform = "none";
        node.style.transform = "none";
        node.style.opacity = 1;
    });


    const handleExit: any = normalizedTransitionCallback((node: any) => {
        const transitionProps = getTransitionProps(
            { timeout },
            {
                mode: "exit"
            }
        );

        node.style.opacity = 0.5;
        node.style.webkitTransition = theme.transitions.create(["-webkit-transform", "opacity"], {
            ...transitionProps,
            easing: theme.transitions.easing.sharp
        });

        node.style.transition = theme.transitions.create(["transform", "opacity"], {
            ...transitionProps,
            easing: theme.transitions.easing.sharp
        });

        setTranslateValue(node);
    });

    const handleExited: any = normalizedTransitionCallback((node: any) => {
        // No need for transitions when the component is hidden
        node.style.webkitTransition = "";
        node.style.transition = "";

    });

    const updatePosition = React.useCallback(() => {
        if (childrenRef.current) {
            setTranslateValue(childrenRef.current);
        }
    }, []);

    React.useEffect(() => {
        // Skip configuration where the position is screen size invariant.
        if (inProp) {
            return undefined;
        }

        const handleResize = debounce(() => {
            if (childrenRef.current) {
                setTranslateValue(childrenRef.current);
            }
        });

        const containerWindow = ownerWindow(childrenRef.current);
        containerWindow.addEventListener("resize", handleResize);
        return () => {
            handleResize.clear();
            containerWindow.removeEventListener("resize", handleResize);
        };
    }, [inProp]);

    React.useEffect(() => {
        if (!inProp) {
            // We need to update the position of the drawer when the direction change and
            // when it's hidden.d
            updatePosition();
        }
    }, [inProp, updatePosition]);

    return (
        <Transition
            nodeRef={childrenRef}
            onEnter={handleEnter}
            onEntering={handleEntering}
            onExit={handleExit}
            onExited={handleExited}
            appear={true}
            in={inProp}
            timeout={timeout}
            {...other}
        >
            {((state: any, childProps: any) => {
                return React.cloneElement(children, {
                    ref: handleRef,
                    style: {
                        visibility: state === "exited" && !inProp ? "hidden" : undefined,
                        ...children.props.style
                    },
                    ...childProps
                });
            }) as any}
        </Transition>
    );
})
Example #9
Source File: FileGallery.tsx    From abrechnung with GNU Affero General Public License v3.0 4 votes vote down vote up
export default function FileGallery({ transaction }) {
    const [files, setFiles] = useState([]); // map of file id to object
    const [active, setActive] = useState(0);
    const setTransactions = useSetRecoilState(groupTransactions(transaction.group_id));

    const [showUploadDialog, setShowUploadDialog] = useState(false);
    const [showImage, setShowImage] = useState(false);

    useEffect(() => {
        const newFileIDs = new Set(transaction.files.map((file) => file.id));
        const filteredFiles = files.reduce((map, file) => {
            map[file.id] = file;
            return map;
        }, {});
        for (const loadedFile of files) {
            if (!newFileIDs.has(loadedFile.id)) {
                URL.revokeObjectURL(loadedFile.objectUrl); // clean up memory
                delete filteredFiles[loadedFile.id];
            }
        }
        setFiles(Object.values(filteredFiles)); // TODO: maybe include placeholders
        setActive(Math.max(0, Math.min(active, transaction.files.length - 1)));

        const newFiles = transaction.files.filter((file) => !filteredFiles.hasOwnProperty(file.id));
        Promise.all(
            newFiles.map((newFile) => {
                return fetchFile({
                    fileID: newFile.id,
                    blobID: newFile.blob_id,
                }).then((resp) => {
                    const objectUrl = URL.createObjectURL(resp.data);
                    return {
                        ...newFile,
                        objectUrl: objectUrl,
                    };
                });
            })
        )
            .then((newlyLoadedFiles) => {
                setFiles([...Object.values(filteredFiles), ...newlyLoadedFiles]);
            })
            .catch((err) => {
                toast.error(`Error loading file: ${err}`);
            });
    }, [transaction]);

    const toNextImage = () => {
        if (active < files.length - 1) {
            setActive(active + 1);
        }
    };

    const toPrevImage = () => {
        if (active > 0) {
            setActive(active - 1);
        }
    };

    const doShowImage = (img) => {
        setShowImage(true);
    };

    const deleteSelectedFile = () => {
        if (active < files.length) {
            // sanity check, should not be needed
            deleteFile({ fileID: files[active].id })
                .then((t) => {
                    updateTransactionInState(t, setTransactions);
                    setShowImage(false);
                })
                .catch((err) => {
                    toast.error(`Error deleting file: ${err}`);
                });
        }
    };

    // @ts-ignore
    return (
        <>
            <Grid
                container
                justifyContent="center"
                alignItems="center"
                style={{
                    position: "relative",
                    height: "200px",
                    width: "100%",
                }}
            >
                {files.length === 0 ? (
                    <img height="100%" src={placeholderImg} alt="placeholder" />
                ) : (
                    files.map((item, idx) => (
                        <Transition key={item.id} in={active === idx} timeout={duration}>
                            {(state) => (
                                <img
                                    height="100%"
                                    style={{
                                        ...defaultStyle,
                                        ...transitionStyles[state],
                                    }}
                                    onClick={() => doShowImage(item)}
                                    src={item.objectUrl}
                                    srcSet={item.objectUrl}
                                    alt={item.filename.split(".")[0]}
                                    loading="lazy"
                                />
                            )}
                        </Transition>
                    ))
                )}
                <Chip
                    sx={{ position: "absolute", top: "5px", right: "10px" }}
                    size="small"
                    label={`${Math.min(files.length, active + 1)} / ${files.length}`}
                />
                {active > 0 && (
                    <IconButton onClick={toPrevImage} sx={{ position: "absolute", top: "40%", left: "10px" }}>
                        <ChevronLeft />
                    </IconButton>
                )}
                {active < files.length - 1 && (
                    <IconButton onClick={toNextImage} sx={{ position: "absolute", top: "40%", right: "10px" }}>
                        <ChevronRight />
                    </IconButton>
                )}
                {transaction.is_wip && (
                    <>
                        <IconButton
                            color="primary"
                            sx={{
                                position: "absolute",
                                top: "80%",
                                right: "10px",
                            }}
                            onClick={() => setShowUploadDialog(true)}
                        >
                            <AddCircle fontSize="large" />
                        </IconButton>
                        <ImageUploadDialog
                            transaction={transaction}
                            show={showUploadDialog}
                            onClose={() => setShowUploadDialog(false)}
                        />
                    </>
                )}
            </Grid>
            <Dialog open={showImage} onClose={() => setShowImage(false)} scroll="body">
                {active < files.length && <DialogTitle>{files[active].filename.split(".")[0]}</DialogTitle>}

                <DialogContent>
                    <Grid
                        container
                        justifyContent="center"
                        alignItems="center"
                        style={{
                            position: "relative",
                        }}
                    >
                        {active < files.length && (
                            <img
                                height="100%"
                                width="100%"
                                src={files[active]?.objectUrl}
                                srcSet={files[active]?.objectUrl}
                                alt={files[active]?.filename}
                                loading="lazy"
                            />
                        )}
                        {active > 0 && (
                            <IconButton
                                onClick={toPrevImage}
                                sx={{
                                    position: "absolute",
                                    top: "40%",
                                    left: "0px",
                                }}
                            >
                                <ChevronLeft />
                            </IconButton>
                        )}
                        {active < files.length - 1 && (
                            <IconButton
                                onClick={toNextImage}
                                sx={{
                                    position: "absolute",
                                    top: "40%",
                                    right: "0px",
                                }}
                            >
                                <ChevronRight />
                            </IconButton>
                        )}
                    </Grid>
                </DialogContent>
                {transaction.is_wip && (
                    <DialogActions>
                        <Button startIcon={<Delete />} onClick={deleteSelectedFile} variant="outlined" color="error">
                            Delete
                        </Button>
                    </DialogActions>
                )}
            </Dialog>
        </>
    );
}
Example #10
Source File: index.tsx    From midway with MIT License 4 votes vote down vote up
Layout = ({ children, location, pageContext }: { children: any, location: { pathname: string }, pageContext: { site?: {}, layout: string }}) => {

  const { site } = pageContext

  // Render documentation for CMS minus header/footer experience
  if (pageContext.layout === 'docs') {
    return (
      <div>
        {children}
      </div>
    )
  }

  if (pageContext.layout === 'accounts') {
    return (
      <React.Fragment>
        <Helmet title='Accounts' />
        <Header />
        <div>{children}</div>
        <Footer {...site} />
      </React.Fragment>
    )
  }

  useEffect(() => {
    tighpo('spaghetti', function () {
      const style = document.createElement('style')
      document.body.appendChild(style)
      style.sheet.insertRule('html, body { cursor: url(https://spaghet.now.sh), auto !important; }')
    })
  }, [0])

  return (
    <React.Fragment>
      <Helmet title='Midway'>
        <link href='https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&display=swap' rel='stylesheet' />
      </Helmet>
      <Analytics
        googleAnalyticsPropertyId={process.env.GATSBY_GA_ID} />
      <PasswordWrapper>
        <div>
          <a
            name='maincontent'
            className='pf top left z10 skip'
            href='#maincontent'
          >
            Skip to main content
          </a>
          <Header />
          <CartDrawer />
          {/* 
          
            Smooth transition credits to Ian Williams: https://github.com/dictions
          
          */}
          {!/account/.test(location.pathname) ? (
            <SwitchTransition>
              <Transition
                key={location.pathname}
                mountOnEnter={true}
                unmountOnExit={true}
                appear={true}
                timeout={TRANSITION_DURATION}>
                  {status => (
                    <main
                      className='site'
                      id='maincontent'
                      style={{
                        ...TRANSITION_STYLES.default,
                        ...TRANSITION_STYLES[status],
                      }}>
                      {children}
                      <Footer {...site} />
                    </main>
                  )}
              </Transition>
            </SwitchTransition>
          ) : (
            <div>
              {children}
              <Footer {...site} />
            </div>
          )}
        </div>
      </PasswordWrapper>
    </React.Fragment>
  )
}
Example #11
Source File: NotificationsProvider.tsx    From mantine with MIT License 4 votes vote down vote up
export function NotificationsProvider({
  className,
  position = 'bottom-right',
  autoClose = 4000,
  transitionDuration = 250,
  containerWidth = 440,
  notificationMaxHeight = 200,
  limit = 5,
  zIndex = getDefaultZIndex('overlay'),
  style,
  children,
  ...others
}: NotificationProviderProps) {
  const forceUpdate = useForceUpdate();
  const refs = useRef<Record<string, HTMLDivElement>>({});
  const previousLength = useRef<number>(0);
  const {
    notifications,
    queue,
    showNotification,
    updateNotification,
    hideNotification,
    clean,
    cleanQueue,
  } = useNotificationsState({ limit });
  const reduceMotion = useReducedMotion();
  const duration = reduceMotion ? 1 : transitionDuration;
  const { classes, cx, theme } = useStyles();
  const positioning = (POSITIONS.includes(position) ? position : 'bottom-right').split(
    '-'
  ) as NotificationsProviderPositioning;

  const ctx = {
    notifications,
    queue,
    showNotification,
    hideNotification,
    updateNotification,
    clean,
    cleanQueue,
  };

  useDidUpdate(() => {
    if (notifications.length > previousLength.current) {
      setTimeout(() => forceUpdate(), 0);
    }
    previousLength.current = notifications.length;
  }, [notifications]);

  useNotificationsEvents(ctx);

  const items = notifications.map((notification) => (
    <Transition
      key={notification.id}
      timeout={duration}
      onEnter={() => refs.current[notification.id].offsetHeight}
      nodeRef={{ current: refs.current[notification.id] }}
    >
      {(state) => (
        <NotificationContainer
          innerRef={(node) => {
            refs.current[notification.id] = node;
          }}
          notification={notification}
          onHide={hideNotification}
          className={classes.notification}
          autoClose={autoClose}
          sx={[
            {
              ...getNotificationStateStyles({
                state,
                positioning,
                transitionDuration: duration,
                maxHeight: notificationMaxHeight,
              }),
            },
            ...(Array.isArray(notification.sx) ? notification.sx : [notification.sx]),
          ]}
        />
      )}
    </Transition>
  ));

  return (
    <NotificationsContext.Provider value={ctx}>
      <Portal zIndex={zIndex}>
        <Box
          className={cx(classes.notifications, className)}
          style={style}
          sx={{
            maxWidth: containerWidth,
            ...getPositionStyles(positioning, containerWidth, theme.spacing.md),
          }}
          {...others}
        >
          <TransitionGroup>{items}</TransitionGroup>
        </Box>
      </Portal>

      {children}
    </NotificationsContext.Provider>
  );
}