responsive mobile layout

This commit is contained in:
2025-10-13 20:46:09 +02:00
parent f641272c22
commit c292da4d60
12 changed files with 31 additions and 28 deletions

View File

@@ -1,7 +1,7 @@
<template> <template>
<UApp> <UApp>
<UHeader> <UHeader>
<template #left> <template #content>
<NuxtLink to="https://github.com/C9Glax/tranga" external no-prefetch><Icon name="i-lucide-github" />API</NuxtLink> <NuxtLink to="https://github.com/C9Glax/tranga" external no-prefetch><Icon name="i-lucide-github" />API</NuxtLink>
<NuxtLink to="https://github.com/C9Glax/tranga-website" external no-prefetch <NuxtLink to="https://github.com/C9Glax/tranga-website" external no-prefetch
><Icon name="i-lucide-github" />Website</NuxtLink ><Icon name="i-lucide-github" />Website</NuxtLink
@@ -10,7 +10,7 @@
><Icon name="i-lucide-book-open" />Swagger</NuxtLink ><Icon name="i-lucide-book-open" />Swagger</NuxtLink
> >
</template> </template>
<template #default> <template #title>
<NuxtLink to="/"> <NuxtLink to="/">
<div class="h-full flex gap-2 items-center"> <div class="h-full flex gap-2 items-center">
<img src="/blahaj.png" class="h-lh cursor-grab" alt="Blahaj" /> <img src="/blahaj.png" class="h-lh cursor-grab" alt="Blahaj" />
@@ -27,7 +27,7 @@
</NuxtLink> </NuxtLink>
</template> </template>
<template #right> <template #right>
<UButton icon="i-lucide-plus" to="/search" color="primary">Add</UButton> <UButton icon="i-lucide-plus" to="/search" color="primary">Manga</UButton>
<UColorModeButton color="secondary" /> <UColorModeButton color="secondary" />
<UButton icon="i-lucide-settings" variant="ghost" to="/settings" color="secondary" /> <UButton icon="i-lucide-settings" variant="ghost" to="/settings" color="secondary" />
</template> </template>

View File

@@ -5,3 +5,8 @@
--color-pink: #f5a9b8; --color-pink: #f5a9b8;
--color-blue: #5bcefa; --color-blue: #5bcefa;
} }
:root {
--mangacover-width: 240px;
--mangacover-height: 350px;
}

View File

@@ -2,7 +2,7 @@
<UCard <UCard
v-if="!expanded" v-if="!expanded"
:ui="{ body: 'p-0 sm:p-0', root: 'overflow-visible' }" :ui="{ body: 'p-0 sm:p-0', root: 'overflow-visible' }"
class="relative h-[350px] mt-2 mb-2" class="relative max-sm:w-[calc(var(--mangacover-width)/2)] max-sm:h-[calc(var(--mangacover-height)/2)] w-(--mangacover-width) h-(--mangacover-height) mt-2 mb-2"
@click="$emit('click')"> @click="$emit('click')">
<MangaCover :manga="manga" blur /> <MangaCover :manga="manga" blur />
<div class="absolute -top-4 -right-4 flex flex-col bg-pink rounded-full"> <div class="absolute -top-4 -right-4 flex flex-col bg-pink rounded-full">
@@ -13,7 +13,7 @@
v-else v-else
orientation="horizontal" orientation="horizontal"
reverse reverse
class="relative max-w-[600px] w-full h-[350px] mt-2 mb-2" class="relative max-sm:w-full max-sm:h-full w-[calc(var(--mangacover-width)*2+1.5rem)] h-(--mangacover-height) mt-2 mb-2"
:ui="{ body: 'p-0 sm:p-0', root: 'overflow-visible' }" :ui="{ body: 'p-0 sm:p-0', root: 'overflow-visible' }"
@click="$emit('click')"> @click="$emit('click')">
<div class="flex flex-row w-full h-full basis-auto"> <div class="flex flex-row w-full h-full basis-auto">
@@ -21,7 +21,7 @@
<div class="absolute -top-4 -right-4 flex flex-col bg-pink rounded-full"> <div class="absolute -top-4 -right-4 flex flex-col bg-pink rounded-full">
<MangaconnectorIcon v-for="m in manga.mangaConnectorIds" v-bind="m" :key="m.key" /> <MangaconnectorIcon v-for="m in manga.mangaConnectorIds" v-bind="m" :key="m.key" />
</div> </div>
<div class="flex flex-col h-[350px] shrink mx-2 mt-4"> <div class="flex flex-col h-(--mangacover-height) shrink mx-2 mt-4">
<p class="font-semibold text-xl">{{ manga.name }}</p> <p class="font-semibold text-xl">{{ manga.name }}</p>
<p class="max-h-30 overflow-y-hidden grow">{{ manga.description }}</p> <p class="max-h-30 overflow-y-hidden grow">{{ manga.description }}</p>
</div> </div>

