mirror of
https://github.com/revoltchat/revite.git
synced 2024-11-26 00:50:56 -05:00
Add animations to loaders.
This commit is contained in:
parent
e98a962071
commit
22b21c030f
16 changed files with 123 additions and 21 deletions
|
@ -49,7 +49,7 @@ export default function TextFile({ attachment }: Props) {
|
||||||
content ?
|
content ?
|
||||||
<pre><code>{ content }</code></pre>
|
<pre><code>{ content }</code></pre>
|
||||||
: <RequiresOnline>
|
: <RequiresOnline>
|
||||||
<Preloader />
|
<Preloader type="ring" />
|
||||||
</RequiresOnline>
|
</RequiresOnline>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,3 +1,103 @@
|
||||||
export default function Preloader() {
|
import styled, { keyframes } from "styled-components";
|
||||||
return <span>LOADING</span>;
|
|
||||||
|
const skSpinner = keyframes`
|
||||||
|
0%, 80%, 100% {
|
||||||
|
-webkit-transform: scale(0);
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
40% {
|
||||||
|
-webkit-transform: scale(1.0);
|
||||||
|
transform: scale(1.0);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const prRing = keyframes`
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const PreloaderBase = styled.div`
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
|
||||||
|
.spinner {
|
||||||
|
width: 58px;
|
||||||
|
display: flex;
|
||||||
|
text-align: center;
|
||||||
|
margin: 100px auto 0;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner > div {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
background-color: var(--tertiary-foreground);
|
||||||
|
|
||||||
|
border-radius: 100%;
|
||||||
|
display: inline-block;
|
||||||
|
animation: ${skSpinner} 1.4s infinite ease-in-out both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner div:nth-child(1) {
|
||||||
|
animation-delay: -0.32s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner div:nth-child(2) {
|
||||||
|
animation-delay: -0.16s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ring {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
width: 48px;
|
||||||
|
height: 52px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ring div {
|
||||||
|
width: 32px;
|
||||||
|
margin: 8px;
|
||||||
|
height: 32px;
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 2px solid #fff;
|
||||||
|
animation: ${prRing} 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
||||||
|
border-color: #fff transparent transparent transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ring div:nth-child(1) {
|
||||||
|
animation-delay: -0.45s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ring div:nth-child(2) {
|
||||||
|
animation-delay: -0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ring div:nth-child(3) {
|
||||||
|
animation-delay: -0.15s;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
type: 'spinner' | 'ring'
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Preloader({ type }: Props) {
|
||||||
|
return (
|
||||||
|
<PreloaderBase>
|
||||||
|
<div class={type}>
|
||||||
|
<div />
|
||||||
|
<div />
|
||||||
|
<div />
|
||||||
|
</div>
|
||||||
|
</PreloaderBase>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ export function OnboardingModal({ onClose, callback }: Props) {
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.form}>
|
<div className={styles.form}>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<Preloader />
|
<Preloader type="spinner" />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -309,7 +309,7 @@ export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Preloader />
|
<Preloader type="ring" />
|
||||||
))}
|
))}
|
||||||
{tab === "groups" && (
|
{tab === "groups" && (
|
||||||
<div className={styles.entries}>
|
<div className={styles.entries}>
|
||||||
|
|
|
@ -187,7 +187,7 @@ export function FileUploader(props: Props) {
|
||||||
onClick={onClick}>
|
onClick={onClick}>
|
||||||
{ uploading ?
|
{ uploading ?
|
||||||
<div className={styles.uploading}>
|
<div className={styles.uploading}>
|
||||||
<Preloader />
|
<Preloader type="ring" />
|
||||||
</div> :
|
</div> :
|
||||||
<div className={styles.edit}>
|
<div className={styles.edit}>
|
||||||
<Edit size={30} />
|
<Edit size={30} />
|
||||||
|
|
|
@ -29,7 +29,7 @@ const Base = styled.div`
|
||||||
export default function RequiresOnline(props: Props) {
|
export default function RequiresOnline(props: Props) {
|
||||||
const status = useContext(StatusContext);
|
const status = useContext(StatusContext);
|
||||||
|
|
||||||
if (status === ClientStatus.CONNECTING) return <Preloader />;
|
if (status === ClientStatus.CONNECTING) return <Preloader type="ring" />;
|
||||||
if (status !== ClientStatus.ONLINE && status !== ClientStatus.READY)
|
if (status !== ClientStatus.ONLINE && status !== ClientStatus.READY)
|
||||||
return (
|
return (
|
||||||
<Base>
|
<Base>
|
||||||
|
|
|
@ -202,7 +202,7 @@ function Context({ auth, sync, children, dispatcher }: Props) {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (status === ClientStatus.LOADING) {
|
if (status === ClientStatus.LOADING) {
|
||||||
return <Preloader />;
|
return <Preloader type="spinner" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -34,13 +34,15 @@ const Routes = styled.div`
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const path = useLocation().pathname;
|
const path = useLocation().pathname;
|
||||||
const fixedBottomNav = (path === '/' || path === '/settings' || path.startsWith("/friends"));
|
const fixedBottomNav = (path === '/' || path === '/settings' || path.startsWith("/friends"));
|
||||||
|
const inSettings = path === '/settings';
|
||||||
|
const inChannel = path.includes('/channel');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<OverlappingPanels
|
<OverlappingPanels
|
||||||
width="100vw"
|
width="100vw"
|
||||||
height="100vh"
|
height="100vh"
|
||||||
leftPanel={{ width: 292, component: <LeftSidebar /> }}
|
leftPanel={inSettings ? undefined : { width: 292, component: <LeftSidebar /> }}
|
||||||
rightPanel={{ width: 240, component: <RightSidebar /> }}
|
rightPanel={(!inSettings && inChannel) ? { width: 240, component: <RightSidebar /> } : undefined}
|
||||||
bottomNav={{
|
bottomNav={{
|
||||||
component: <BottomNavigation />,
|
component: <BottomNavigation />,
|
||||||
showIf: fixedBottomNav ? ShowIf.Always : ShowIf.Left,
|
showIf: fixedBottomNav ? ShowIf.Always : ShowIf.Left,
|
||||||
|
|
|
@ -12,7 +12,7 @@ export function App() {
|
||||||
<Context>
|
<Context>
|
||||||
{/*
|
{/*
|
||||||
// @ts-expect-error */}
|
// @ts-expect-error */}
|
||||||
<Suspense fallback={<Preloader />}>
|
<Suspense fallback={<Preloader type="spinner" />}>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/login">
|
<Route path="/login">
|
||||||
<CheckAuth>
|
<CheckAuth>
|
||||||
|
|
|
@ -215,10 +215,10 @@ export function MessageArea({ id }: Props) {
|
||||||
<MessageAreaWidthContext.Provider value={(width ?? 0) - MESSAGE_AREA_PADDING}>
|
<MessageAreaWidthContext.Provider value={(width ?? 0) - MESSAGE_AREA_PADDING}>
|
||||||
<Area ref={ref}>
|
<Area ref={ref}>
|
||||||
<div>
|
<div>
|
||||||
{state.type === "LOADING" && <Preloader />}
|
{state.type === "LOADING" && <Preloader type="ring" />}
|
||||||
{state.type === "WAITING_FOR_NETWORK" && (
|
{state.type === "WAITING_FOR_NETWORK" && (
|
||||||
<RequiresOnline>
|
<RequiresOnline>
|
||||||
<Preloader />
|
<Preloader type="ring" />
|
||||||
</RequiresOnline>
|
</RequiresOnline>
|
||||||
)}
|
)}
|
||||||
{state.type === "RENDER" && (
|
{state.type === "RENDER" && (
|
||||||
|
|
|
@ -60,7 +60,7 @@ function MessageRenderer({ id, state, queue }: Props) {
|
||||||
} else {
|
} else {
|
||||||
render.push(
|
render.push(
|
||||||
<RequiresOnline>
|
<RequiresOnline>
|
||||||
<Preloader />
|
<Preloader type="ring" />
|
||||||
</RequiresOnline>
|
</RequiresOnline>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ function MessageRenderer({ id, state, queue }: Props) {
|
||||||
} else {
|
} else {
|
||||||
render.push(
|
render.push(
|
||||||
<RequiresOnline>
|
<RequiresOnline>
|
||||||
<Preloader />
|
<Preloader type="ring" />
|
||||||
</RequiresOnline>
|
</RequiresOnline>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ export default function Invite() {
|
||||||
<div className={styles.preloader}>
|
<div className={styles.preloader}>
|
||||||
<RequiresOnline>
|
<RequiresOnline>
|
||||||
{ error ? <Overline type="error" error={error} />
|
{ error ? <Overline type="error" error={error} />
|
||||||
: <Preloader /> }
|
: <Preloader type="spinner" /> }
|
||||||
</RequiresOnline>
|
</RequiresOnline>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -52,7 +52,7 @@ export default function Invite() {
|
||||||
</div> }
|
</div> }
|
||||||
|
|
||||||
<div className={styles.details}>
|
<div className={styles.details}>
|
||||||
{ processing ? <Preloader /> :
|
{ processing ? <Preloader type="ring" /> :
|
||||||
<>
|
<>
|
||||||
<h1>{ invite.server_name }</h1>
|
<h1>{ invite.server_name }</h1>
|
||||||
<h2>#{invite.channel_name}</h2>
|
<h2>#{invite.channel_name}</h2>
|
||||||
|
|
|
@ -20,7 +20,7 @@ export function CaptchaBlock(props: CaptchaProps) {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (!client.configuration?.features.captcha.enabled)
|
if (!client.configuration?.features.captcha.enabled)
|
||||||
return <Preloader />;
|
return <Preloader type="spinner" />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -138,7 +138,7 @@ export function Form({ page, callback }: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (captcha) return <CaptchaBlock {...captcha} />;
|
if (captcha) return <CaptchaBlock {...captcha} />;
|
||||||
if (loading) return <Preloader />;
|
if (loading) return <Preloader type="spinner" />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.form}>
|
<div className={styles.form}>
|
||||||
|
|
|
@ -55,7 +55,7 @@ export function Sessions() {
|
||||||
if (typeof sessions === "undefined") {
|
if (typeof sessions === "undefined") {
|
||||||
return (
|
return (
|
||||||
<div className={styles.loader}>
|
<div className={styles.loader}>
|
||||||
<Preloader />
|
<Preloader type="ring" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ export function Invites({ server }: Props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.invites}>
|
<div className={styles.invites}>
|
||||||
{ typeof invites === 'undefined' && <Preloader /> }
|
{ typeof invites === 'undefined' && <Preloader type="ring" /> }
|
||||||
{
|
{
|
||||||
invites?.map(
|
invites?.map(
|
||||||
invite => {
|
invite => {
|
||||||
|
|
Loading…
Reference in a new issue