feat: cross-link related blueprints on the detail page
The title-block "Extends" now links to the parent blueprint when it is illustrated, and a new "Related blueprints" section lists hosts, siblings, and extensions. References resolve to live links via the registry and fall back to plain text otherwise, so PasswordAuth and RememberMe now interlink.
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch, type Component } from "vue"
|
||||
import type { Blueprint } from "@/data/blueprint"
|
||||
import { slugForName } from "@/data/blueprints"
|
||||
import FunctionReadout from "@/components/FunctionReadout.vue"
|
||||
import CompositionMap from "@/components/CompositionMap.vue"
|
||||
import StateMachine from "@/components/StateMachine.vue"
|
||||
|
||||
const props = defineProps<{ blueprint: Blueprint; specimen: Component }>()
|
||||
|
||||
const extendsSlug = computed(() => slugForName(props.blueprint.extendsName))
|
||||
|
||||
const activeId = ref("full")
|
||||
// reset to the overview whenever we switch blueprints
|
||||
watch(
|
||||
@@ -47,7 +50,12 @@ const funcCount = computed(() => props.blueprint.functions.length)
|
||||
</div>
|
||||
<div class="tb-cell">
|
||||
<div class="tb-k">Extends</div>
|
||||
<div class="tb-v">{{ blueprint.extendsName ?? "—" }}</div>
|
||||
<div class="tb-v">
|
||||
<RouterLink v-if="extendsSlug" :to="`/b/${extendsSlug}`" class="xlink">{{
|
||||
blueprint.extendsName
|
||||
}}</RouterLink>
|
||||
<template v-else>{{ blueprint.extendsName ?? "—" }}</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tb-cell">
|
||||
<div class="tb-k">Role</div>
|
||||
@@ -168,6 +176,23 @@ const funcCount = computed(() => props.blueprint.functions.length)
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- COMPANION 3: related blueprints -->
|
||||
<template v-if="blueprint.related?.length">
|
||||
<h2 class="section">Related blueprints</h2>
|
||||
<div class="related">
|
||||
<template v-for="r in blueprint.related" :key="r.name">
|
||||
<RouterLink v-if="slugForName(r.name)" :to="`/b/${slugForName(r.name)}`" class="rel link">
|
||||
<span class="rel-name">{{ r.name }} <span class="rel-arrow">▸</span></span>
|
||||
<span class="rel-rel">{{ r.relation }}</span>
|
||||
</RouterLink>
|
||||
<div v-else class="rel">
|
||||
<span class="rel-name">{{ r.name }}</span>
|
||||
<span class="rel-rel">{{ r.relation }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<footer class="credit">
|
||||
<div>
|
||||
<span class="ck">SOURCE</span> blueprint-ontology / blueprints / {{ blueprint.slug }} ·
|
||||
@@ -456,6 +481,54 @@ code {
|
||||
color: #7ea6cd;
|
||||
}
|
||||
|
||||
/* cross-links */
|
||||
.xlink {
|
||||
color: var(--color-secondary);
|
||||
text-decoration: none;
|
||||
border-bottom: 1px dashed color-mix(in srgb, var(--color-secondary) 50%, transparent);
|
||||
}
|
||||
.xlink:hover {
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
.related {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
||||
gap: 8px;
|
||||
}
|
||||
.rel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
border: 1px solid rgba(200, 226, 255, 0.14);
|
||||
padding: 8px 12px;
|
||||
text-decoration: none;
|
||||
}
|
||||
.rel.link {
|
||||
border-color: rgba(200, 226, 255, 0.3);
|
||||
cursor: pointer;
|
||||
transition: all 0.12s;
|
||||
}
|
||||
.rel.link:hover {
|
||||
border-color: var(--color-secondary);
|
||||
background: var(--color-base-200);
|
||||
}
|
||||
.rel-name {
|
||||
font-size: 13px;
|
||||
color: #7ea6cd;
|
||||
}
|
||||
.rel.link .rel-name {
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
.rel-arrow {
|
||||
font-size: 10px;
|
||||
}
|
||||
.rel-rel {
|
||||
font-size: 10px;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
color: #4f7099;
|
||||
}
|
||||
|
||||
.credit {
|
||||
margin-top: 34px;
|
||||
padding-top: 14px;
|
||||
|
||||
@@ -302,4 +302,11 @@ export const rememberMe: Blueprint = {
|
||||
},
|
||||
|
||||
stateMachine: REMEMBER_ME_MACHINE,
|
||||
|
||||
related: [
|
||||
{ name: "PasswordAuth", relation: "host · requires" },
|
||||
{ name: "StatelessSession", relation: "sibling capability" },
|
||||
{ name: "MFA", relation: "sibling capability" },
|
||||
{ name: "Captcha", relation: "sibling capability" },
|
||||
],
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user