View File

@@ -1,5 +1,5 @@
<template> <template>
<div class="relative w-[240px] h-[350px] rounded-lg overflow-clip"> <div class="relative max-sm:w-[calc(var(--mangacover-width)/2)] max-sm:h-[calc(var(--mangacover-height)/2)] w-(--mangacover-width) h-(--mangacover-height) rounded-lg overflow-clip">
<div <div
v-if="blur" v-if="blur"
class="absolute l-0 t-0 w-full h-full rounded-lg overflow-clip" class="absolute l-0 t-0 w-full h-full rounded-lg overflow-clip"
@@ -9,7 +9,7 @@
backdrop-filter: blur(2px) brightness(70%); backdrop-filter: blur(2px) brightness(70%);
-webkit-backdrop-filter: blur(2px) brightness(70%); -webkit-backdrop-filter: blur(2px) brightness(70%);
"> ">
<p class="p-3 text-xl font-semibold max-h-full overflow-clip text-shadow-lg text-white"> <p class="p-3 max-sm:text-sm text-xl font-semibold max-h-full overflow-clip text-shadow-lg text-white">
{{ manga?.name }} {{ manga?.name }}
</p> </p>
</div> </div>

View File

@@ -23,7 +23,7 @@
<USkeleton v-else class="w-full h-30" /> <USkeleton v-else class="w-full h-30" />
</div> </div>
</template> </template>
<UPageBody class="relative mr-12"> <UPageBody class="relative min-sm:mr-12 max-sm:mx-4">
<div class="w-full flex flex-row justify-between"> <div class="w-full flex flex-row justify-between">
<div> <div>
<UButton variant="soft" :to="backPath ?? '/'" icon="i-lucide-arrow-left">Back</UButton> <UButton variant="soft" :to="backPath ?? '/'" icon="i-lucide-arrow-left">Back</UButton>

View File

@@ -38,5 +38,5 @@ const onDownloadClick = async () => {
loading.value = false; loading.value = false;
}; };
useHead({title: `Download ${manga.value?.name} from ${mangaConnector.value?.name}`}); useHead({ title: `Download ${manga.value?.name} from ${mangaConnector.value?.name}` });
</script> </script>

View File

