diff --git a/DESIGN.md b/DESIGN.md index 4be0fd4..6ce6aa1 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -18,7 +18,15 @@ Port of the visual system for ewancroft.uk. - **Tone**: Clinical, efficient, dense. - **Locations**: Blog listings, ATProto profiles, Project indices. -- **Patterns**: Panel primitives, row-based listings, minimal decoration. +- **Patterns**: Panel primitives, editorial indexes, minimal decoration. + +### Editorial indexes + +- Use a raised parent surface with a 4px inset to group compact rows. +- Use the Selected Projects row anatomy across UI collections: a clear label, supporting detail, and trailing metadata where relevant. +- Actionable rows share a primary-tinted hover and keyboard-focus highlight. Static rows do not imply interactivity. +- Apply the brief quart-eased lift only to actionable rows, and remove it when reduced motion is preferred. +- Keep prose lists semantic and unstyled; this pattern is for navigational and data indexes. ## Anti-references diff --git a/src/lib/components/BacklinkAvatars.svelte b/src/lib/components/BacklinkAvatars.svelte index f53ca97..ec3d773 100644 --- a/src/lib/components/BacklinkAvatars.svelte +++ b/src/lib/components/BacklinkAvatars.svelte @@ -243,15 +243,12 @@ } .backlink-avatar { - transition: - transform var(--duration-fast) var(--ease-out-quart), - box-shadow var(--duration-fast) var(--ease-out-quart); + transition: opacity var(--duration-fast) var(--ease-out-quart); } .backlink-trigger:hover .backlink-avatar { z-index: 20 !important; - transform: translateY(-3px) scale(1.08); - box-shadow: 0 4px 12px oklch(0% 0 0 / 0.18); + opacity: 0.72; } .backlink-avatar img { diff --git a/src/lib/components/Header.svelte b/src/lib/components/Header.svelte index 90f40cb..8475467 100644 --- a/src/lib/components/Header.svelte +++ b/src/lib/components/Header.svelte @@ -23,10 +23,8 @@
- +
- [01]

Identity

@@ -265,10 +259,9 @@
- +
- [02]

Colour Architecture

@@ -321,10 +314,9 @@
- +
- [03]

Typography

@@ -376,10 +368,9 @@
- +
- [04]

Prose Styling

@@ -397,10 +388,9 @@
- +
- [05]

Geometry

@@ -436,10 +426,9 @@
- +
- [06]

Motion

@@ -468,10 +457,9 @@
- +
- [07]

Iconography

@@ -505,10 +493,9 @@
- +
- [08]

Components

@@ -533,6 +520,49 @@
+
+

Editorial Index

+

+ The default collection pattern for projects, posts, profiles, links, support options, and site metadata. A raised parent surface groups compact inset rows; only actionable rows receive the shared hover and keyboard-focus treatment. +

+
+
+ DEFAULT UI LIST + .project-grid / .post-list / .meta-list +
+
+ + Interactive row +

Primary-tinted hover and keyboard-focus state.

+ LINK +
+
+ Static row +

No highlight or lift when the row has no action.

+ DATA +
+
+
+
+
Container
+
--surface-raised with a --space-xs inset
+
+
+
Row
+
--space-3 padding and --radius-sm corners
+
+
+
Highlight
+
12% primary mixed into the sunken surface
+
+
+
Motion
+
2px lift over 200ms; removed for reduced motion
+
+
+
+
+

Interactive Elements

@@ -564,10 +594,9 @@
- +
- [09]

Layout Systems

@@ -593,10 +622,9 @@
- +
- [10]

Voice & Tone

@@ -620,19 +648,17 @@
- +
- [11]

Manifesto

{#each principles as p}
- {p.number}
-

{p.name}

+

{p.name}

{p.description}

@@ -641,10 +667,9 @@
- +
- [13]

Assets

diff --git a/src/routes/site/meta/+page.svelte b/src/routes/site/meta/+page.svelte index eb5fca9..5ae9c55 100644 --- a/src/routes/site/meta/+page.svelte +++ b/src/routes/site/meta/+page.svelte @@ -6,23 +6,6 @@ let { data } = $props(); const info = $derived(data.siteInfo as NormalizedSiteInfo | null); - const visibleSections = $derived.by(() => { - if (!info) return []; - return [ - info.additionalInfo?.purpose ? 'purpose' : undefined, - info.additionalInfo?.websiteBirthYear ? 'history' : undefined, - info.privacyStatement || info.additionalInfo?.analytics ? 'privacy' : undefined, - info.openSourceInfo ? 'open-source' : undefined, - info.technologyStack.length ? 'tech-stack' : undefined, - info.additionalInfo?.deployment || info.additionalInfo?.sectionLicense.length ? 'operations' : undefined, - info.credits.length ? 'credits' : undefined, - ].filter((section): section is string => Boolean(section)); - }); - - function sectionNumber(id: string): string { - const index = visibleSections.indexOf(id); - return `[${String(index + 1).padStart(2, '0')}]`; - } function groupBySection(items: T[]): Map { const grouped = new Map(); @@ -50,7 +33,6 @@ {#if info.additionalInfo?.purpose}
- {sectionNumber('purpose')}

Purpose

{info.additionalInfo.purpose}

@@ -60,7 +42,6 @@ {#if info.additionalInfo?.websiteBirthYear}
- {sectionNumber('history')}

History

This website was first launched in {info.additionalInfo.websiteBirthYear}.

@@ -70,7 +51,6 @@ {#if info.privacyStatement || info.additionalInfo?.analytics}
- {sectionNumber('privacy')}

Privacy

{#if info.privacyStatement}

{info.privacyStatement}

{/if} @@ -98,7 +78,6 @@ {#if info.openSourceInfo}
- {sectionNumber('open-source')}

Open Source

{#if info.openSourceInfo.description} @@ -172,7 +151,6 @@ {#if info.technologyStack?.length}
- {sectionNumber('tech-stack')}

Technology Stack

{#each groupBySection(info.technologyStack) as [section, techs]} @@ -205,7 +183,6 @@ {#if info.additionalInfo?.deployment || info.additionalInfo?.sectionLicense.length}
- {sectionNumber('operations')}

Operations & licensing

@@ -238,7 +215,6 @@ {#if info.credits?.length}
- {sectionNumber('credits')}

Credits

{#each groupBySection(info.credits) as [section, credits]}