improved styles for manga page

This commit is contained in:
Daniel Bulant 2022-12-10 00:02:23 +01:00
parent 324133418f
commit d9bf3af9c0
6 changed files with 250 additions and 96 deletions

View file

@ -21,15 +21,21 @@
<style>
div {
display: flex;
display: grid;
flex-wrap: wrap;
gap: 0.5rem;
justify-content: start;
align-items: start;
grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr));
}
div img {
border-radius: 5px;
height: 10rem;
width: auto;
}
div img:first-child {
grid-column: 1 / span 2;
grid-row: 1 / span 2;
height: 20rem;
}
</style>

View file

@ -3,7 +3,7 @@
export var selected = list[0];
</script>
<div>
<div class="tabs">
{#each list as item}
<button on:click={() => selected = item} class:active={selected == item}>{item}</button>
{/each}
@ -16,16 +16,24 @@
button {
border-radius: 0;
flex-grow: 1;
padding: 0.5rem;
border: none;
background: none;
color: white;
font-size: 1.2rem;
cursor: pointer;
transition: background-color 0.2s, text-shadow 0.2s;
}
button:first-child {
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
border-radius: 0.5rem 0 0 0.5rem;
}
button:last-child {
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
border-radius: 0 0.5rem 0.5rem 0;
}
button.active {
background: rgb(202, 202, 202);
button:hover, button:active, button:focus, button.active {
background: rgba(255,255,255,0.1);
outline: none;
text-shadow: 0 0 0.1rem white;
}
</style>

View file

@ -13,6 +13,8 @@
import SvelteMarkdown from 'svelte-markdown';
import ArtDialog from "$lib/components/artDialog.svelte";
import streamSaver from "streamsaver";
import Navbar from "./navbar.svelte";
import ExpandableDescription from "./expandableDescription.svelte";
export var data;
@ -287,73 +289,81 @@
var width;
var smallScreenMode = width < 660;
$: smallScreenMode = width < 660;
var smallScreenMode = width < 700;
$: smallScreenMode = width < 700;
var scrollY, innerHeight;
</script>
<svelte:window on:beforeUnload={beforeUnload} bind:innerWidth={width} />
<svelte:window on:beforeUnload={beforeUnload} bind:innerWidth={width} bind:scrollY bind:innerHeight />
<svelte:head>
<title>Chapters of {title}</title>
<meta name="description" value="Read {title} online, or download it as EPUB or CBZ file. Free of charge and ads." />
<title>{title} - Chapter list</title>
<meta name="description" value="Read {title} online, or download it as EPUB or CBZ file. Free of charge as well as free of ads." />
</svelte:head>
{#if anilistData} {#await anilistData then data}
{#if data.bannerImage}
<img class="banner" src={data.bannerImage} on:click={() => selectedImage = data.bannerImage} alt="">
{/if}
{/await} {/if}
<Navbar transparent={scrollY < 0.2*innerHeight} {title} />
<ArtDialog bind:selectedImage />
{#if anilistData} {#await anilistData then data}
{#if data.bannerImage}
<div class="banner-container">
<img class="banner" src={data.bannerImage} on:click={() => selectedImage = data.bannerImage} alt="">
<div class="fader"></div>
</div>
{/if}
{/await} {/if}
<main class:smallScreenMode>
<h1>{title}</h1>
<h3>
{#if manga.altTitles.find(t => t.en)}
{manga.altTitles.find(t => t.en)?.en} &middot;
{/if}
{#if manga.year}
{manga.year} &middot;
{/if}
{#if anilistData} {#await anilistData then data} {data.status} &middot; {/await} {/if}
{manga.contentRating}
{#if smallScreenMode}
<br>
{#if relationships.find(t => t.type === "author")}
Author: {relationships.find(t => t.type === "author").attributes.name}
{#if relationships.find(t => t.type === "artist")} &middot; {/if}
{/if}
{#if relationships.find(t => t.type === "artist")}
Artist: {relationships.find(t => t.type === "artist").attributes.name}
{/if}
{/if}
</h3>
<div class="flex infoflex">
{#if relationships.find(t => t.type === "cover_art")}
<img class="cover" class:r18={!["safe", "suggestive"].includes(manga.contentRating)} draggable="false" src="{imageproxy}https://uploads.mangadex.org/covers/{mangaId}/{relationships.find(t => t.type === "cover_art").attributes.fileName}.512.jpg" alt="" on:click={() => selectedImage = `https://uploads.mangadex.org/covers/${mangaId}/${relationships.find(t => t.type === "cover_art").attributes.fileName}.512.jpg`}>
{/if}
<div class="info" class:hidden={smallScreenMode}>
<div class="info">
<h1>{title}</h1>
<h3>
{#if manga.altTitles.find(t => t.en)}
{manga.altTitles.find(t => t.en)?.en} &middot;
{/if}
{#if manga.year}
{manga.year} &middot;
{/if}
{#if anilistData} {#await anilistData then data} {data.status} &middot; {/await} {/if}
{manga.contentRating}
</h3>
{#if relationships.find(t => t.type === "author")}
<span class="block">Author: {relationships.find(t => t.type === "author").attributes.name}</span>
<span class="block author">Author: {relationships.find(t => t.type === "author").attributes.name}</span>
{/if}
{#if relationships.find(t => t.type === "artist")}
<span class="block">Artist: {relationships.find(t => t.type === "artist").attributes.name}</span>
<span class="block author">Artist: {relationships.find(t => t.type === "artist").attributes.name}</span>
{/if}
{#if relationships.find(t => t.related === "colored" && t.type === "manga")}
<a href="/{relationships.find(t => t.related === "colored" && t.type === "manga").id}" class="block">Colored version</a>
{/if}
{#if manga.description.en}
<p><SvelteMarkdown source={manga.description.en} isInline /></p>
{#if !smallScreenMode && manga.description.en}
<p class="description"><SvelteMarkdown source={manga.description.en} isInline /></p>
{/if}
</div>
</div>
{#if smallScreenMode && manga.description.en}
<div class="fulldescription">
<ExpandableDescription source={manga.description.en} />
</div>
{/if}
{#if manga.tags}
<div class="tags">
{#each manga.tags as tag}
<span class="tag">{tag.attributes.name.en || tag.attributes.name.jp || Object.values(tag.attributes.name)[0]}</span>
{/each}
</div>
{/if}
<div class="flex">
<div class="linklist">
<a href="..">Go back to search page</a> <br>
<a href="https://mangadex.org/title/{mangaId}">Mangadex.org</a>
</div>
<div class="copyright-header" class:copyright-header-active={copyrightOpen} on:click={() => copyrightOpen = !copyrightOpen}>Copyright infringement? (click)</div>
@ -446,19 +456,6 @@
AL score: {data.averageScore} <br>
Also known as: {data.synonyms.join(", ")} {Object.values(manga.title).filter(t => t !== title).join(", ")}
{#if smallScreenMode}
{#if relationships.find(t => t.type === "author")}
<span class="block">Author: {relationships.find(t => t.type === "author").attributes.name}</span>
{/if}
{#if relationships.find(t => t.type === "artist")}
<span class="block">Artist: {relationships.find(t => t.type === "artist").attributes.name}</span>
{/if}
{#if manga.description.en}
<p><SvelteMarkdown source={manga.description.en} isInline /></p>
{/if}
{/if}
<br><br>
{/await} {/if}
@ -510,28 +507,30 @@
{/if}
</div>
{/if}
{#if manga.tags}
<div>
<h4>Tags</h4>
{#each manga.tags as tag}
<span class="block">{tag.attributes.name.en || tag.attributes.name.jp || Object.values(tag.attributes.name)[0]}</span>
{/each}
</div>
{/if}
</div>
</div>
</SwiperSlide>
</Swiper>
</main>
<style lang="postcss">
<style>
.tags {
display: flex;
overflow: auto;
}
.tag {
margin: 5px;
padding: 5px;
border-radius: 5px;
background-color: rgb(64,64,64);
user-select: all;
}
.hidden {
display: none;
}
.infoflex {
margin: 15px;
}
h4 { margin: 0; }
.flex-wrapped {
display: flex;
justify-content: space-between;
@ -547,11 +546,26 @@
.cover.r18:hover {
filter: blur(0);
}
.banner-container {
width: 100%;
max-height: 40vh;
position: absolute;
z-index: 0;
user-select: none;
}
.banner {
width: 100%;
max-height: 30vh;
max-height: 100%;
object-fit: cover;
animation: reveal 2s cubic-bezier(0, 0, 0.08, 0.99);
}
.banner-container .fader {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
background: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 100%);
}
.genre {
border-radius: 5px;
@ -562,29 +576,14 @@
.tabbed {
min-height: 20rem;
}
@media (prefers-reduced-motion) {
.banner {
animation: none;
}
}
@keyframes reveal {
from {
max-height: 0;
}
to {
max-height: 30vh;
}
}
.cover {
border-radius: 10px;
height: 350px;
height: 20rem;
margin-right: 15px;
transition: height .3s;
}
.smallScreenMode .cover {
margin: 0;
}
.smallScreenMode .infoflex {
justify-content: center;
height: 12rem;
}
.block {
display: block;
@ -592,12 +591,23 @@
.flex {
display: flex;
}
h3 {
text-align: center;
margin-top: 0;
}
h1 {
margin-bottom: 0;
margin: 0;
padding-top: 0.5rem;
text-align: left;
}
.smallScreenMode h1 {
font-size: 1.5rem;
}
h3 {
margin: 0;
}
.smallScreenMode h3 {
font-size: 1.2rem;
font-weight: normal;
}
.author {
font-weight: bold;
}
.flex {
display: flex;
@ -642,6 +652,10 @@
main {
font-size: 1.1rem;
padding-bottom: 1rem;
position: relative;
z-index: 1;
/* background: linear-gradient(to bottom, rgba(0,0,0,0.3) 0vh, rgba(0,0,0,1) 30vh); */
padding-top: 5rem;
}
.no-wrap {
white-space: nowrap;

View file

@ -0,0 +1,66 @@
<script lang="ts">
import SvelteMarkdown from "svelte-markdown";
export var source: string;
export var expanded = false;
</script>
<div class="description" class:expanded>
<div class="content">
<SvelteMarkdown {source} />
</div>
<div class="expander">
<button on:click={() => expanded = !expanded}>
{expanded ? "^" : "v"}
</button>
</div>
</div>
<style>
.description {
padding: 0 1rem 1rem 1rem;
font-size: 1.2rem;
line-height: 1.5rem;
/* limit to 5 rows when not expanded */
max-height: calc(2*1rem + 1.5rem * 5);
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 5;
-webkit-box-orient: vertical;
position: relative;
}
.expanded.description {
max-height: none;
-webkit-line-clamp: initial;
}
.expander {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 4rem;
background: linear-gradient(rgba(0,0,0,0), rgba(0,0,0,1));
text-align: center;
}
.expander button {
background: none;
border: none;
color: white;
font-size: 2rem;
cursor: pointer;
}
.expanded .expander {
background: none;
bottom: -1rem;
}
</style>

View file

@ -0,0 +1,4 @@
<script lang="ts">
</script>

View file

@ -0,0 +1,56 @@
<script lang="ts">
export var transparent: boolean = false;
export var title: string;
</script>
<div class="navbar" class:transparent>
<a href="/"></a>
<span class="title">{title}</span>
</div>
<style>
.navbar {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 5rem;
background: rgb(0,0,0,0.9);
backdrop-filter: blur(25px);
z-index: 100;
display: flex;
align-items: center;
gap: 1rem;
padding: 0 1rem;
transition: background 0.3s ease;
user-select: none;
}
.transparent.navbar {
background: none;
backdrop-filter: none;
}
.navbar a {
color: white;
font-size: 2rem;
transform: translateX(0);
transition: transform 0.2s ease;
}
.navbar a:hover, .navbar a:active, .navbar a:focus {
text-decoration: none;
transform: translateX(-0.5rem);
}
.transparent .title {
opacity: 0;
user-select: none;
}
.title {
user-select: inherit;
opacity: 1;
transition: opacity 0.3s ease;
font-size: 1.5rem;
color: white;
font-weight: bold;
flex-grow: 1;
text-align: center;
}
</style>