Stop reading clutter
This commit is contained in:
parent
82c723c192
commit
1cdc202731
8 changed files with 11 additions and 67 deletions
|
|
@ -1,13 +0,0 @@
|
|||
WEBVTT
|
||||
|
||||
00:00.000 --> 00:04.000
|
||||
No spoken dialogue. Game audio only.
|
||||
|
||||
00:04.000 --> 00:35.000
|
||||
The Ad Astra handheld board runs the game on a small OLED display.
|
||||
|
||||
00:35.000 --> 01:05.000
|
||||
The player controls the game through the IR input while the engine updates the display in real time.
|
||||
|
||||
01:05.000 --> 01:34.600
|
||||
The clip continues showing gameplay on the custom ATtiny85-based board.
|
||||
|
|
@ -5,7 +5,6 @@ import ProjectLinks from './ProjectLinks.astro';
|
|||
type Link = CollectionEntry<'work'>['data']['links'][number];
|
||||
|
||||
interface Props {
|
||||
role?: string;
|
||||
projectPeriod?: string;
|
||||
stack?: string[];
|
||||
scale?: string;
|
||||
|
|
@ -14,18 +13,9 @@ interface Props {
|
|||
headingId: string;
|
||||
}
|
||||
|
||||
const {
|
||||
role,
|
||||
projectPeriod,
|
||||
stack = [],
|
||||
scale,
|
||||
outcome,
|
||||
links = [],
|
||||
headingId,
|
||||
} = Astro.props;
|
||||
const { projectPeriod, stack = [], scale, outcome, links = [], headingId } = Astro.props;
|
||||
|
||||
const rows: Array<[string, string]> = [];
|
||||
if (role) rows.push(['Role', role]);
|
||||
if (projectPeriod) rows.push(['Period', projectPeriod]);
|
||||
if (stack.length > 0) rows.push(['Stack', stack.join(', ')]);
|
||||
if (scale) rows.push(['Scale', scale]);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ const videoHeight = item.type === 'video' ? (item.poster?.height ?? 720) : undef
|
|||
{
|
||||
item.type === 'video' ? (
|
||||
// Decorative videos stay inert and hidden from assistive tech. Meaningful
|
||||
// videos expose controls, captions, and an accessible name.
|
||||
// videos expose controls and an accessible name.
|
||||
item.decorative ? (
|
||||
<video
|
||||
muted
|
||||
|
|
@ -44,15 +44,6 @@ const videoHeight = item.type === 'video' ? (item.poster?.height ?? 720) : undef
|
|||
>
|
||||
{item.webm && <source src={item.webm} type="video/webm" />}
|
||||
{item.mp4 && <source src={item.mp4} type="video/mp4" />}
|
||||
{item.captions && (
|
||||
<track
|
||||
kind="captions"
|
||||
src={item.captions}
|
||||
srclang="en"
|
||||
label={item.captionsLabel}
|
||||
default
|
||||
/>
|
||||
)}
|
||||
</video>
|
||||
)
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -111,17 +111,6 @@ const playScript = `
|
|||
>
|
||||
{video.webm && <source src={video.webm} type="video/webm" />}
|
||||
{video.mp4 && <source src={video.mp4} type="video/mp4" />}
|
||||
{
|
||||
video.captions && (
|
||||
<track
|
||||
kind="captions"
|
||||
src={video.captions}
|
||||
srclang="en"
|
||||
label={video.captionsLabel}
|
||||
default
|
||||
/>
|
||||
)
|
||||
}
|
||||
</video>
|
||||
|
||||
<noscript>
|
||||
|
|
|
|||
|
|
@ -64,13 +64,12 @@ const thumbnailSchema = ({ image }: SchemaContext) =>
|
|||
alt: z.string().min(1, 'Thumbnail alt text must not be empty.'),
|
||||
});
|
||||
|
||||
// Partial thumbnail used by the project card to override just the image, just
|
||||
// the alt text, or both. Anything omitted falls back to the entry's top-level
|
||||
// thumbnail, so a card that only rewords its alt doesn't repeat the `src`.
|
||||
// Thumbnail override used by the project card to swap just the image when the
|
||||
// card wants a different crop from the article. The alt text is never
|
||||
// overridden, so it stays a single source of truth on the top-level thumbnail.
|
||||
const thumbnailOverrideSchema = ({ image }: SchemaContext) =>
|
||||
z.object({
|
||||
src: image().optional(),
|
||||
alt: z.string().min(1, 'Thumbnail alt text must not be empty.').optional(),
|
||||
src: image(),
|
||||
});
|
||||
|
||||
const mediaSchema = ({ image }: SchemaContext) =>
|
||||
|
|
@ -90,8 +89,6 @@ const mediaSchema = ({ image }: SchemaContext) =>
|
|||
poster: image().optional(),
|
||||
mp4: mediaUrl.optional(),
|
||||
webm: mediaUrl.optional(),
|
||||
captions: mediaUrl.optional(),
|
||||
captionsLabel: z.string().default('English captions'),
|
||||
alt: z.string().optional(),
|
||||
decorative: z.boolean().optional(),
|
||||
caption: z.string().optional(),
|
||||
|
|
@ -104,12 +101,6 @@ const mediaSchema = ({ image }: SchemaContext) =>
|
|||
.refine((item) => item.decorative || (Boolean(item.alt) && Boolean(item.caption)), {
|
||||
message: 'Meaningful media needs both alt text and a caption.',
|
||||
})
|
||||
.refine(
|
||||
(item) => item.type !== 'video' || item.decorative || Boolean(item.captions),
|
||||
{
|
||||
message: 'Meaningful video needs captions.',
|
||||
}
|
||||
)
|
||||
.refine(
|
||||
(item) => item.type !== 'video' || item.decorative || Boolean(item.transcript),
|
||||
{
|
||||
|
|
@ -130,11 +121,9 @@ const articleFacet = ({ image }: SchemaContext) =>
|
|||
iframeThumbnail: z.boolean().default(false),
|
||||
featuredOrder: z.number().optional(),
|
||||
tags: z.array(z.enum(TAGS)).default([]),
|
||||
role: z.string().min(1).optional(),
|
||||
stack: z.array(z.string()).optional(),
|
||||
scale: z.string().min(1).optional(),
|
||||
outcome: z.string().min(1).optional(),
|
||||
audience: z.enum(['general', 'technical', 'recruiter-relevant']).default('technical'),
|
||||
media: z.array(mediaSchema({ image })).default([]),
|
||||
});
|
||||
|
||||
|
|
@ -145,7 +134,6 @@ const projectFacet = ({ image }: SchemaContext) =>
|
|||
technologies: z.array(z.string()).optional(),
|
||||
// Card overrides. When omitted, the card uses the top-level value.
|
||||
title: z.string().optional(),
|
||||
description: z.string().max(160).optional(),
|
||||
thumbnail: thumbnailOverrideSchema({ image }).optional(),
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -137,7 +137,6 @@ const personJsonLd = buildPersonJsonLd();
|
|||
|
||||
<AtAGlance
|
||||
headingId={`at-a-glance-${post.id}`}
|
||||
role={post.data.article?.role}
|
||||
projectPeriod={post.data.period}
|
||||
stack={post.data.article?.stack}
|
||||
scale={post.data.article?.scale}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import type { ImageMetadata } from 'astro';
|
|||
|
||||
// Theme background colors, the single source of truth for the
|
||||
// <meta name="theme-color"> tags and the FOUC-prevention scripts (injected in
|
||||
// Base.astro and Header.astro). Keep --color-bg in global.css in sync; CSS
|
||||
// cannot import these values.
|
||||
// Base.astro and Header.astro). Keep --color-bg in styles/tokens.css in sync;
|
||||
// CSS cannot import these values.
|
||||
export const THEME_BG = { light: '#fbfaf7', dark: '#201f1d' };
|
||||
|
||||
export const site = {
|
||||
|
|
@ -139,10 +139,10 @@ export function projectCard(entry: CollectionEntry<'work'>): ProjectCard {
|
|||
const project = data.project;
|
||||
return {
|
||||
title: project?.title ?? data.title,
|
||||
description: project?.description ?? data.description,
|
||||
description: data.description,
|
||||
thumbnail: {
|
||||
src: project?.thumbnail?.src ?? data.thumbnail.src,
|
||||
alt: project?.thumbnail?.alt ?? data.thumbnail.alt,
|
||||
alt: data.thumbnail.alt,
|
||||
},
|
||||
technologies: project?.technologies ?? data.article?.stack ?? [],
|
||||
selected: project?.selected ?? false,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ const STARTING_POINTS = 5;
|
|||
|
||||
const posts = await getArticles();
|
||||
const startingPoints = posts
|
||||
.filter((post) => post.data.article?.audience === 'recruiter-relevant')
|
||||
.filter((post) => post.data.article?.featuredOrder !== undefined)
|
||||
.sort(
|
||||
(a, b) =>
|
||||
(a.data.article?.featuredOrder ?? 99) - (b.data.article?.featuredOrder ?? 99)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue