[ci] format
This commit is contained in:
parent
e6be2d8146
commit
a10a798c18
35 changed files with 83947 additions and 485 deletions
|
@ -1,15 +1,15 @@
|
||||||
import { defineConfig } from 'astro/config'
|
import { defineConfig } from 'astro/config';
|
||||||
import tailwind from '@astrojs/tailwind';
|
import tailwind from '@astrojs/tailwind';
|
||||||
import nodejs from '@astrojs/node';
|
import nodejs from '@astrojs/node';
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
integrations: [tailwind()],
|
integrations: [tailwind()],
|
||||||
output: 'server',
|
output: 'server',
|
||||||
adapter: nodejs({ mode: 'standalone' }),
|
adapter: nodejs({ mode: 'standalone' }),
|
||||||
vite: {
|
vite: {
|
||||||
define: {
|
define: {
|
||||||
'process.env.TMDB_API_KEY': JSON.stringify(process.env.TMDB_API_KEY),
|
'process.env.TMDB_API_KEY': JSON.stringify(process.env.TMDB_API_KEY),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
<footer class="border border-t border-gray-800">
|
<footer class="border border-t border-gray-800">
|
||||||
<div class="container mx-auto text-sm px-4 py-6">
|
<div class="container mx-auto text-sm px-4 py-6">
|
||||||
Made with ❤️ by <a
|
Made with ❤️ by <a
|
||||||
href="https://www.twitter.com/charca"
|
href="https://www.twitter.com/charca"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="underline hover:text-gray-300">Maxi Ferreira</a
|
class="underline hover:text-gray-300">Maxi Ferreira</a
|
||||||
> — Powered by <a
|
> — Powered by <a
|
||||||
href="https://astro.build"
|
href="https://astro.build"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="underline hover:text-gray-300">Astro</a
|
class="underline hover:text-gray-300">Astro</a
|
||||||
> and <a
|
> and <a
|
||||||
href="https://www.themoviedb.org/documentation/api"
|
href="https://www.themoviedb.org/documentation/api"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="underline hover:text-gray-300">TMDb API</a
|
class="underline hover:text-gray-300">TMDb API</a
|
||||||
>.
|
>.
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
@ -3,21 +3,29 @@ const { movie } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="mt-8">
|
<div class="mt-8">
|
||||||
<a href={`/movies/${movie.id}`}>
|
<a href={`/movies/${movie.id}`}>
|
||||||
<img src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
|
<img
|
||||||
alt={`${movie.title} Poster`}
|
src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
|
||||||
class="thumbnail hover:opacity-75 transition ease-in-out duration-150"
|
alt={`${movie.title} Poster`}
|
||||||
id={`movie-poster-${movie.id}`}
|
class="thumbnail hover:opacity-75 transition ease-in-out duration-150"
|
||||||
transition:name={`poster-${movie.id}`}>
|
id={`movie-poster-${movie.id}`}
|
||||||
</a>
|
transition:name={`poster-${movie.id}`}
|
||||||
<div class="mt-2">
|
/>
|
||||||
<a href={`/movies/${movie.id}`} class="text-lg mt-2 hover:text-gray-300">{movie.title}</a>
|
</a>
|
||||||
<div class="flex items-center text-gray-400 text-sm mt-1">
|
<div class="mt-2">
|
||||||
<svg class="fill-current text-orange-500 w-4" viewBox="0 0 24 24"><g data-name="Layer 2"><path d="M17.56 21a1 1 0 01-.46-.11L12 18.22l-5.1 2.67a1 1 0 01-1.45-1.06l1-5.63-4.12-4a1 1 0 01-.25-1 1 1 0 01.81-.68l5.7-.83 2.51-5.13a1 1 0 011.8 0l2.54 5.12 5.7.83a1 1 0 01.81.68 1 1 0 01-.25 1l-4.12 4 1 5.63a1 1 0 01-.4 1 1 1 0 01-.62.18z" data-name="star"/></g></svg>
|
<a href={`/movies/${movie.id}`} class="text-lg mt-2 hover:text-gray-300">{movie.title}</a>
|
||||||
<span class="ml-1">{movie.vote_average}</span>
|
<div class="flex items-center text-gray-400 text-sm mt-1">
|
||||||
<span class="mx-2">|</span>
|
<svg class="fill-current text-orange-500 w-4" viewBox="0 0 24 24"
|
||||||
<span>{movie.release_date}</span>
|
><g data-name="Layer 2"
|
||||||
</div>
|
><path
|
||||||
<div class="text-gray-400 text-sm">{movie.genres}</div>
|
d="M17.56 21a1 1 0 01-.46-.11L12 18.22l-5.1 2.67a1 1 0 01-1.45-1.06l1-5.63-4.12-4a1 1 0 01-.25-1 1 1 0 01.81-.68l5.7-.83 2.51-5.13a1 1 0 011.8 0l2.54 5.12 5.7.83a1 1 0 01.81.68 1 1 0 01-.25 1l-4.12 4 1 5.63a1 1 0 01-.4 1 1 1 0 01-.62.18z"
|
||||||
</div>
|
data-name="star"></path></g
|
||||||
|
></svg
|
||||||
|
>
|
||||||
|
<span class="ml-1">{movie.vote_average}</span>
|
||||||
|
<span class="mx-2">|</span>
|
||||||
|
<span>{movie.release_date}</span>
|
||||||
|
</div>
|
||||||
|
<div class="text-gray-400 text-sm">{movie.genres}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,99 +2,124 @@
|
||||||
const { data } = Astro.props;
|
const { data } = Astro.props;
|
||||||
|
|
||||||
const movie = {
|
const movie = {
|
||||||
...data,
|
...data,
|
||||||
poster_path: data.poster_path
|
poster_path: data.poster_path
|
||||||
? 'https://image.tmdb.org/t/p/w500/' + data.poster_path
|
? 'https://image.tmdb.org/t/p/w500/' + data.poster_path
|
||||||
: 'https://via.placeholder.com/500x750',
|
: 'https://via.placeholder.com/500x750',
|
||||||
vote_average: (data.vote_average * 10).toFixed(2) + '%',
|
vote_average: (data.vote_average * 10).toFixed(2) + '%',
|
||||||
release_date: new Date(data.release_date).toLocaleDateString('en-us', {
|
release_date: new Date(data.release_date).toLocaleDateString('en-us', {
|
||||||
year: 'numeric',
|
year: 'numeric',
|
||||||
month: 'long',
|
month: 'long',
|
||||||
day: 'numeric'
|
day: 'numeric',
|
||||||
}),
|
}),
|
||||||
genres: data.genres.map((g: any) => g.name).join(', '),
|
genres: data.genres.map((g: any) => g.name).join(', '),
|
||||||
crew: data.credits.crew.slice(0,3),
|
crew: data.credits.crew.slice(0, 3),
|
||||||
cast: data.credits.cast.slice(0,5).map((c: any) => ({
|
cast: data.credits.cast.slice(0, 5).map((c: any) => ({
|
||||||
...c,
|
...c,
|
||||||
profile_path: c.profile_path
|
profile_path: c.profile_path
|
||||||
? 'https://image.tmdb.org/t/p/w300/' + c.profile_path
|
? 'https://image.tmdb.org/t/p/w300/' + c.profile_path
|
||||||
: 'https://via.placeholder.com/300x450'
|
: 'https://via.placeholder.com/300x450',
|
||||||
})),
|
})),
|
||||||
images: data.images.backdrops.slice(0, 9),
|
images: data.images.backdrops.slice(0, 9),
|
||||||
}
|
};
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="movie-info border-b border-gray-800">
|
<div class="movie-info border-b border-gray-800">
|
||||||
<div class="container mx-auto px-4 py-16 flex flex-col md:flex-row">
|
<div class="container mx-auto px-4 py-16 flex flex-col md:flex-row">
|
||||||
<div class="flex-none">
|
<div class="flex-none">
|
||||||
<img src={movie.poster_path}
|
<img
|
||||||
alt={`${movie.title} Poster`}
|
src={movie.poster_path}
|
||||||
class="movie-poster w-64 lg:w-96"
|
alt={`${movie.title} Poster`}
|
||||||
id="movie-poster"
|
class="movie-poster w-64 lg:w-96"
|
||||||
transition:name={`poster-${movie.id}`}>
|
id="movie-poster"
|
||||||
</div>
|
transition:name={`poster-${movie.id}`}
|
||||||
<div class="md:ml-24">
|
/>
|
||||||
<h2 class="text-4xl mt-4 md:mt-0 mb-2 font-semibold">{movie.title}</h2>
|
</div>
|
||||||
<div class="flex flex-wrap items-center text-gray-400 text-sm">
|
<div class="md:ml-24">
|
||||||
<svg class="fill-current text-orange-500 w-4" viewBox="0 0 24 24"><g data-name="Layer 2"><path d="M17.56 21a1 1 0 01-.46-.11L12 18.22l-5.1 2.67a1 1 0 01-1.45-1.06l1-5.63-4.12-4a1 1 0 01-.25-1 1 1 0 01.81-.68l5.7-.83 2.51-5.13a1 1 0 011.8 0l2.54 5.12 5.7.83a1 1 0 01.81.68 1 1 0 01-.25 1l-4.12 4 1 5.63a1 1 0 01-.4 1 1 1 0 01-.62.18z" data-name="star"/></g></svg>
|
<h2 class="text-4xl mt-4 md:mt-0 mb-2 font-semibold">{movie.title}</h2>
|
||||||
<span class="ml-1">{movie.vote_average}</span>
|
<div class="flex flex-wrap items-center text-gray-400 text-sm">
|
||||||
<span class="mx-2">|</span>
|
<svg class="fill-current text-orange-500 w-4" viewBox="0 0 24 24"
|
||||||
<span>{movie.release_date}</span>
|
><g data-name="Layer 2"
|
||||||
<span class="mx-2">|</span>
|
><path
|
||||||
<span>{movie.genres}</span>
|
d="M17.56 21a1 1 0 01-.46-.11L12 18.22l-5.1 2.67a1 1 0 01-1.45-1.06l1-5.63-4.12-4a1 1 0 01-.25-1 1 1 0 01.81-.68l5.7-.83 2.51-5.13a1 1 0 011.8 0l2.54 5.12 5.7.83a1 1 0 01.81.68 1 1 0 01-.25 1l-4.12 4 1 5.63a1 1 0 01-.4 1 1 1 0 01-.62.18z"
|
||||||
</div>
|
data-name="star"></path></g
|
||||||
|
></svg
|
||||||
|
>
|
||||||
|
<span class="ml-1">{movie.vote_average}</span>
|
||||||
|
<span class="mx-2">|</span>
|
||||||
|
<span>{movie.release_date}</span>
|
||||||
|
<span class="mx-2">|</span>
|
||||||
|
<span>{movie.genres}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<p class="text-gray-300 mt-8">
|
<p class="text-gray-300 mt-8">
|
||||||
{movie.overview}
|
{movie.overview}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="mt-12">
|
<div class="mt-12">
|
||||||
<h4 class="text-white font-semibold">Featured Crew</h4>
|
<h4 class="text-white font-semibold">Featured Crew</h4>
|
||||||
<div class="flex mt-4">
|
<div class="flex mt-4">
|
||||||
{movie.crew.map((crew: any) => (
|
{
|
||||||
<div class="mr-8">
|
movie.crew.map((crew: any) => (
|
||||||
<div>{crew.name}</div>
|
<div class="mr-8">
|
||||||
<div class="text-gray-400 text-sm">{crew.job}</div>
|
<div>{crew.name}</div>
|
||||||
</div>
|
<div class="text-gray-400 text-sm">{crew.job}</div>
|
||||||
))}
|
</div>
|
||||||
</div>
|
))
|
||||||
</div>
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> <!-- end movie-info -->
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- end movie-info -->
|
||||||
|
|
||||||
<div class="movie-cast border-b border-gray-800">
|
<div class="movie-cast border-b border-gray-800">
|
||||||
<div class="container mx-auto px-4 py-16">
|
<div class="container mx-auto px-4 py-16">
|
||||||
<h2 class="text-4xl font-semibold">Cast</h2>
|
<h2 class="text-4xl font-semibold">Cast</h2>
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-8">
|
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-8">
|
||||||
{movie.cast.map((cast: any) => (
|
{
|
||||||
<div class="mt-8">
|
movie.cast.map((cast: any) => (
|
||||||
<span>
|
<div class="mt-8">
|
||||||
<img id={`person-photo-${cast.id}`} src={cast.profile_path} alt={cast.name} class="thumbnail hover:opacity-75 transition ease-in-out duration-150">
|
<span>
|
||||||
</span>
|
<img
|
||||||
<div class="mt-2">
|
id={`person-photo-${cast.id}`}
|
||||||
<span class="text-lg mt-2 hover:text-gray:300">{cast.name}</span>
|
src={cast.profile_path}
|
||||||
<div class="text-sm text-gray-400">
|
alt={cast.name}
|
||||||
{cast.character}
|
class="thumbnail hover:opacity-75 transition ease-in-out duration-150"
|
||||||
</div>
|
/>
|
||||||
</div>
|
</span>
|
||||||
</div>
|
<div class="mt-2">
|
||||||
))}
|
<span class="text-lg mt-2 hover:text-gray:300">{cast.name}</span>
|
||||||
</div>
|
<div class="text-sm text-gray-400">{cast.character}</div>
|
||||||
</div>
|
</div>
|
||||||
</div> <!-- end movie-cast -->
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- end movie-cast -->
|
||||||
|
|
||||||
<div class="movie-images">
|
<div class="movie-images">
|
||||||
<div class="container mx-auto px-4 py-16">
|
<div class="container mx-auto px-4 py-16">
|
||||||
<h2 class="text-4xl font-semibold">Images</h2>
|
<h2 class="text-4xl font-semibold">Images</h2>
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-8">
|
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-8">
|
||||||
{movie.images.map((image: any) => (
|
{
|
||||||
<div class="mt-8">
|
movie.images.map((image: any) => (
|
||||||
<span>
|
<div class="mt-8">
|
||||||
<img src={`https://image.tmdb.org/t/p/w500${image.file_path}`} loading="lazy" alt={movie.name} class="hover:opacity-75 transition ease-in-out duration-150">
|
<span>
|
||||||
</span>
|
<img
|
||||||
</div>
|
src={`https://image.tmdb.org/t/p/w500${image.file_path}`}
|
||||||
))}
|
loading="lazy"
|
||||||
</div>
|
alt={movie.name}
|
||||||
</div>
|
class="hover:opacity-75 transition ease-in-out duration-150"
|
||||||
</div> <!-- end movie-images -->
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- end movie-images -->
|
||||||
|
|
|
@ -5,15 +5,11 @@ const popularMovies = movies.results;
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="container mx-auto px-4 pt-16 mb-16">
|
<div class="container mx-auto px-4 pt-16 mb-16">
|
||||||
<div class="popular-movies">
|
<div class="popular-movies">
|
||||||
<h2 class="uppercase tracking-wider text-orange-500 text-lg font-semibold">
|
<h2 class="uppercase tracking-wider text-orange-500 text-lg font-semibold">Popular Movies</h2>
|
||||||
Popular Movies
|
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-8">
|
||||||
</h2>
|
{popularMovies.map((movie) => <MovieCard movie={movie} />)}
|
||||||
<div
|
</div>
|
||||||
class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-8"
|
</div>
|
||||||
>
|
<!-- end pouplar-movies -->
|
||||||
{popularMovies.map((movie) => <MovieCard movie={movie} />)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- end pouplar-movies -->
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
<nav class="nav border-b border-gray-800 sticky top-0 z-30 bg-gray-900">
|
<nav class="nav border-b border-gray-800 sticky top-0 z-30 bg-gray-900">
|
||||||
<div class="container mx-auto px-4 flex flex-col md:flex-row items-center justify-between px-4 py-6">
|
<div
|
||||||
<ul class="flex flex-col md:flex-row items-center">
|
class="container mx-auto px-4 flex flex-col md:flex-row items-center justify-between px-4 py-6"
|
||||||
<li>
|
>
|
||||||
<a href="/" class="flex items-center font-bold text-xl">
|
<ul class="flex flex-col md:flex-row items-center">
|
||||||
<span>Movies</span>
|
<li>
|
||||||
|
<a href="/" class="flex items-center font-bold text-xl">
|
||||||
<span class="text-orange-500">List</span>
|
<span>Movies</span>
|
||||||
</a>
|
|
||||||
</li>
|
<span class="text-orange-500">List</span>
|
||||||
<li class="md:ml-16 mt-3 md:mt-0">
|
</a>
|
||||||
<a href="/" class="hover:text-gray-300">Movies</a>
|
</li>
|
||||||
</li>
|
<li class="md:ml-16 mt-3 md:mt-0">
|
||||||
</ul>
|
<a href="/" class="hover:text-gray-300">Movies</a>
|
||||||
</div>
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { z, defineCollection } from 'astro:content';
|
import { z, defineCollection } from 'astro:content';
|
||||||
|
|
||||||
const movies = defineCollection({
|
const movies = defineCollection({
|
||||||
type: 'data',
|
type: 'data',
|
||||||
schema: z.object({
|
schema: z.object({
|
||||||
data: z.any(),
|
data: z.any(),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Expose your defined collection to Astro
|
// Expose your defined collection to Astro
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
import '../styles/styles.css';
|
import '../styles/styles.css';
|
||||||
import { ViewTransitions } from 'astro:transitions';
|
import { ViewTransitions } from 'astro:transitions';
|
||||||
import Footer from "../components/Footer.astro";
|
import Footer from '../components/Footer.astro';
|
||||||
import Nav from "../components/Nav.astro";
|
import Nav from '../components/Nav.astro';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -11,7 +11,7 @@ export interface Props {
|
||||||
const { title } = Astro.props as Props;
|
const { title } = Astro.props as Props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
|
|
|
@ -4,11 +4,11 @@ import MovieDetails from '../../components/MovieDetails.astro';
|
||||||
import { getDataEntryById } from 'astro:content';
|
import { getDataEntryById } from 'astro:content';
|
||||||
|
|
||||||
// Data collection bug?
|
// Data collection bug?
|
||||||
const id: any = '/src/content/movies/'+Astro.params.id;
|
const id: any = '/src/content/movies/' + Astro.params.id;
|
||||||
const result = await getDataEntryById('movies', id);
|
const result = await getDataEntryById('movies', id);
|
||||||
const data = result.data.data;
|
const data = result.data.data;
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title={`${data.title} on Movies List`}>
|
<Layout title={`${data.title} on Movies List`}>
|
||||||
<MovieDetails data={data} />
|
<MovieDetails data={data} />
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,262 +1,254 @@
|
||||||
import {
|
import {
|
||||||
getNavigationType,
|
getNavigationType,
|
||||||
getPathId,
|
getPathId,
|
||||||
isBackNavigation,
|
isBackNavigation,
|
||||||
shouldNotIntercept,
|
shouldNotIntercept,
|
||||||
updateTheDOMSomehow,
|
updateTheDOMSomehow,
|
||||||
useTvFragment,
|
useTvFragment,
|
||||||
} from './utils'
|
} from './utils';
|
||||||
|
|
||||||
// View Transitions support cross-document navigations.
|
// View Transitions support cross-document navigations.
|
||||||
// Should compare performace.
|
// Should compare performace.
|
||||||
// https://github.com/WICG/view-transitions/blob/main/explainer.md#cross-document-same-origin-transitions
|
// https://github.com/WICG/view-transitions/blob/main/explainer.md#cross-document-same-origin-transitions
|
||||||
// https://github.com/WICG/view-transitions/blob/main/explainer.md#script-events
|
// https://github.com/WICG/view-transitions/blob/main/explainer.md#script-events
|
||||||
function shouldDisableSpa() {
|
function shouldDisableSpa() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
navigation.addEventListener('navigate', (navigateEvent) => {
|
navigation.addEventListener('navigate', (navigateEvent) => {
|
||||||
if (shouldDisableSpa()) return
|
if (shouldDisableSpa()) return;
|
||||||
if (shouldNotIntercept(navigateEvent)) return
|
if (shouldNotIntercept(navigateEvent)) return;
|
||||||
|
|
||||||
const toUrl = new URL(navigateEvent.destination.url)
|
const toUrl = new URL(navigateEvent.destination.url);
|
||||||
const toPath = toUrl.pathname
|
const toPath = toUrl.pathname;
|
||||||
const fromPath = location.pathname
|
const fromPath = location.pathname;
|
||||||
const navigationType = getNavigationType(fromPath, toPath)
|
const navigationType = getNavigationType(fromPath, toPath);
|
||||||
|
|
||||||
if (location.origin !== toUrl.origin) return
|
if (location.origin !== toUrl.origin) return;
|
||||||
|
|
||||||
switch (navigationType) {
|
switch (navigationType) {
|
||||||
case 'home-to-movie':
|
case 'home-to-movie':
|
||||||
case 'tv-to-show':
|
case 'tv-to-show':
|
||||||
handleHomeToMovieTransition(navigateEvent, getPathId(toPath))
|
handleHomeToMovieTransition(navigateEvent, getPathId(toPath));
|
||||||
break
|
break;
|
||||||
case 'movie-to-home':
|
case 'movie-to-home':
|
||||||
case 'show-to-tv':
|
case 'show-to-tv':
|
||||||
handleMovieToHomeTransition(navigateEvent, getPathId(fromPath))
|
handleMovieToHomeTransition(navigateEvent, getPathId(fromPath));
|
||||||
break
|
break;
|
||||||
case 'movie-to-person':
|
case 'movie-to-person':
|
||||||
handleMovieToPersonTransition(
|
handleMovieToPersonTransition(navigateEvent, getPathId(fromPath), getPathId(toPath));
|
||||||
navigateEvent,
|
break;
|
||||||
getPathId(fromPath),
|
case 'person-to-movie':
|
||||||
getPathId(toPath)
|
case 'person-to-show':
|
||||||
)
|
handlePersonToMovieTransition(navigateEvent, getPathId(fromPath), getPathId(toPath));
|
||||||
break
|
break;
|
||||||
case 'person-to-movie':
|
default:
|
||||||
case 'person-to-show':
|
return;
|
||||||
handlePersonToMovieTransition(
|
}
|
||||||
navigateEvent,
|
});
|
||||||
getPathId(fromPath),
|
|
||||||
getPathId(toPath)
|
|
||||||
)
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// TODO: https://developer.chrome.com/docs/web-platform/view-transitions/#transitions-as-an-enhancement
|
// TODO: https://developer.chrome.com/docs/web-platform/view-transitions/#transitions-as-an-enhancement
|
||||||
function handleHomeToMovieTransition(navigateEvent, movieId) {
|
function handleHomeToMovieTransition(navigateEvent, movieId) {
|
||||||
navigateEvent.intercept({
|
navigateEvent.intercept({
|
||||||
async handler() {
|
async handler() {
|
||||||
const fragmentUrl = useTvFragment(navigateEvent)
|
const fragmentUrl = useTvFragment(navigateEvent)
|
||||||
? '/fragments/TvDetails'
|
? '/fragments/TvDetails'
|
||||||
: '/fragments/MovieDetails'
|
: '/fragments/MovieDetails';
|
||||||
const response = await fetch(`${fragmentUrl}/${movieId}`)
|
const response = await fetch(`${fragmentUrl}/${movieId}`);
|
||||||
const data = await response.text()
|
const data = await response.text();
|
||||||
|
|
||||||
if (!document.startViewTransition) {
|
if (!document.startViewTransition) {
|
||||||
updateTheDOMSomehow(data);
|
updateTheDOMSomehow(data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const thumbnail = document.getElementById(`movie-poster-${movieId}`)
|
const thumbnail = document.getElementById(`movie-poster-${movieId}`);
|
||||||
if (thumbnail) {
|
if (thumbnail) {
|
||||||
thumbnail.style.viewTransitionName = 'movie-poster'
|
thumbnail.style.viewTransitionName = 'movie-poster';
|
||||||
}
|
}
|
||||||
|
|
||||||
const transition = document.startViewTransition(() => {
|
const transition = document.startViewTransition(() => {
|
||||||
if (thumbnail) {
|
if (thumbnail) {
|
||||||
thumbnail.style.viewTransitionName = ''
|
thumbnail.style.viewTransitionName = '';
|
||||||
}
|
}
|
||||||
document.getElementById('container').scrollTop = 0
|
document.getElementById('container').scrollTop = 0;
|
||||||
updateTheDOMSomehow(data)
|
updateTheDOMSomehow(data);
|
||||||
})
|
});
|
||||||
|
|
||||||
await transition.finished
|
await transition.finished;
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMovieToHomeTransition(navigateEvent, movieId) {
|
function handleMovieToHomeTransition(navigateEvent, movieId) {
|
||||||
navigateEvent.intercept({
|
navigateEvent.intercept({
|
||||||
scroll: 'manual',
|
scroll: 'manual',
|
||||||
async handler() {
|
async handler() {
|
||||||
const fragmentUrl = useTvFragment(navigateEvent)
|
const fragmentUrl = useTvFragment(navigateEvent)
|
||||||
? '/fragments/TvList'
|
? '/fragments/TvList'
|
||||||
: '/fragments/MovieList'
|
: '/fragments/MovieList';
|
||||||
const response = await fetch(fragmentUrl)
|
const response = await fetch(fragmentUrl);
|
||||||
const data = await response.text()
|
const data = await response.text();
|
||||||
|
|
||||||
if (!document.startViewTransition) {
|
if (!document.startViewTransition) {
|
||||||
updateTheDOMSomehow(data)
|
updateTheDOMSomehow(data);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tempHomePage = document.createElement('div')
|
const tempHomePage = document.createElement('div');
|
||||||
const moviePoster = document.getElementById(`movie-poster`)
|
const moviePoster = document.getElementById(`movie-poster`);
|
||||||
let thumbnail
|
let thumbnail;
|
||||||
|
|
||||||
// If the movie poster is not in the home page, removes the transition style so that
|
// If the movie poster is not in the home page, removes the transition style so that
|
||||||
// the poster doesn't stay on the page while transitioning
|
// the poster doesn't stay on the page while transitioning
|
||||||
tempHomePage.innerHTML = data
|
tempHomePage.innerHTML = data;
|
||||||
if (!tempHomePage.querySelector(`#movie-poster-${movieId}`)) {
|
if (!tempHomePage.querySelector(`#movie-poster-${movieId}`)) {
|
||||||
moviePoster?.classList.remove('movie-poster')
|
moviePoster?.classList.remove('movie-poster');
|
||||||
}
|
}
|
||||||
|
|
||||||
const transition = document.startViewTransition(() => {
|
const transition = document.startViewTransition(() => {
|
||||||
updateTheDOMSomehow(data)
|
updateTheDOMSomehow(data);
|
||||||
|
|
||||||
thumbnail = document.getElementById(`movie-poster-${movieId}`)
|
thumbnail = document.getElementById(`movie-poster-${movieId}`);
|
||||||
if (thumbnail) {
|
if (thumbnail) {
|
||||||
thumbnail.scrollIntoViewIfNeeded()
|
thumbnail.scrollIntoViewIfNeeded();
|
||||||
thumbnail.style.viewTransitionName = 'movie-poster'
|
thumbnail.style.viewTransitionName = 'movie-poster';
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
await transition.finished
|
await transition.finished;
|
||||||
|
|
||||||
if (thumbnail) {
|
if (thumbnail) {
|
||||||
thumbnail.style.viewTransitionName = ''
|
thumbnail.style.viewTransitionName = '';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMovieToPersonTransition(navigateEvent, movieId, personId) {
|
function handleMovieToPersonTransition(navigateEvent, movieId, personId) {
|
||||||
// TODO: https://developer.chrome.com/docs/web-platform/view-transitions/#not-a-polyfill
|
// TODO: https://developer.chrome.com/docs/web-platform/view-transitions/#not-a-polyfill
|
||||||
// ...has example of `back-transition` class applied to document
|
// ...has example of `back-transition` class applied to document
|
||||||
const isBack = isBackNavigation(navigateEvent)
|
const isBack = isBackNavigation(navigateEvent);
|
||||||
|
|
||||||
navigateEvent.intercept({
|
navigateEvent.intercept({
|
||||||
async handler() {
|
async handler() {
|
||||||
const response = await fetch('/fragments/PersonDetails/' + personId)
|
const response = await fetch('/fragments/PersonDetails/' + personId);
|
||||||
const data = await response.text()
|
const data = await response.text();
|
||||||
|
|
||||||
if (!document.startViewTransition) {
|
if (!document.startViewTransition) {
|
||||||
updateTheDOMSomehow(data)
|
updateTheDOMSomehow(data);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let personThumbnail
|
let personThumbnail;
|
||||||
let moviePoster
|
let moviePoster;
|
||||||
let movieThumbnail
|
let movieThumbnail;
|
||||||
|
|
||||||
if (!isBack) {
|
if (!isBack) {
|
||||||
// We're transitioning the person photo; we need to remove the transition of the poster
|
// We're transitioning the person photo; we need to remove the transition of the poster
|
||||||
// so that it doesn't stay on the page while transitioning
|
// so that it doesn't stay on the page while transitioning
|
||||||
moviePoster = document.getElementById(`movie-poster`)
|
moviePoster = document.getElementById(`movie-poster`);
|
||||||
if (moviePoster) {
|
if (moviePoster) {
|
||||||
moviePoster.classList.remove('movie-poster')
|
moviePoster.classList.remove('movie-poster');
|
||||||
}
|
}
|
||||||
|
|
||||||
personThumbnail = document.getElementById(`person-photo-${personId}`)
|
personThumbnail = document.getElementById(`person-photo-${personId}`);
|
||||||
if (personThumbnail) {
|
if (personThumbnail) {
|
||||||
personThumbnail.style.viewTransitionName = 'person-photo'
|
personThumbnail.style.viewTransitionName = 'person-photo';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const transition = document.startViewTransition(() => {
|
const transition = document.startViewTransition(() => {
|
||||||
updateTheDOMSomehow(data)
|
updateTheDOMSomehow(data);
|
||||||
|
|
||||||
if (personThumbnail) {
|
if (personThumbnail) {
|
||||||
personThumbnail.style.viewTransitionName = ''
|
personThumbnail.style.viewTransitionName = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isBack) {
|
if (isBack) {
|
||||||
// If we're coming back to the person page, we're transitioning
|
// If we're coming back to the person page, we're transitioning
|
||||||
// into the movie poster thumbnail, so we need to add the tag to it
|
// into the movie poster thumbnail, so we need to add the tag to it
|
||||||
movieThumbnail = document.getElementById(`movie-poster-${movieId}`)
|
movieThumbnail = document.getElementById(`movie-poster-${movieId}`);
|
||||||
if (movieThumbnail) {
|
if (movieThumbnail) {
|
||||||
movieThumbnail.scrollIntoViewIfNeeded()
|
movieThumbnail.scrollIntoViewIfNeeded();
|
||||||
movieThumbnail.style.viewTransitionName = 'movie-poster'
|
movieThumbnail.style.viewTransitionName = 'movie-poster';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('container').scrollTop = 0
|
document.getElementById('container').scrollTop = 0;
|
||||||
})
|
});
|
||||||
|
|
||||||
await transition.finished
|
await transition.finished;
|
||||||
|
|
||||||
if (movieThumbnail) {
|
if (movieThumbnail) {
|
||||||
movieThumbnail.style.viewTransitionName = ''
|
movieThumbnail.style.viewTransitionName = '';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePersonToMovieTransition(navigateEvent, personId, movieId) {
|
function handlePersonToMovieTransition(navigateEvent, personId, movieId) {
|
||||||
const isBack = isBackNavigation(navigateEvent)
|
const isBack = isBackNavigation(navigateEvent);
|
||||||
|
|
||||||
navigateEvent.intercept({
|
navigateEvent.intercept({
|
||||||
scroll: 'manual',
|
scroll: 'manual',
|
||||||
async handler() {
|
async handler() {
|
||||||
const fragmentUrl = useTvFragment(navigateEvent)
|
const fragmentUrl = useTvFragment(navigateEvent)
|
||||||
? '/fragments/TvDetails'
|
? '/fragments/TvDetails'
|
||||||
: '/fragments/MovieDetails'
|
: '/fragments/MovieDetails';
|
||||||
const response = await fetch(`${fragmentUrl}/${movieId}`)
|
const response = await fetch(`${fragmentUrl}/${movieId}`);
|
||||||
const data = await response.text()
|
const data = await response.text();
|
||||||
|
|
||||||
if (!document.startViewTransition) {
|
if (!document.startViewTransition) {
|
||||||
updateTheDOMSomehow(data)
|
updateTheDOMSomehow(data);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let thumbnail
|
let thumbnail;
|
||||||
let moviePoster
|
let moviePoster;
|
||||||
let movieThumbnail
|
let movieThumbnail;
|
||||||
|
|
||||||
if (!isBack) {
|
if (!isBack) {
|
||||||
movieThumbnail = document.getElementById(`movie-poster-${movieId}`)
|
movieThumbnail = document.getElementById(`movie-poster-${movieId}`);
|
||||||
if (movieThumbnail) {
|
if (movieThumbnail) {
|
||||||
movieThumbnail.style.viewTransitionName = 'movie-poster'
|
movieThumbnail.style.viewTransitionName = 'movie-poster';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const transition = document.startViewTransition(() => {
|
const transition = document.startViewTransition(() => {
|
||||||
updateTheDOMSomehow(data)
|
updateTheDOMSomehow(data);
|
||||||
|
|
||||||
if (isBack) {
|
if (isBack) {
|
||||||
moviePoster = document.getElementById(`movie-poster`)
|
moviePoster = document.getElementById(`movie-poster`);
|
||||||
if (moviePoster) {
|
if (moviePoster) {
|
||||||
moviePoster.classList.remove('movie-poster')
|
moviePoster.classList.remove('movie-poster');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (personId) {
|
if (personId) {
|
||||||
thumbnail = document.getElementById(`person-photo-${personId}`)
|
thumbnail = document.getElementById(`person-photo-${personId}`);
|
||||||
if (thumbnail) {
|
if (thumbnail) {
|
||||||
thumbnail.scrollIntoViewIfNeeded()
|
thumbnail.scrollIntoViewIfNeeded();
|
||||||
thumbnail.style.viewTransitionName = 'person-photo'
|
thumbnail.style.viewTransitionName = 'person-photo';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
document.getElementById('container').scrollTop = 0
|
document.getElementById('container').scrollTop = 0;
|
||||||
|
|
||||||
if (movieThumbnail) {
|
if (movieThumbnail) {
|
||||||
movieThumbnail.style.viewTransitionName = ''
|
movieThumbnail.style.viewTransitionName = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
await transition.finished
|
await transition.finished;
|
||||||
|
|
||||||
if (thumbnail) {
|
if (thumbnail) {
|
||||||
thumbnail.style.viewTransitionName = ''
|
thumbnail.style.viewTransitionName = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moviePoster) {
|
if (moviePoster) {
|
||||||
moviePoster.classList.add('movie-poster')
|
moviePoster.classList.add('movie-poster');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,79 +1,76 @@
|
||||||
export function getNavigationType(fromPath, toPath) {
|
export function getNavigationType(fromPath, toPath) {
|
||||||
if (fromPath.startsWith('/movies') && toPath === '/') {
|
if (fromPath.startsWith('/movies') && toPath === '/') {
|
||||||
return 'movie-to-home'
|
return 'movie-to-home';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fromPath === '/tv' && toPath.startsWith('/tv/')) {
|
if (fromPath === '/tv' && toPath.startsWith('/tv/')) {
|
||||||
return 'tv-to-show'
|
return 'tv-to-show';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fromPath === '/' && toPath.startsWith('/movies')) {
|
if (fromPath === '/' && toPath.startsWith('/movies')) {
|
||||||
return 'home-to-movie'
|
return 'home-to-movie';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fromPath.startsWith('/tv/') && toPath === '/tv') {
|
if (fromPath.startsWith('/tv/') && toPath === '/tv') {
|
||||||
return 'show-to-tv'
|
return 'show-to-tv';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(fromPath.startsWith('/movies') || fromPath.startsWith('/tv')) &&
|
(fromPath.startsWith('/movies') || fromPath.startsWith('/tv')) &&
|
||||||
toPath.startsWith('/people')
|
toPath.startsWith('/people')
|
||||||
) {
|
) {
|
||||||
return 'movie-to-person'
|
return 'movie-to-person';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
fromPath.startsWith('/people') &&
|
fromPath.startsWith('/people') &&
|
||||||
(toPath.startsWith('/movies') || toPath.startsWith('/tv/'))
|
(toPath.startsWith('/movies') || toPath.startsWith('/tv/'))
|
||||||
) {
|
) {
|
||||||
return 'person-to-movie'
|
return 'person-to-movie';
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'other'
|
return 'other';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isBackNavigation(navigateEvent) {
|
export function isBackNavigation(navigateEvent) {
|
||||||
if (
|
if (navigateEvent.navigationType === 'push' || navigateEvent.navigationType === 'replace') {
|
||||||
navigateEvent.navigationType === 'push' ||
|
return false;
|
||||||
navigateEvent.navigationType === 'replace'
|
}
|
||||||
) {
|
if (
|
||||||
return false
|
navigateEvent.destination.index !== -1 &&
|
||||||
}
|
navigateEvent.destination.index < navigation.currentEntry.index
|
||||||
if (
|
) {
|
||||||
navigateEvent.destination.index !== -1 &&
|
return true;
|
||||||
navigateEvent.destination.index < navigation.currentEntry.index
|
}
|
||||||
) {
|
return false;
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function shouldNotIntercept(navigationEvent) {
|
export function shouldNotIntercept(navigationEvent) {
|
||||||
return (
|
return (
|
||||||
navigationEvent.canIntercept === false ||
|
navigationEvent.canIntercept === false ||
|
||||||
// If this is just a hashChange,
|
// If this is just a hashChange,
|
||||||
// just let the browser handle scrolling to the content.
|
// just let the browser handle scrolling to the content.
|
||||||
navigationEvent.hashChange ||
|
navigationEvent.hashChange ||
|
||||||
// If this is a download,
|
// If this is a download,
|
||||||
// let the browser perform the download.
|
// let the browser perform the download.
|
||||||
navigationEvent.downloadRequest ||
|
navigationEvent.downloadRequest ||
|
||||||
// If this is a form submission,
|
// If this is a form submission,
|
||||||
// let that go to the server.
|
// let that go to the server.
|
||||||
navigationEvent.formData
|
navigationEvent.formData
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useTvFragment(navigateEvent) {
|
export function useTvFragment(navigateEvent) {
|
||||||
const toUrl = new URL(navigateEvent.destination.url)
|
const toUrl = new URL(navigateEvent.destination.url);
|
||||||
const toPath = toUrl.pathname
|
const toPath = toUrl.pathname;
|
||||||
|
|
||||||
return toPath.startsWith('/tv')
|
return toPath.startsWith('/tv');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPathId(path) {
|
export function getPathId(path) {
|
||||||
return path.split('/')[2]
|
return path.split('/')[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateTheDOMSomehow(data) {
|
export function updateTheDOMSomehow(data) {
|
||||||
document.getElementById('content').innerHTML = data
|
document.getElementById('content').innerHTML = data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,61 +1,63 @@
|
||||||
@keyframes fade-in {
|
@keyframes fade-in {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fade-out {
|
@keyframes fade-out {
|
||||||
to {
|
to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes slide-from-right {
|
@keyframes slide-from-right {
|
||||||
from {
|
from {
|
||||||
transform: translateX(30px);
|
transform: translateX(30px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes slide-to-left {
|
@keyframes slide-to-left {
|
||||||
to {
|
to {
|
||||||
transform: translateX(-30px);
|
transform: translateX(-30px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::view-transition-old(root) {
|
::view-transition-old(root) {
|
||||||
animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
|
animation:
|
||||||
300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
|
90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
|
||||||
|
300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
|
||||||
}
|
}
|
||||||
|
|
||||||
::view-transition-new(root) {
|
::view-transition-new(root) {
|
||||||
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
|
animation:
|
||||||
300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
|
210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
|
||||||
|
300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
|
||||||
}
|
}
|
||||||
|
|
||||||
::view-transition-old(movie-poster),
|
::view-transition-old(movie-poster),
|
||||||
::view-transition-new(movie-poster) {
|
::view-transition-new(movie-poster) {
|
||||||
animation: none;
|
animation: none;
|
||||||
mix-blend-mode: normal;
|
mix-blend-mode: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
::view-transition-image-pair(movie-poster) {
|
::view-transition-image-pair(movie-poster) {
|
||||||
isolation: none;
|
isolation: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav {
|
.nav {
|
||||||
view-transition-name: main-header;
|
view-transition-name: main-header;
|
||||||
contain: paint;
|
contain: paint;
|
||||||
}
|
}
|
||||||
|
|
||||||
.movie-poster {
|
.movie-poster {
|
||||||
contain: paint;
|
contain: paint;
|
||||||
}
|
}
|
||||||
|
|
||||||
.person-photo {
|
.person-photo {
|
||||||
view-transition-name: person-photo;
|
view-transition-name: person-photo;
|
||||||
contain: paint;
|
contain: paint;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumbnail {
|
.thumbnail {
|
||||||
contain: paint;
|
contain: paint;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
width: {
|
width: {
|
||||||
96: '24rem',
|
96: '24rem',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
}
|
};
|
||||||
|
|
|
@ -24,16 +24,21 @@ const announce = () => {
|
||||||
let div = document.createElement('div');
|
let div = document.createElement('div');
|
||||||
div.setAttribute('aria-live', 'assertive');
|
div.setAttribute('aria-live', 'assertive');
|
||||||
div.setAttribute('aria-atomic', 'true');
|
div.setAttribute('aria-atomic', 'true');
|
||||||
div.setAttribute('style', 'position:absolute;left:0;top:0;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden;white-space:nowrap;width:1px;height:1px');
|
div.setAttribute(
|
||||||
|
'style',
|
||||||
|
'position:absolute;left:0;top:0;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden;white-space:nowrap;width:1px;height:1px'
|
||||||
|
);
|
||||||
document.body.append(div);
|
document.body.append(div);
|
||||||
setTimeout(() => {
|
setTimeout(
|
||||||
let title = document.title || document.querySelector('h1')?.textContent || location.pathname;
|
() => {
|
||||||
div.textContent = title;
|
let title = document.title || document.querySelector('h1')?.textContent || location.pathname;
|
||||||
},
|
div.textContent = title;
|
||||||
// Much thought went into this magic number; the gist is that screen readers
|
},
|
||||||
// need to see that the element changed and might not do so if it happens
|
// Much thought went into this magic number; the gist is that screen readers
|
||||||
// too quickly.
|
// need to see that the element changed and might not do so if it happens
|
||||||
60);
|
// too quickly.
|
||||||
|
60
|
||||||
|
);
|
||||||
};
|
};
|
||||||
const PERSIST_ATTR = 'data-astro-transition-persist';
|
const PERSIST_ATTR = 'data-astro-transition-persist';
|
||||||
const parser = new DOMParser();
|
const parser = new DOMParser();
|
||||||
|
|
Loading…
Add table
Reference in a new issue