It's time for a new loading indicator

This commit is contained in:
Lim Chee Aun 2023-04-14 15:46:11 +08:00
parent cc3a1d3030
commit 19858dc889
4 changed files with 90 additions and 61 deletions

View file

@ -154,6 +154,36 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) {
padding-bottom: 80dvh !important; padding-bottom: 80dvh !important;
} }
@keyframes indeterminate-bar {
0% {
transform: translateX(-50%);
opacity: 0.25;
}
50% {
opacity: 1;
}
100% {
transform: translateX(50%);
opacity: 0.25;
}
}
.deck > header.loading:after {
pointer-events: none;
content: '';
display: block;
height: 4px;
position: absolute;
bottom: 0;
width: 50%;
left: 25%;
background-image: radial-gradient(
ellipse farthest-side at bottom,
var(--link-color),
transparent
);
animation: indeterminate-bar 1s ease-in-out infinite alternate;
}
.timeline { .timeline {
margin: 0 auto; margin: 0 auto;
padding: 0; padding: 0;

View file

@ -271,6 +271,7 @@ function Timeline({
loadItems(true); loadItems(true);
} }
}} }}
class={uiState === 'loading' ? 'loading' : ''}
> >
<div class="header-grid"> <div class="header-grid">
<div class="header-side"> <div class="header-side">
@ -285,7 +286,7 @@ function Timeline({
</div> </div>
{title && (titleComponent ? titleComponent : <h1>{title}</h1>)} {title && (titleComponent ? titleComponent : <h1>{title}</h1>)}
<div class="header-side"> <div class="header-side">
<Loader hidden={uiState !== 'loading'} /> {/* <Loader hidden={uiState !== 'loading'} /> */}
{!!headerEnd && headerEnd} {!!headerEnd && headerEnd}
</div> </div>
</div> </div>

View file

@ -162,6 +162,7 @@ function Notifications() {
scrollableRef.current?.scrollTo({ top: 0, behavior: 'smooth' }); scrollableRef.current?.scrollTo({ top: 0, behavior: 'smooth' });
} }
}} }}
class={uiState === 'loading' ? 'loading' : ''}
> >
<div class="header-grid"> <div class="header-grid">
<div class="header-side"> <div class="header-side">
@ -172,7 +173,7 @@ function Notifications() {
</div> </div>
<h1>Notifications</h1> <h1>Notifications</h1>
<div class="header-side"> <div class="header-side">
<Loader hidden={uiState !== 'loading'} /> {/* <Loader hidden={uiState !== 'loading'} /> */}
</div> </div>
</div> </div>
{snapStates.notificationsShowNew && uiState !== 'loading' && ( {snapStates.notificationsShowNew && uiState !== 'loading' && (

View file

@ -554,7 +554,9 @@ function StatusThread({ closeLink = '/' }) {
} ${initialPageState.current === 'status' ? 'slide-in' : ''}`} } ${initialPageState.current === 'status' ? 'slide-in' : ''}`}
> >
<header <header
class={`${heroInView ? 'inview' : ''}`} class={`${heroInView ? 'inview' : ''} ${
uiState === 'loading' ? 'loading' : ''
}`}
onDblClick={(e) => { onDblClick={(e) => {
// reload statuses // reload statuses
states.reloadStatusPage++; states.reloadStatusPage++;
@ -628,66 +630,61 @@ function StatusThread({ closeLink = '/' }) {
)} )}
</h1> </h1>
<div class="header-side"> <div class="header-side">
{uiState === 'loading' ? ( <Menu
<Loader abrupt /> align="end"
) : ( portal={{
<Menu // Need this, else the menu click will cause scroll jump
align="end" target: scrollableRef.current,
portal={{ }}
// Need this, else the menu click will cause scroll jump menuButton={
target: scrollableRef.current, <button type="button" class="button plain4">
<Icon icon="more" alt="Actions" size="xl" />
</button>
}
>
<MenuItem
disabled={uiState === 'loading'}
onClick={() => {
states.reloadStatusPage++;
}} }}
menuButton={
<button type="button" class="button plain4">
<Icon icon="more" alt="Actions" size="xl" />
</button>
}
> >
<MenuItem <Icon icon="refresh" />
disabled={uiState === 'loading'} <span>Refresh</span>
onClick={() => { </MenuItem>
states.reloadStatusPage++; <MenuItem
}} onClick={() => {
> // Click all buttons with class .spoiler but not .spoiling
<Icon icon="refresh" /> const buttons = Array.from(
<span>Refresh</span> scrollableRef.current.querySelectorAll(
</MenuItem> 'button.spoiler:not(.spoiling)',
<MenuItem ),
onClick={() => { );
// Click all buttons with class .spoiler but not .spoiling buttons.forEach((button) => {
const buttons = Array.from( button.click();
scrollableRef.current.querySelectorAll( });
'button.spoiler:not(.spoiling)', }}
), >
); <Icon icon="eye-open" /> <span>Show all sensitive content</span>
buttons.forEach((button) => { </MenuItem>
button.click(); <MenuDivider />
}); <MenuHeader className="plain">Experimental</MenuHeader>
}} <MenuItem
> disabled={postSameInstance}
<Icon icon="eye-open" />{' '} onClick={() => {
<span>Show all sensitive content</span> const statusURL = getInstanceStatusURL(heroStatus.url);
</MenuItem> if (statusURL) {
<MenuDivider /> location.hash = statusURL;
<MenuHeader className="plain">Experimental</MenuHeader> } else {
<MenuItem alert('Unable to switch');
disabled={postSameInstance} }
onClick={() => { }}
const statusURL = getInstanceStatusURL(heroStatus.url); >
if (statusURL) { <Icon icon="transfer" />
location.hash = statusURL; <small class="menu-double-lines">
} else { Switch to post's instance (<b>{postInstance}</b>)
alert('Unable to switch'); </small>
} </MenuItem>
}} </Menu>
>
<Icon icon="transfer" />
<small class="menu-double-lines">
Switch to post's instance (<b>{postInstance}</b>)
</small>
</MenuItem>
</Menu>
)}
<Link class="button plain deck-close" to={closeLink}> <Link class="button plain deck-close" to={closeLink}>
<Icon icon="x" size="xl" /> <Icon icon="x" size="xl" />
</Link> </Link>