Refactor error banners and add new slimlined reconnect and offline banners
This commit is contained in:
parent
83d80fbbbd
commit
815cc3aead
@ -2,7 +2,13 @@ import React from "react";
|
||||
import Modal from "react-modal";
|
||||
import { useThemeUI, Close } from "theme-ui";
|
||||
|
||||
function Banner({ isOpen, onRequestClose, children, allowClose }) {
|
||||
function Banner({
|
||||
isOpen,
|
||||
onRequestClose,
|
||||
children,
|
||||
allowClose,
|
||||
backgroundColor,
|
||||
}) {
|
||||
const { theme } = useThemeUI();
|
||||
|
||||
return (
|
||||
@ -12,7 +18,7 @@ function Banner({ isOpen, onRequestClose, children, allowClose }) {
|
||||
style={{
|
||||
overlay: { bottom: "0", top: "initial", zIndex: 2000 },
|
||||
content: {
|
||||
backgroundColor: theme.colors.highlight,
|
||||
backgroundColor: backgroundColor || theme.colors.highlight,
|
||||
color: "hsl(210, 50%, 96%)",
|
||||
top: "initial",
|
||||
left: "50%",
|
||||
@ -22,7 +28,7 @@ function Banner({ isOpen, onRequestClose, children, allowClose }) {
|
||||
border: "none",
|
||||
padding: "8px",
|
||||
margin: "8px",
|
||||
paddingRight: "24px",
|
||||
paddingRight: allowClose ? "24px" : "8px",
|
||||
maxWidth: "500px",
|
||||
transform: "translateX(-50%)",
|
||||
},
|
18
src/components/banner/ErrorBanner.js
Normal file
18
src/components/banner/ErrorBanner.js
Normal file
@ -0,0 +1,18 @@
|
||||
import React from "react";
|
||||
import { Box, Text } from "theme-ui";
|
||||
|
||||
import Banner from "./Banner";
|
||||
|
||||
function ErrorBanner({ error, onRequestClose }) {
|
||||
return (
|
||||
<Banner isOpen={!!error} onRequestClose={onRequestClose}>
|
||||
<Box p={1}>
|
||||
<Text as="p" variant="body2">
|
||||
Error: {error && error.message}
|
||||
</Text>
|
||||
</Box>
|
||||
</Banner>
|
||||
);
|
||||
}
|
||||
|
||||
export default ErrorBanner;
|
33
src/components/banner/OfflineBanner.js
Normal file
33
src/components/banner/OfflineBanner.js
Normal file
@ -0,0 +1,33 @@
|
||||
import React from "react";
|
||||
import { Flex } from "theme-ui";
|
||||
|
||||
import Banner from "./Banner";
|
||||
import OfflineIcon from "../../icons/OfflineIcon";
|
||||
|
||||
function OfflineBanner({ isOpen }) {
|
||||
return (
|
||||
<Banner
|
||||
isOpen={isOpen}
|
||||
onRequestClose={() => {}}
|
||||
allowClose={false}
|
||||
backgroundColor="transparent"
|
||||
>
|
||||
<Flex
|
||||
sx={{
|
||||
width: "28px",
|
||||
height: "28px",
|
||||
borderRadius: "28px",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
bg="overlay"
|
||||
title="Unable to connect to game, refresh to reconnect."
|
||||
aria-label="Unable to connect to game, refresh to reconnect."
|
||||
>
|
||||
<OfflineIcon />
|
||||
</Flex>
|
||||
</Banner>
|
||||
);
|
||||
}
|
||||
|
||||
export default OfflineBanner;
|
33
src/components/banner/ReconnectBanner.js
Normal file
33
src/components/banner/ReconnectBanner.js
Normal file
@ -0,0 +1,33 @@
|
||||
import React from "react";
|
||||
import { Flex } from "theme-ui";
|
||||
|
||||
import Banner from "./Banner";
|
||||
import ReconnectingIcon from "../../icons/ReconnectingIcon";
|
||||
|
||||
function ReconnectBanner({ isOpen }) {
|
||||
return (
|
||||
<Banner
|
||||
isOpen={isOpen}
|
||||
onRequestClose={() => {}}
|
||||
allowClose={false}
|
||||
backgroundColor="transparent"
|
||||
>
|
||||
<Flex
|
||||
sx={{
|
||||
width: "28px",
|
||||
height: "28px",
|
||||
borderRadius: "28px",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
bg="overlay"
|
||||
title="Disconnected. Attempting to reconnect..."
|
||||
aria-label="Disconnected. Attempting to reconnect..."
|
||||
>
|
||||
<ReconnectingIcon />
|
||||
</Flex>
|
||||
</Banner>
|
||||
);
|
||||
}
|
||||
|
||||
export default ReconnectBanner;
|
@ -1,5 +1,4 @@
|
||||
import React, { useRef, useEffect, useState } from "react";
|
||||
import { Box, Text } from "theme-ui";
|
||||
import { Engine } from "@babylonjs/core/Engines/engine";
|
||||
import { Scene } from "@babylonjs/core/scene";
|
||||
import { Vector3, Color4, Matrix } from "@babylonjs/core/Maths/math";
|
||||
@ -19,7 +18,7 @@ import ReactResizeDetector from "react-resize-detector";
|
||||
|
||||
import usePreventTouch from "../../hooks/usePreventTouch";
|
||||
|
||||
import Banner from "../Banner";
|
||||
import ErrorBanner from "../banner/ErrorBanner";
|
||||
|
||||
const diceThrowSpeed = 2;
|
||||
|
||||
@ -166,13 +165,7 @@ function DiceInteraction({ onSceneMount, onPointerDown, onPointerUp }) {
|
||||
style={{ outline: "none" }}
|
||||
/>
|
||||
</ReactResizeDetector>
|
||||
<Banner isOpen={!!error} onRequestClose={() => setError()}>
|
||||
<Box p={1}>
|
||||
<Text as="p" variant="body2">
|
||||
Error: {error && error.message}
|
||||
</Text>
|
||||
</Box>
|
||||
</Banner>
|
||||
<ErrorBanner error={error} onRequestClose={() => setError()} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import { Text, IconButton, Box, Flex } from "theme-ui";
|
||||
|
||||
import StreamMuteIcon from "../../icons/StreamMuteIcon";
|
||||
|
||||
import Banner from "../Banner";
|
||||
import Banner from "../banner/Banner";
|
||||
import Slider from "../Slider";
|
||||
|
||||
function Stream({ stream, nickname }) {
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React, { useState, useEffect, useContext } from "react";
|
||||
import { Box, Text } from "theme-ui";
|
||||
|
||||
import Banner from "../components/Banner";
|
||||
import ErrorBanner from "../components/banner/ErrorBanner";
|
||||
|
||||
import { getDatabase } from "../database";
|
||||
|
||||
@ -64,16 +63,10 @@ export function DatabaseProvider({ children }) {
|
||||
<DatabaseContext.Provider value={value}>
|
||||
<>
|
||||
{children}
|
||||
<Banner
|
||||
isOpen={!!databaseError}
|
||||
<ErrorBanner
|
||||
error={databaseError}
|
||||
onRequestClose={() => setDatabaseError()}
|
||||
>
|
||||
<Box p={1}>
|
||||
<Text as="p" variant="body2">
|
||||
{databaseError && databaseError.message}
|
||||
</Text>
|
||||
</Box>
|
||||
</Banner>
|
||||
/>
|
||||
</>
|
||||
</DatabaseContext.Provider>
|
||||
);
|
||||
|
18
src/icons/OfflineIcon.js
Normal file
18
src/icons/OfflineIcon.js
Normal file
@ -0,0 +1,18 @@
|
||||
import React from "react";
|
||||
|
||||
function PointerToolIcon() {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
fill="currentcolor"
|
||||
>
|
||||
<path d="M0 0h24v24H0V0zm0 0h24v24H0V0z" fill="none" />
|
||||
<path d="M10 5.74v-.19c0-.68-.71-1.11-1.32-.82-.19.09-.36.2-.54.3L9.6 6.49c.24-.18.4-.45.4-.75zM20 12c0-2.21-.91-4.2-2.36-5.64l1.51-1.51c.31-.31.09-.85-.36-.85H14v4.79c0 .45.54.67.85.35l1.39-1.39C17.32 8.85 18 10.34 18 12c0 .85-.18 1.66-.5 2.39l1.48 1.48C19.62 14.72 20 13.41 20 12zM3.57 4.7c-.39.39-.39 1.02 0 1.41l1.65 1.65C4.45 9 4 10.44 4 12c0 2.21.91 4.2 2.36 5.64l-1.51 1.51c-.31.31-.09.85.36.85H9.5c.28 0 .5-.22.5-.5v-4.29c0-.45-.54-.67-.85-.35l-1.39 1.39C6.68 15.15 6 13.66 6 12c0-1 .26-1.93.69-2.76l8.07 8.07c-.01.02-.01.02-.01.04-.43.12-.75.48-.75.91v.18c0 .68.71 1.11 1.32.82.31-.14.61-.31.9-.49l1.87 1.87c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L4.98 4.7c-.39-.39-1.02-.39-1.41 0z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export default PointerToolIcon;
|
28
src/icons/ReconnectingIcon.js
Normal file
28
src/icons/ReconnectingIcon.js
Normal file
@ -0,0 +1,28 @@
|
||||
import React from "react";
|
||||
|
||||
function ReconnectingIcon() {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
fill="currentcolor"
|
||||
>
|
||||
<path d="M.01 0h24v24h-24V0z" fill="none" />
|
||||
<path d="M12 4V2.21c0-.45-.54-.67-.85-.35l-2.8 2.79c-.2.2-.2.51 0 .71l2.79 2.79c.32.31.86.09.86-.36V6c3.31 0 6 2.69 6 6 0 .79-.15 1.56-.44 2.25-.15.36-.04.77.23 1.04.51.51 1.37.33 1.64-.34.37-.91.57-1.91.57-2.95 0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-.79.15-1.56.44-2.25.15-.36.04-.77-.23-1.04-.51-.51-1.37-.33-1.64.34C4.2 9.96 4 10.96 4 12c0 4.42 3.58 8 8 8v1.79c0 .45.54.67.85.35l2.79-2.79c.2-.2.2-.51 0-.71l-2.79-2.79c-.31-.31-.85-.09-.85.36V18z">
|
||||
<animateTransform
|
||||
attributeName="transform"
|
||||
attributeType="XML"
|
||||
type="rotate"
|
||||
from="360 12 12"
|
||||
to="0 12 12"
|
||||
dur="2s"
|
||||
repeatCount="indefinite"
|
||||
/>
|
||||
</path>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export default ReconnectingIcon;
|
@ -8,7 +8,7 @@ import { useToasts } from "react-toast-notifications";
|
||||
import Modal from "../components/Modal";
|
||||
import LoadingOverlay from "../components/LoadingOverlay";
|
||||
import LoadingBar from "../components/LoadingBar";
|
||||
import Banner from "../components/Banner";
|
||||
import ErrorBanner from "../components/banner/ErrorBanner";
|
||||
|
||||
import { useAuth } from "../contexts/AuthContext";
|
||||
|
||||
@ -271,13 +271,7 @@ function ImportExportModal({ isOpen, onRequestClose }) {
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
<Banner isOpen={!!error} onRequestClose={() => setError()}>
|
||||
<Box p={1}>
|
||||
<Text as="p" variant="body2">
|
||||
Error: {error && error.message}
|
||||
</Text>
|
||||
</Box>
|
||||
</Banner>
|
||||
<ErrorBanner error={error} onRequestClose={() => setError()} />
|
||||
<SelectDataModal
|
||||
isOpen={showImportSelector}
|
||||
onRequestClose={handleImportSelectorClose}
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
import Footer from "../components/Footer";
|
||||
import Banner from "../components/Banner";
|
||||
import ErrorBanner from "../components/banner/ErrorBanner";
|
||||
import LoadingOverlay from "../components/LoadingOverlay";
|
||||
|
||||
import { logError } from "../helpers/logging";
|
||||
@ -159,13 +159,7 @@ function Donate() {
|
||||
</Flex>
|
||||
<Footer />
|
||||
{loading && <LoadingOverlay />}
|
||||
<Banner isOpen={!!error} onRequestClose={() => setError(null)}>
|
||||
<Box p={1}>
|
||||
<Text as="p" variant="body2">
|
||||
{error}
|
||||
</Text>
|
||||
</Box>
|
||||
</Banner>
|
||||
<ErrorBanner error={error} onRequestClose={() => setError()} />
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
@ -2,7 +2,9 @@ import React, { useState, useEffect, useRef } from "react";
|
||||
import { Flex, Box, Text } from "theme-ui";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
import Banner from "../components/Banner";
|
||||
import Banner from "../components/banner/Banner";
|
||||
import ReconnectBanner from "../components/banner/ReconnectBanner";
|
||||
import OfflineBanner from "../components/banner/OfflineBanner";
|
||||
import LoadingOverlay from "../components/LoadingOverlay";
|
||||
import Link from "../components/Link";
|
||||
import MapLoadingOverlay from "../components/map/MapLoadingOverlay";
|
||||
@ -125,28 +127,8 @@ function Game() {
|
||||
</Text>
|
||||
</Box>
|
||||
</Banner>
|
||||
<Banner
|
||||
isOpen={sessionStatus === "offline"}
|
||||
onRequestClose={() => {}}
|
||||
allowClose={false}
|
||||
>
|
||||
<Box p={1}>
|
||||
<Text as="p" variant="body2">
|
||||
Unable to connect to game, refresh to reconnect.
|
||||
</Text>
|
||||
</Box>
|
||||
</Banner>
|
||||
<Banner
|
||||
isOpen={sessionStatus === "reconnecting"}
|
||||
onRequestClose={() => {}}
|
||||
allowClose={false}
|
||||
>
|
||||
<Box p={1}>
|
||||
<Text as="p" variant="body2">
|
||||
Disconnected. Attempting to reconnect...
|
||||
</Text>
|
||||
</Box>
|
||||
</Banner>
|
||||
<OfflineBanner isOpen={sessionStatus === "offline"} />
|
||||
<ReconnectBanner isOpen={sessionStatus === "reconnecting"} />
|
||||
<AuthModal
|
||||
isOpen={sessionStatus === "auth"}
|
||||
onSubmit={handleAuthSubmit}
|
||||
|
Loading…
Reference in New Issue
Block a user