fix: Custom scrollIntoView function with offsets and onFocus handlers for containers

This commit is contained in:
Aleksi Lassila
2024-04-05 12:51:11 +03:00
parent 754227737b
commit b436e809de
12 changed files with 275 additions and 162 deletions

View File

@@ -7,7 +7,7 @@
import type { TitleType } from '../../types';
import Container from '../../../Container.svelte';
import { useNavigate } from 'svelte-navigator';
import { scrollWithOffset } from '../../selectable';
import { scrollIntoView } from '../../selectable';
export let tmdbId: number | undefined = undefined;
export let tvdbId: number | undefined = undefined;

View File

@@ -1,7 +1,6 @@
<script lang="ts">
import Container from '../../Container.svelte';
import { onMount } from 'svelte';
import { scrollWithOffset } from '../selectable';
let cols: number = 1;
const calculateRows = () => {
@@ -25,7 +24,6 @@
<Container
direction="grid"
gridCols={cols}
childrenRevealStrategy={scrollWithOffset('all', 50)}
class="grid gap-x-4 gap-y-8 grid-cols-2 md:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5"
>
<slot />

View File

@@ -3,7 +3,6 @@
import { ChevronLeft, ChevronRight } from 'radix-icons-svelte';
import classNames from 'classnames';
import Container from '../../../Container.svelte';
import { scrollWithOffset } from '../../selectable';
export let gradientFromColor = 'from-stone-950';
export let heading = '';
@@ -45,11 +44,7 @@
</div>
<div class="relative">
<Container
childrenRevealStrategy={scrollWithOffset('left', 64 + 16)}
direction="horizontal"
navigationActions={{ left: () => true }}
>
<Container direction="horizontal" navigationActions={{ left: () => true }}>
<div
class={classNames(
'flex overflow-x-scroll items-center overflow-y-visible relative scrollbar-hide',

View File

@@ -32,6 +32,7 @@
}black 5%, black 95%, ${fadeRight ? '' : 'black 100%, '}transparent 100%);`}
on:scroll={updateScrollPosition}
bind:this={element}
navigationActions={{ left: () => true }}
>
<slot />
</Container>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import Container from '../../../Container.svelte';
import HeroShowcaseBackground from './HeroBackground.svelte';
import { scrollWithOffset, Selectable } from '../../selectable';
import { scrollIntoView, Selectable } from '../../selectable';
import IconButton from '../IconButton.svelte';
import { ChevronRight } from 'radix-icons-svelte';
import PageDots from '../HeroShowcase/PageDots.svelte';
@@ -42,7 +42,6 @@
<Container class="flex-1 flex">
<HeroShowcaseBackground {urls} {index} />
<Container
revealStrategy={scrollWithOffset('up', 0)}
navigationActions={{
right: onNext,
left: onPrevious,

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import type { TmdbEpisode, TmdbSeason } from '../../apis/tmdb/tmdb-api';
import type { TmdbEpisode } from '../../apis/tmdb/tmdb-api';
import Container from '../../../Container.svelte';
import classNames from 'classnames';
import { TMDB_BACKDROP_SMALL } from '../../constants';

View File

@@ -6,7 +6,7 @@
import { tmdbApi, type TmdbSeason, type TmdbSeriesFull2 } from '../../apis/tmdb/tmdb-api';
import Carousel from '../Carousel/Carousel.svelte';
import Container from '../../../Container.svelte';
import { scrollWithOffset } from '../../selectable';
import { scrollElementIntoView, scrollIntoView } from '../../selectable';
import UICarousel from '../Carousel/UICarousel.svelte';
import classNames from 'classnames';
@@ -20,8 +20,22 @@
(series) => (series?.seasons?.length ? ([series.seasons.length] as const) : undefined)
);
const episodeContainers: Record<string, Container> = {};
function handleSelectSeason(season: TmdbSeason) {
console.log(season);
const episode = season.episodes?.[0];
if (episode) {
console.log(
episode,
episodeContainers,
`episode-${episode.id}`,
episodeContainers[`episode-${episode.id}`]
);
const selectable = episodeContainers[`episode-${episode.id}`]?.container;
if (selectable) {
selectable.focus(false);
}
}
}
</script>
@@ -35,6 +49,11 @@
let:hasFocus
class="mx-2 text-nowrap"
on:click={() => handleSelectSeason(season)}
handleFocus={(s) => {
const element = s.getHtmlElement();
if (element) scrollElementIntoView(element, { horizontal: 64 });
handleSelectSeason(season);
}}
>
<div
class={classNames({
@@ -50,9 +69,13 @@
<div class="flex">
{#each $tmdbSeasons as season}
{#each season?.episodes || [] as episode}
<div class="mx-2">
<Container
class="mx-2"
bind:this={episodeContainers[`episode-${episode.id}`]}
handleFocus={scrollIntoView({ left: 64 + 16 })}
>
<EpisodeCard {episode} />
</div>
</Container>
{/each}
{/each}
</div>

View File

@@ -16,6 +16,7 @@
import ManageMediaModal from '../ManageMedia/ManageMediaModal.svelte';
import { derived } from 'svelte/store';
import EpisodeCarousel from './EpisodeCarousel.svelte';
import { scrollIntoView } from '../../selectable';
export let id: string;
@@ -46,7 +47,10 @@
</script>
<DetachedPage>
<div class="h-screen flex flex-col py-12 px-20 relative">
<Container
class="h-screen flex flex-col py-12 px-20 relative"
handleFocus={scrollIntoView({ top: 0 })}
>
<HeroCarousel
urls={$tmdbSeries.then(
(series) =>
@@ -143,6 +147,8 @@
{/await}
</div>
</HeroCarousel>
</div>
<EpisodeCarousel id={Number(id)} tmdbSeries={tmdbSeriesData} />
</Container>
<Container handleFocus={scrollIntoView({ vertical: 64 })}>
<EpisodeCarousel id={Number(id)} tmdbSeries={tmdbSeriesData} />
</Container>
</DetachedPage>