feat: compose the portfolio journey layer
This commit is contained in:
@@ -3,6 +3,7 @@ import { computed, onMounted, onUnmounted, shallowRef, watch } from 'vue';
|
||||
import ContactDestination from './ContactDestination.vue';
|
||||
import DriveControls from './DriveControls.vue';
|
||||
import ExperienceTimeline from './ExperienceTimeline.vue';
|
||||
import HeroJourney from './HeroJourney.vue';
|
||||
import InfrastructureDiagram from './InfrastructureDiagram.vue';
|
||||
import JourneyHud from './JourneyHud.vue';
|
||||
import PortfolioSection from './PortfolioSection.vue';
|
||||
@@ -16,7 +17,7 @@ import { useAudioEngine } from '@/composables/useAudioEngine';
|
||||
import { useJourneySections } from '@/composables/useJourneySections';
|
||||
import { useKeyboardNavigation } from '@/composables/useKeyboardNavigation';
|
||||
import { useMotionPreferences } from '@/composables/useMotionPreferences';
|
||||
import type { PortfolioContent, SectionId } from '@/content/types';
|
||||
import type { PortfolioContent, SectionId, SectionLayout } from '@/content/types';
|
||||
import type { SceneHostState } from '@/composables/useSceneController';
|
||||
import type { MotionPolicy } from '@/journey/motion-policy';
|
||||
|
||||
@@ -29,6 +30,17 @@ const canonicalSectionIds = [
|
||||
'start', 'profile', 'experience', 'infrastructure', 'selected-builds', 'additional-work', 'toolkit', 'contact',
|
||||
] as const satisfies readonly SectionId[];
|
||||
|
||||
const sectionLayouts = {
|
||||
start: 'hero',
|
||||
profile: 'right-rail',
|
||||
experience: 'left-timeline',
|
||||
infrastructure: 'full-diagram',
|
||||
'selected-builds': 'project-stage',
|
||||
'additional-work': 'compact-rail',
|
||||
toolkit: 'toolkit-field',
|
||||
contact: 'destination',
|
||||
} as const satisfies Readonly<Record<SectionId, SectionLayout>>;
|
||||
|
||||
const navigationById = computed(() => new Map(props.content.navigation.map((item) => [item.id, item])));
|
||||
|
||||
const sectionLabel = (id: SectionId): string => {
|
||||
@@ -174,9 +186,6 @@ onUnmounted(() => removePageListeners());
|
||||
:section-label="activeSectionLabel"
|
||||
/>
|
||||
<header class="site-header">
|
||||
<h1>{{ content.identity.name }}</h1>
|
||||
<p>{{ content.identity.role }}</p>
|
||||
<p class="print-portfolio-label" aria-hidden="true">Portfolio</p>
|
||||
<SiteNavigation
|
||||
:items="canonicalNavigation"
|
||||
:journey="journey"
|
||||
@@ -185,13 +194,11 @@ onUnmounted(() => removePageListeners());
|
||||
</header>
|
||||
|
||||
<main id="portfolio-content" class="portfolio-main" tabindex="-1">
|
||||
<PortfolioSection id="start" :index="1" :eyebrow="sectionLabel('start').toUpperCase()" :heading="sectionLabel('start').toUpperCase()">
|
||||
<p>{{ content.identity.valueProposition }}</p>
|
||||
</PortfolioSection>
|
||||
<HeroJourney :identity="content.identity" @explore="navigation.onSectionLinkClick" />
|
||||
|
||||
<PortfolioSection id="profile" :index="2" :eyebrow="sectionLabel('profile').toUpperCase()" :heading="sectionLabel('profile').toUpperCase()">
|
||||
<PortfolioSection id="profile" :layout="sectionLayouts.profile" :heading="sectionLabel('profile')">
|
||||
<p>{{ content.profile.introduction }}</p>
|
||||
<dl>
|
||||
<dl class="profile-facts">
|
||||
<template v-for="fact in content.profile.screeningFacts" :key="fact.label">
|
||||
<dt>{{ fact.label }}</dt>
|
||||
<dd>{{ fact.value }}</dd>
|
||||
@@ -199,39 +206,44 @@ onUnmounted(() => removePageListeners());
|
||||
</dl>
|
||||
</PortfolioSection>
|
||||
|
||||
<PortfolioSection id="experience" :index="3" :eyebrow="sectionLabel('experience').toUpperCase()" :heading="sectionLabel('experience').toUpperCase()">
|
||||
<PortfolioSection id="experience" :layout="sectionLayouts.experience" :heading="sectionLabel('experience')">
|
||||
<ExperienceTimeline :experience="content.experience" :systems-operations="content.systemsOperations" />
|
||||
</PortfolioSection>
|
||||
|
||||
<PortfolioSection id="infrastructure" :index="4" :eyebrow="sectionLabel('infrastructure').toUpperCase()" :heading="sectionLabel('infrastructure').toUpperCase()">
|
||||
<PortfolioSection id="infrastructure" :layout="sectionLayouts.infrastructure" :heading="sectionLabel('infrastructure')">
|
||||
<InfrastructureDiagram :infrastructure="content.infrastructure" />
|
||||
</PortfolioSection>
|
||||
|
||||
<PortfolioSection id="selected-builds" :index="5" :eyebrow="sectionLabel('selected-builds').toUpperCase()" :heading="sectionLabel('selected-builds').toUpperCase()">
|
||||
<ProjectCaseStudy
|
||||
v-for="project in content.projects.selected"
|
||||
:key="project.id"
|
||||
:project="project"
|
||||
:allow-automatic-video="motion.policy.value.allowAutomaticVideo"
|
||||
/>
|
||||
<PortfolioSection id="selected-builds" :layout="sectionLayouts['selected-builds']" eyebrow="Selected work" :heading="sectionLabel('selected-builds')">
|
||||
<div class="project-stage__projects">
|
||||
<ProjectCaseStudy
|
||||
v-for="(project, index) in content.projects.selected"
|
||||
:key="project.id"
|
||||
:project="project"
|
||||
:priority="index < 2 ? 'primary' : 'supporting'"
|
||||
:allow-automatic-video="motion.policy.value.allowAutomaticVideo"
|
||||
/>
|
||||
</div>
|
||||
</PortfolioSection>
|
||||
|
||||
<PortfolioSection id="additional-work" :index="6" :eyebrow="sectionLabel('additional-work').toUpperCase()" :heading="sectionLabel('additional-work').toUpperCase()">
|
||||
<ProjectCard
|
||||
v-for="project in content.projects.additional"
|
||||
:key="project.id"
|
||||
:project="project"
|
||||
:allow-automatic-video="motion.policy.value.allowAutomaticVideo"
|
||||
/>
|
||||
<PortfolioSection id="additional-work" :layout="sectionLayouts['additional-work']" :heading="sectionLabel('additional-work')">
|
||||
<div class="compact-projects">
|
||||
<ProjectCard
|
||||
v-for="project in content.projects.additional"
|
||||
:key="project.id"
|
||||
:project="project"
|
||||
:allow-automatic-video="motion.policy.value.allowAutomaticVideo"
|
||||
/>
|
||||
</div>
|
||||
</PortfolioSection>
|
||||
|
||||
<PortfolioSection id="toolkit" :index="7" :eyebrow="sectionLabel('toolkit').toUpperCase()" :heading="sectionLabel('toolkit').toUpperCase()">
|
||||
<PortfolioSection id="toolkit" :layout="sectionLayouts.toolkit" :heading="sectionLabel('toolkit')">
|
||||
<ToolkitGrid :groups="content.toolkit" />
|
||||
</PortfolioSection>
|
||||
|
||||
<PortfolioSection id="contact" :index="8" :eyebrow="sectionLabel('contact').toUpperCase()" :heading="sectionLabel('contact').toUpperCase()">
|
||||
<PortfolioSection id="contact" :layout="sectionLayouts.contact" eyebrow="Destination" :heading="sectionLabel('contact')">
|
||||
<footer>
|
||||
<ContactDestination :contact="content.contact" :identity="content.identity" />
|
||||
<ContactDestination :contact="content.contact" />
|
||||
</footer>
|
||||
</PortfolioSection>
|
||||
</main>
|
||||
|
||||
Reference in New Issue
Block a user