@@ -13,5 +13,5 @@ const { data: manga, refresh } = await useApi('/v2/Manga', { key: FetchKeys.Mang
onMounted(() => refresh()); onMounted(() => refresh());
const expanded = ref(-1); const expanded = ref(-1);
useHead({title: 'Tranga'}); useHead({ title: 'Tranga' });
</script> </script>

View File

@@ -1,6 +1,6 @@
<template> <template>
<MangaDetailPage :manga="manga"> <MangaDetailPage :manga="manga">
<div class="grid gap-3 grid-cols-[70%_30%]"> <div class="grid gap-3 max-sm:grid-flow-row-dense min-sm:grid-cols-[70%_30%]">
<ChaptersList v-if="manga" :manga-id="manga.key" /> <ChaptersList v-if="manga" :manga-id="manga.key" />
<UCard> <UCard>
<template #header> <template #header>
@@ -57,5 +57,5 @@ const setRequestedFrom = async (MangaConnectorName: string, IsRequested: boolean
await refreshNuxtData(FetchKeys.Manga.Id(mangaId)); await refreshNuxtData(FetchKeys.Manga.Id(mangaId));
}; };
useHead({title: `Manga ${manga.value?.name}`}); useHead({ title: `Manga ${manga.value?.name}` });
</script> </script>

View File

@@ -21,5 +21,5 @@ const mangaId = route.params.mangaId as string;
const { data: target } = await useApi('/v2/Manga/{MangaId}', { path: { MangaId: targetId }, key: FetchKeys.Manga.Id(targetId) }); const { data: target } = await useApi('/v2/Manga/{MangaId}', { path: { MangaId: targetId }, key: FetchKeys.Manga.Id(targetId) });
const { data: manga } = await useApi('/v2/Manga/{MangaId}', { path: { MangaId: mangaId }, key: FetchKeys.Manga.Id(mangaId) }); const { data: manga } = await useApi('/v2/Manga/{MangaId}', { path: { MangaId: mangaId }, key: FetchKeys.Manga.Id(mangaId) });
useHead({title: `Merge ${manga.value?.name} with ${target.value?.name}`}); useHead({ title: `Merge ${manga.value?.name} with ${target.value?.name}` });
</script> </script>

View File

@@ -19,5 +19,5 @@ const mangaId = route.params.mangaId as string;
const { data: manga } = await useApi('/v2/Manga/{MangaId}', { path: { MangaId: mangaId }, key: FetchKeys.Manga.Id(mangaId) }); const { data: manga } = await useApi('/v2/Manga/{MangaId}', { path: { MangaId: mangaId }, key: FetchKeys.Manga.Id(mangaId) });
const { data: mangas } = await useApi('/v2/Manga', { key: FetchKeys.Manga.All }); const { data: mangas } = await useApi('/v2/Manga', { key: FetchKeys.Manga.All });
useHead({title: `Merge Manga ${manga.value?.name}`}); useHead({ title: `Merge Manga ${manga.value?.name}` });
</script> </script>

View File

@@ -1,13 +1,13 @@
<template> <template>
<UPageBody> <UPageBody>
<UPageSection :ui="{ container: 'gap-4 sm:gap-4 lg:gap-4 py-4 sm:py-4 lg:py-4 gap-4 sm:gap-4 lg:gap-4' }" class="h-fit"> <UPageSection :ui="{ container: 'gap-1 sm:gap-1 lg:gap-1 py-4 sm:py-1 lg:py-1 gap-1 sm:gap-1 lg:gap-1' }" class="h-fit">
<UButton variant="soft" to="/" icon="i-lucide-arrow-left" class="w-min">Back</UButton> <UButton variant="soft" to="/" icon="i-lucide-arrow-left" class="w-min">Back</UButton>
<div class="flex flex-row w-full h-full justify-between gap-4"> <div class="flex max-sm:flex-col flex-row w-full h-full justify-between gap-4">
<UStepper v-model="activeStep" orientation="vertical" :items="items" class="h-full" disabled color="secondary" /> <UStepper v-model="activeStep" orientation="vertical" :items="items" class="h-full" disabled color="secondary" />
<UCard class="grow"> <UCard class="grow">
<div class="flex flex-col justify-between gap-2"> <div class="flex flex-col justify-between gap-2">
<UInput v-model="query" class="w-full" :disabled="busy" /> <UInput v-model="query" class="w-full" :disabled="busy" />
<div class="flex gap-1 w-full justify-center"> <div class="flex flex-wrap gap-1 w-full justify-center">
<UButton <UButton
v-for="c in connectors" v-for="c in connectors"
:key="c.key" :key="c.key"
@@ -27,14 +27,14 @@
</UPageSection> </UPageSection>
<UPageSection <UPageSection
v-if="searchResult.length > 0" v-if="searchResult.length > 0"
:ui="{ container: 'gap-4 sm:gap-4 lg:gap-4 py-4 sm:py-4 lg:py-4 gap-4 sm:gap-4 lg:gap-4' }"> :ui="{ container: 'gap-1 sm:gap-1 lg:gap-1 py-1 sm:py-1 lg:py-1 gap-1 sm:gap-1 lg:gap-1' }">
<template #description> <template #description>
<p class="text-lg"> <p class="text-lg">
Result for <span class="text-secondary">'{{ searchQuery }}'</span> Result for <span class="text-secondary">'{{ searchQuery }}'</span>
</p> </p>
</template> </template>
<template #default> <template #default>
<div class="relative flex flex-row flex-wrap gap-6 mt-0"> <div class="relative flex flex-row flex-wrap gap-4 mt-0">
<MangaCard <MangaCard
v-for="(m, i) in searchResult" v-for="(m, i) in searchResult"
:key="m.key" :key="m.key"
@@ -120,5 +120,5 @@ const items = ref<StepperItem[]>([
{ title: 'Results', icon: 'i-lucide-logs' }, { title: 'Results', icon: 'i-lucide-logs' },
]); ]);
useHead({title: 'Search Manga'}); useHead({ title: 'Search Manga' });
</script> </script>

View File

@@ -14,13 +14,11 @@
<template #header> <template #header>
<h1>Maintenance</h1> <h1>Maintenance</h1>
</template> </template>
<div class="flex flex-col gap-1 items-end basis-1"> <UButton icon="i-lucide-database" :loading="cleanUpDatabaseBusy" class="w-fit mb-2" @click="cleanUpDatabase"
<UButton icon="i-lucide-database" :loading="cleanUpDatabaseBusy" class="w-fit" @click="cleanUpDatabase" >Clean database</UButton
>Clean database</UButton >
>
</div>
<UFormField label="API Url" name="apiUrl"> <UFormField label="API Url" name="apiUrl">
<UInput v-model="apiUrl" class="max-w-full w-lg" placeholder="http://<ip:port>/" /> <UInput v-model="apiUrl" class="max-w-full w-xs" placeholder="http://<ip:port>/" />
<UButton :loading="reloading" class="mx-1" @click="setUrl">Set</UButton> <UButton :loading="reloading" class="mx-1" @click="setUrl">Set</UButton>
</UFormField> </UFormField>
</UCard> </UCard>
@@ -54,5 +52,5 @@ const cleanUpDatabase = async () => {
cleanUpDatabaseBusy.value = false; cleanUpDatabaseBusy.value = false;
}; };
useHead({title: 'Settings'}); useHead({ title: 'Settings' });
</script> </script>