mirror of
https://github.com/cheeaun/phanpy.git
synced 2025-02-02 06:06:41 +01:00
Smart status heading + tap to scroll to hero status
I'll probably need to componentize relative-time, it's getting not DRY
This commit is contained in:
parent
17ac9cc2c6
commit
ec67811823
2 changed files with 72 additions and 3 deletions
29
src/pages/status.css
Normal file
29
src/pages/status.css
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
.status-deck header h1 {
|
||||||
|
grid-column: 1 / 3;
|
||||||
|
}
|
||||||
|
.status-deck header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.status-deck header h1 {
|
||||||
|
min-width: 0;
|
||||||
|
flex-grow: 1;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-deck header.inview h1 {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-heading {
|
||||||
|
font-size: 16px;
|
||||||
|
pointer-events: none;
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
.hero-heading .insignificant {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
import './status.css';
|
||||||
|
|
||||||
import debounce from 'just-debounce-it';
|
import debounce from 'just-debounce-it';
|
||||||
import { Link } from 'preact-router/match';
|
import { Link } from 'preact-router/match';
|
||||||
import {
|
import {
|
||||||
|
@ -7,15 +9,18 @@ import {
|
||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
} from 'preact/hooks';
|
} from 'preact/hooks';
|
||||||
|
import { InView } from 'react-intersection-observer';
|
||||||
import { useSnapshot } from 'valtio';
|
import { useSnapshot } from 'valtio';
|
||||||
|
|
||||||
import Icon from '../components/icon';
|
import Icon from '../components/icon';
|
||||||
import Loader from '../components/loader';
|
import Loader from '../components/loader';
|
||||||
|
import NameText from '../components/name-text';
|
||||||
import Status from '../components/status';
|
import Status from '../components/status';
|
||||||
import htmlContentLength from '../utils/html-content-length';
|
import htmlContentLength from '../utils/html-content-length';
|
||||||
import shortenNumber from '../utils/shorten-number';
|
import shortenNumber from '../utils/shorten-number';
|
||||||
import states from '../utils/states';
|
import states from '../utils/states';
|
||||||
import store from '../utils/store';
|
import store from '../utils/store';
|
||||||
|
import useDebouncedCallback from '../utils/useDebouncedCallback';
|
||||||
import useTitle from '../utils/useTitle';
|
import useTitle from '../utils/useTitle';
|
||||||
|
|
||||||
const LIMIT = 40;
|
const LIMIT = 40;
|
||||||
|
@ -243,6 +248,9 @@ function StatusPage({ id }) {
|
||||||
const hasManyStatuses = statuses.length > LIMIT;
|
const hasManyStatuses = statuses.length > LIMIT;
|
||||||
const hasDescendants = statuses.some((s) => s.descendant);
|
const hasDescendants = statuses.some((s) => s.descendant);
|
||||||
|
|
||||||
|
const [heroInView, setHeroInView] = useState(true);
|
||||||
|
const onView = useDebouncedCallback(setHeroInView, 100);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="deck-backdrop">
|
<div class="deck-backdrop">
|
||||||
<Link href={closeLink}></Link>
|
<Link href={closeLink}></Link>
|
||||||
|
@ -252,13 +260,43 @@ function StatusPage({ id }) {
|
||||||
statuses.length > 1 ? 'padded-bottom' : ''
|
statuses.length > 1 ? 'padded-bottom' : ''
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<header>
|
<header
|
||||||
|
class={`${heroInView ? 'inview' : ''}`}
|
||||||
|
onClick={(e) => {
|
||||||
|
if (
|
||||||
|
!/^(a|button)$/i.test(e.target.tagName) &&
|
||||||
|
heroStatusRef.current
|
||||||
|
) {
|
||||||
|
heroStatusRef.current.scrollIntoView({
|
||||||
|
behavior: 'smooth',
|
||||||
|
block: 'start',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
{/* <div>
|
{/* <div>
|
||||||
<Link class="button plain deck-close" href={closeLink}>
|
<Link class="button plain deck-close" href={closeLink}>
|
||||||
<Icon icon="chevron-left" size="xl" />
|
<Icon icon="chevron-left" size="xl" />
|
||||||
</Link>
|
</Link>
|
||||||
</div> */}
|
</div> */}
|
||||||
<h1>Status</h1>
|
<h1>
|
||||||
|
{!heroInView && heroStatus ? (
|
||||||
|
<span class="hero-heading">
|
||||||
|
<NameText showAvatar account={heroStatus.account} short />{' '}
|
||||||
|
<span class="insignificant">
|
||||||
|
•{' '}
|
||||||
|
<relative-time
|
||||||
|
datetime={heroStatus.createdAt}
|
||||||
|
format="micro"
|
||||||
|
threshold="P1D"
|
||||||
|
prefix=""
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
'Status'
|
||||||
|
)}
|
||||||
|
</h1>
|
||||||
<div class="header-side">
|
<div class="header-side">
|
||||||
<Loader hidden={uiState !== 'loading'} />
|
<Loader hidden={uiState !== 'loading'} />
|
||||||
<Link class="button plain deck-close" href={closeLink}>
|
<Link class="button plain deck-close" href={closeLink}>
|
||||||
|
@ -289,7 +327,9 @@ function StatusPage({ id }) {
|
||||||
} ${thread ? 'thread' : ''} ${isHero ? 'hero' : ''}`}
|
} ${thread ? 'thread' : ''} ${isHero ? 'hero' : ''}`}
|
||||||
>
|
>
|
||||||
{isHero ? (
|
{isHero ? (
|
||||||
<Status statusID={statusID} withinContext size="l" />
|
<InView threshold={0.5} onChange={onView}>
|
||||||
|
<Status statusID={statusID} withinContext size="l" />
|
||||||
|
</InView>
|
||||||
) : (
|
) : (
|
||||||
<Link
|
<Link
|
||||||
class="
|
class="
|
||||||
|
|
Loading…
Reference in a new issue