Limit attributes count on preview cards + fix media pages title

This commit is contained in:
DrMint 2024-06-02 09:59:03 +02:00
parent 2c2dde250e
commit 6cb971b5a5
14 changed files with 181 additions and 44 deletions

View File

@ -9,7 +9,6 @@
## Short term
- [Feat] 404, 500 pages
- [Bugs] [iOS] Video doesn't seem to start
- [Feat] Add languages to collectibles and pages previews
- [Feat] [RichTextContent] Handle relationship
- [Bugs] Vollkorn doesn't support many languages
@ -21,7 +20,6 @@
## Mid term
- [Feat] [Payload] Home as parent folders for home folders
- [Bugs] [Timeline] Error if collectible not published?
- [Feat] [Timeline] display source language
- [Feat] [Timeline] Add details button in footer with credits + last updated / created
@ -32,6 +30,8 @@
## Long term
- [Bugs] [iOS] Video doesn't seem to start
- [Feat] [Folders] Provide a list view, and a list/grid toggle
- [Feat] [Payload] Endpoints should provide a simple text-based version of the content (for OG purposes)
- [Feat] [WebManifest] Add shortcuts https://web.dev/patterns/web-apps/shortcuts
- [Feat] [PWA] Rich install UI https://web.dev/patterns/web-apps/richer-install-ui/

View File

@ -701,6 +701,31 @@ const { currentTheme } = Astro.locals;
> h5 + h6 {
margin-top: -0.75em;
}
h2 {
font-size: var(--font-size-4xl);
font-variation-settings: "wght" 800;
}
h3 {
font-size: var(--font-size-3xl);
font-variation-settings: "wght" 750;
}
h4 {
font-size: var(--font-size-2xl);
font-variation-settings: "wght" 700;
}
h5 {
font-size: var(--font-size-xl);
font-variation-settings: "wght" 600;
}
h6 {
font-size: var(--font-size-l);
font-variation-settings: "wght" 500;
}
}
@view-transition {

View File

@ -11,27 +11,27 @@ const { header, id } = Astro.props;
{
header === 1 ? (
<h1 id={id} class="font-5xl">
<h1 id={id}>
<slot />
</h1>
) : header === 2 ? (
<h2 id={id} class="font-4xl">
<h2 id={id}>
<slot />
</h2>
) : header === 3 ? (
<h3 id={id} class="font-3xl">
<h3 id={id}>
<slot />
</h3>
) : header === 4 ? (
<h4 id={id} class="font-2xl">
<h4 id={id}>
<slot />
</h4>
) : header === 5 ? (
<h5 id={id} class="font-xl">
<h5 id={id}>
<slot />
</h5>
) : (
<h6 id={id} class="font-l">
<h6 id={id}>
<slot />
</h6>
)

View File

@ -27,6 +27,7 @@ interface Props {
metaAttributes?: ComponentProps<typeof Attributes>["attributes"] | undefined;
credits?: EndpointCredit[] | undefined;
filename?: string | undefined;
smallTitle?: boolean | undefined;
}
const {
@ -41,10 +42,9 @@ const {
title,
subtitle,
filename,
smallTitle = false,
} = Astro.props;
const smallTitle = !subtitle && !pretitle;
const hasNavigation = previousImageHref || nextImageHref;
---
@ -96,7 +96,7 @@ const hasNavigation = previousImageHref || nextImageHref;
<div>
{
smallTitle ? (
<h1 class="font-3xl">{title}</h1>
<h1 class="font-4xl">{title}</h1>
) : (
<AppLayoutTitle pretitle={pretitle} title={title} subtitle={subtitle} />
)

View File

@ -2,18 +2,61 @@
import GenericPreview from "components/Previews/GenericPreview.astro";
import { getI18n } from "src/i18n/i18n";
import type { EndpointCollectible } from "src/shared/payload/payload-sdk";
import type { Attribute } from "src/utils/attributes";
import { convert } from "src/utils/currencies";
import { formatLocale } from "src/utils/format";
interface Props {
collectible: EndpointCollectible;
}
const { getLocalizedMatch, getLocalizedUrl, t } = await getI18n(Astro.locals.currentLocale);
const { getLocalizedMatch, getLocalizedUrl, t, formatPrice, formatDate } = await getI18n(
Astro.locals.currentLocale
);
const {
collectible: { slug, translations, thumbnail, attributes },
collectible: { slug, translations, thumbnail, attributes, languages, price, releaseDate },
} = Astro.props;
const { title, pretitle, subtitle } = getLocalizedMatch(translations);
const additionalAttributes: Attribute[] = [];
if (languages.length > 0) {
additionalAttributes.push({
title: t("collectibles.languages"),
icon: "material-symbols:translate",
values: languages.map((lang) => ({ name: formatLocale(lang) })),
withBorder: true,
});
}
if (releaseDate) {
additionalAttributes.push({
title: t("collectibles.releaseDate"),
icon: "material-symbols:calendar-month",
values: [{ name: formatDate(new Date(releaseDate)) }],
withBorder: false,
});
}
if (price) {
const preferredCurrency = Astro.locals.currentCurrency;
const convertedPrice = {
amount: convert(price.currency, preferredCurrency, price.amount),
currency: preferredCurrency,
};
additionalAttributes.push({
title: t("collectibles.price"),
icon: "material-symbols:sell",
values: [
{ name: price.amount === 0 ? t("collectibles.price.free") : formatPrice(convertedPrice) },
],
withBorder: false,
});
}
---
{/* ------------------------------------------- HTML ------------------------------------------- */}
@ -24,7 +67,7 @@ const { title, pretitle, subtitle } = getLocalizedMatch(translations);
subtitle={subtitle}
thumbnail={thumbnail}
href={getLocalizedUrl(`/collectibles/${slug}`)}
attributes={attributes}
attributes={[...attributes, ...additionalAttributes]}
icon="material-symbols:category"
iconHoverLabel={t("global.previewTypes.collectible")}
disableRoundedTop

View File

@ -1,8 +1,10 @@
---
import type {
EndpointImage,
EndpointMediaThumbnail,
EndpointScanImage,
import {
AttributeTypes,
type EndpointAttribute,
type EndpointImage,
type EndpointMediaThumbnail,
type EndpointScanImage,
} from "src/shared/payload/payload-sdk";
import Card from "components/Card.astro";
import { Icon } from "astro-icon/components";
@ -10,6 +12,7 @@ import type { ComponentProps } from "astro/types";
import { getI18n } from "src/i18n/i18n";
import InlineAttributes from "components/InlineAttributes.astro";
import { sizesToSrcset, sizesForGridLayout } from "src/utils/img";
import type { Attribute } from "src/utils/attributes";
interface Props {
thumbnail?: EndpointImage | EndpointMediaThumbnail | EndpointScanImage | undefined;
@ -24,7 +27,7 @@ interface Props {
iconHoverLabel?: string;
}
const { t } = await getI18n(Astro.locals.currentLocale);
const { t, getLocalizedMatch } = await getI18n(Astro.locals.currentLocale);
const {
thumbnail,
@ -38,6 +41,37 @@ const {
icon = "material-symbols:unknown-document",
iconHoverLabel = t("global.previewTypes.unknown"),
} = Astro.props;
/* Clip the number of attributes such that the card isn't ridiculously long */
let metaLength = 0;
const maxMetaLength = 230;
metaLength += (pretitle?.length ?? 0) * 1.5;
metaLength += (title?.length ?? 0) * 3;
metaLength += (subtitle?.length ?? 0) * 3;
const clippedAttributes: (Attribute | EndpointAttribute)[] = [];
for (const attribute of attributes) {
if (metaLength > maxMetaLength) {
clippedAttributes.pop();
break;
}
if ("title" in attribute) {
metaLength += attribute.title.length;
metaLength += attribute.values.join(", ").length;
clippedAttributes.push(attribute);
} else {
metaLength += getLocalizedMatch(attribute.translations).name.length;
if (attribute.type === AttributeTypes.Tags) {
metaLength += attribute.value
.map(({ translations }) => getLocalizedMatch(translations).name)
.join(", ").length;
metaLength += clippedAttributes.push(attribute);
}
// TODO: Handle other attribute types
}
metaLength += 8;
}
---
{/* ------------------------------------------- HTML ------------------------------------------- */}
@ -89,11 +123,11 @@ const {
}
{
attributes.length > 0 && (
clippedAttributes.length > 0 && (
<>
{subtitle && <hr />}
<div id="tags">
<InlineAttributes attributes={attributes} />
<InlineAttributes attributes={clippedAttributes} />
</div>
</>
)

View File

@ -2,18 +2,30 @@
import GenericPreview from "components/Previews/GenericPreview.astro";
import { getI18n } from "src/i18n/i18n";
import type { EndpointPage } from "src/shared/payload/payload-sdk";
import type { Attribute } from "src/utils/attributes";
interface Props {
page: EndpointPage;
}
const { getLocalizedMatch, getLocalizedUrl, t } = await getI18n(Astro.locals.currentLocale);
const { getLocalizedMatch, getLocalizedUrl, t, formatDate } = await getI18n(
Astro.locals.currentLocale
);
const {
page: { slug, translations, thumbnail, attributes },
page: { slug, translations, thumbnail, attributes, updatedAt },
} = Astro.props;
const { title, pretitle, subtitle } = getLocalizedMatch(translations);
const metaAttributes: Attribute[] = [
{
title: t("global.media.attributes.updatedAt"),
icon: "material-symbols:edit-calendar",
values: [{ name: formatDate(new Date(updatedAt)) }],
withBorder: false,
},
];
---
{/* ------------------------------------------- HTML ------------------------------------------- */}
@ -24,7 +36,7 @@ const { title, pretitle, subtitle } = getLocalizedMatch(translations);
subtitle={subtitle}
thumbnail={thumbnail}
href={getLocalizedUrl(`/pages/${slug}`)}
attributes={attributes}
attributes={[...attributes, ...metaAttributes]}
icon="material-symbols:docs"
iconHoverLabel={t("global.previewTypes.page")}
/>

View File

@ -34,8 +34,6 @@ const {
const { pretitle, title, subtitle, description } = getLocalizedMatch(translations);
const smallTitle = !subtitle && !pretitle;
const metaAttributes = [
...(filename && title !== filename
? [
@ -81,13 +79,7 @@ const metaAttributes = [
<AudioPlayer audio={audio} class="audio_id-audio-player" />
<div id="info">
{
smallTitle ? (
<h1>{title}</h1>
) : (
<AppLayoutTitle pretitle={pretitle} title={title} subtitle={subtitle} />
)
}
<AppLayoutTitle pretitle={pretitle} title={title} subtitle={subtitle} />
{description && <RichText content={description} />}
{attributes.length > 0 && <Attributes attributes={attributes} />}
{credits.length > 0 && <Credits credits={credits} />}

View File

@ -76,5 +76,6 @@ const metaAttributes = [
attributes={attributes}
metaAttributes={metaAttributes}
credits={credits}
smallTitle={title === filename}
/>
</AppLayout>

View File

@ -40,5 +40,6 @@ const translation = getLocalizedMatch(translations);
? getLocalizedUrl(`/collectibles/${slug}/scans/${nextIndex}`)
: undefined}
filename={image.filename}
smallTitle
/>
</AppLayout>

View File

@ -0,0 +1,35 @@
---
import AppLayout from "components/AppLayout/AppLayout.astro";
import AppLayoutTitle from "components/AppLayout/components/AppLayoutTitle.astro";
import { getI18n } from "src/i18n/i18n";
const { getLocalizedUrl } = await getI18n(Astro.locals.currentLocale);
---
{/* ------------------------------------------- HTML ------------------------------------------- */}
<AppLayout>
<AppLayoutTitle pretitle="Welcome to" title="The Dev Room" />
<ul>
<li>
<a href={getLocalizedUrl("/dev/design-system")} class="pressable-link">Design System</a>
</li>
<li>
<a href={getLocalizedUrl("/dev/rich-text")} class="pressable-link">
Guide to the Rich Text Editor
</a>
</li>
</ul>
</AppLayout>
{/* ------------------------------------------- CSS -------------------------------------------- */}
<style>
ul {
margin-block: 2em;
}
li {
margin-block: 0.5em;
}
</style>

View File

@ -64,5 +64,6 @@ const metaAttributes = [
attributes={attributes}
metaAttributes={metaAttributes}
credits={credits}
smallTitle={title === filename}
/>
</AppLayout>

View File

@ -24,7 +24,7 @@ const { getLocalizedUrl, t, formatTimelineDate } = await getI18n(Astro.locals.cu
<div class="card-container">
<Card>
<div class="card-content prose">
<h3 class="font-serif font-3xl">{t("timeline.notes.title")}</h3>
<h3>{t("timeline.notes.title")}</h3>
<p
set:html={t("timeline.notes.content", {
@ -38,7 +38,7 @@ const { getLocalizedUrl, t, formatTimelineDate } = await getI18n(Astro.locals.cu
<Card>
<div class="card-content prose">
<h3 class="font-serif font-3xl">{t("timeline.priorCataclysmNote.title")}</h3>
<h3>{t("timeline.priorCataclysmNote.title")}</h3>
<p
set:html={t("timeline.priorCataclysmNote.content", {
@ -52,7 +52,7 @@ const { getLocalizedUrl, t, formatTimelineDate } = await getI18n(Astro.locals.cu
<Card>
<div class="card-content prose jump-card">
<h3 class="font-serif font-3xl">{t("timeline.jumpTo")}</h3>
<h3>{t("timeline.jumpTo")}</h3>
{
cache.config.timeline.eras.map(({ name, startingYear, endingYear }) => (

View File

@ -33,7 +33,6 @@ const {
} = video;
const { pretitle, title, subtitle, description } = getLocalizedMatch(translations);
const smallTitle = !subtitle && !pretitle;
const metaAttributes = [
...(filename && title !== filename
@ -80,13 +79,7 @@ const metaAttributes = [
<VideoPlayer class="video_id-video-player" video={video} />
<div id="info">
{
smallTitle ? (
<h1>{title}</h1>
) : (
<AppLayoutTitle pretitle={pretitle} title={title} subtitle={subtitle} />
)
}
<AppLayoutTitle pretitle={pretitle} title={title} subtitle={subtitle} />
{description && <RichText content={description} />}
{attributes.length > 0 && <Attributes attributes={attributes} />}
{credits.length > 0 && <Credits credits={credits} />}