Fix carousel actually not working properly
- Need intersection observer to tell JS that scroll snap happened - Fix carousel dots not working - Add fancy background overlay based on image average color - Disable fade out if open in carousel
This commit is contained in:
parent
be5a5cbd7c
commit
aeceb94219
16
src/app.css
16
src/app.css
|
@ -349,7 +349,8 @@ a.hashtag {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.carousel-button {
|
button.carousel-button,
|
||||||
|
button.carousel-dot {
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
@ -360,7 +361,12 @@ button.carousel-button[hidden] {
|
||||||
}
|
}
|
||||||
.carousel-dots {
|
.carousel-dots {
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
backdrop-filter: blur(12px);
|
backdrop-filter: blur(12px) invert(.25) brightness(1.5);
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.carousel-dots {
|
||||||
|
backdrop-filter: blur(12px) brightness(.5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
button.carousel-dot {
|
button.carousel-dot {
|
||||||
color: var(--text-insignificant-color) !important;
|
color: var(--text-insignificant-color) !important;
|
||||||
|
@ -392,6 +398,12 @@ button.carousel-dot.active {
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.carousel :is(img, video) {
|
||||||
|
/* No need fade out if inside carousel */
|
||||||
|
filter: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* COMPOSE BUTTON */
|
/* COMPOSE BUTTON */
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import './status.css';
|
||||||
import { getBlurHashAverageColor } from 'fast-blurhash';
|
import { getBlurHashAverageColor } from 'fast-blurhash';
|
||||||
import mem from 'mem';
|
import mem from 'mem';
|
||||||
import { useEffect, useRef, useState } from 'preact/hooks';
|
import { useEffect, useRef, useState } from 'preact/hooks';
|
||||||
|
import { InView } from 'react-intersection-observer';
|
||||||
import { useSnapshot } from 'valtio';
|
import { useSnapshot } from 'valtio';
|
||||||
|
|
||||||
import Modal from '../components/modal';
|
import Modal from '../components/modal';
|
||||||
|
@ -477,7 +478,7 @@ function Status({ statusID, status, withinContext, size = 'm', skeleton }) {
|
||||||
const prevShowMediaModal = useRef(showMediaModal);
|
const prevShowMediaModal = useRef(showMediaModal);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (showMediaModal !== false) {
|
if (showMediaModal !== false) {
|
||||||
carouselFocusItem.current?.scrollIntoView({
|
carouselFocusItem.current?.node?.scrollIntoView({
|
||||||
behavior: prevShowMediaModal.current === false ? 'auto' : 'smooth',
|
behavior: prevShowMediaModal.current === false ? 'auto' : 'smooth',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -498,6 +499,8 @@ function Status({ statusID, status, withinContext, size = 'm', skeleton }) {
|
||||||
|
|
||||||
const [actionsUIState, setActionsUIState] = useState(null); // boost-loading, favourite-loading, bookmark-loading
|
const [actionsUIState, setActionsUIState] = useState(null); // boost-loading, favourite-loading, bookmark-loading
|
||||||
|
|
||||||
|
const carouselRef = useRef(null);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={`status ${
|
class={`status ${
|
||||||
|
@ -802,6 +805,7 @@ function Status({ statusID, status, withinContext, size = 'm', skeleton }) {
|
||||||
{showMediaModal !== false && (
|
{showMediaModal !== false && (
|
||||||
<Modal>
|
<Modal>
|
||||||
<div
|
<div
|
||||||
|
ref={carouselRef}
|
||||||
class="carousel"
|
class="carousel"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
if (
|
if (
|
||||||
|
@ -813,16 +817,33 @@ function Status({ statusID, status, withinContext, size = 'm', skeleton }) {
|
||||||
}}
|
}}
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
{mediaAttachments?.map((media, i) => (
|
{mediaAttachments?.map((media, i) => {
|
||||||
<div
|
const { blurhash } = media;
|
||||||
class="carousel-item"
|
const rgbAverageColor = blurhash
|
||||||
tabindex="0"
|
? getBlurHashAverageColor(blurhash)
|
||||||
key={media.id}
|
: null;
|
||||||
ref={i === showMediaModal ? carouselFocusItem : null}
|
return (
|
||||||
>
|
<InView
|
||||||
<Media media={media} showOriginal />
|
class="carousel-item"
|
||||||
</div>
|
style={{
|
||||||
))}
|
backgroundColor: `rgba(${rgbAverageColor.join(',')}, .5)`,
|
||||||
|
}}
|
||||||
|
tabindex="0"
|
||||||
|
key={media.id}
|
||||||
|
ref={i === showMediaModal ? carouselFocusItem : null}
|
||||||
|
// InView options
|
||||||
|
root={carouselRef.current}
|
||||||
|
threshold={1}
|
||||||
|
onChange={(inView) => {
|
||||||
|
if (inView) {
|
||||||
|
setShowMediaModal(i);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Media media={media} showOriginal />
|
||||||
|
</InView>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div class="carousel-top-controls">
|
<div class="carousel-top-controls">
|
||||||
<span />
|
<span />
|
||||||
|
|
|
@ -123,7 +123,7 @@ button > * {
|
||||||
:is(button, .button).plain {
|
:is(button, .button).plain {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: var(--link-color);
|
color: var(--link-color);
|
||||||
backdrop-filter: blur(12px);
|
backdrop-filter: blur(12px) invert(.25) brightness(1.5);
|
||||||
}
|
}
|
||||||
:is(button, .button).light {
|
:is(button, .button).light {
|
||||||
background-color: var(--bg-faded-color);
|
background-color: var(--bg-faded-color);
|
||||||
|
@ -170,6 +170,9 @@ select.plain {
|
||||||
img:hover, video:hover {
|
img:hover, video:hover {
|
||||||
filter: brightness(1);
|
filter: brightness(1);
|
||||||
}
|
}
|
||||||
|
:is(button, .button).plain {
|
||||||
|
backdrop-filter: blur(12px) brightness(.5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* UTILS */
|
/* UTILS */
|
||||||
|
|
Loading…
Reference in a new issue