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
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 { Link } from 'preact-router/match';
|
||||
import {
|
||||
|
@ -7,15 +9,18 @@ import {
|
|||
useRef,
|
||||
useState,
|
||||
} from 'preact/hooks';
|
||||
import { InView } from 'react-intersection-observer';
|
||||
import { useSnapshot } from 'valtio';
|
||||
|
||||
import Icon from '../components/icon';
|
||||
import Loader from '../components/loader';
|
||||
import NameText from '../components/name-text';
|
||||
import Status from '../components/status';
|
||||
import htmlContentLength from '../utils/html-content-length';
|
||||
import shortenNumber from '../utils/shorten-number';
|
||||
import states from '../utils/states';
|
||||
import store from '../utils/store';
|
||||
import useDebouncedCallback from '../utils/useDebouncedCallback';
|
||||
import useTitle from '../utils/useTitle';
|
||||
|
||||
const LIMIT = 40;
|
||||
|
@ -243,6 +248,9 @@ function StatusPage({ id }) {
|
|||
const hasManyStatuses = statuses.length > LIMIT;
|
||||
const hasDescendants = statuses.some((s) => s.descendant);
|
||||
|
||||
const [heroInView, setHeroInView] = useState(true);
|
||||
const onView = useDebouncedCallback(setHeroInView, 100);
|
||||
|
||||
return (
|
||||
<div class="deck-backdrop">
|
||||
<Link href={closeLink}></Link>
|
||||
|
@ -252,13 +260,43 @@ function StatusPage({ id }) {
|
|||
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>
|
||||
<Link class="button plain deck-close" href={closeLink}>
|
||||
<Icon icon="chevron-left" size="xl" />
|
||||
</Link>
|
||||
</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">
|
||||
<Loader hidden={uiState !== 'loading'} />
|
||||
<Link class="button plain deck-close" href={closeLink}>
|
||||
|
@ -289,7 +327,9 @@ function StatusPage({ id }) {
|
|||
} ${thread ? 'thread' : ''} ${isHero ? 'hero' : ''}`}
|
||||
>
|
||||
{isHero ? (
|
||||
<Status statusID={statusID} withinContext size="l" />
|
||||
<InView threshold={0.5} onChange={onView}>
|
||||
<Status statusID={statusID} withinContext size="l" />
|
||||
</InView>
|
||||
) : (
|
||||
<Link
|
||||
class="
|
||||
|
|
Loading…
Reference in a new issue