feat(sections): add ThreeAmWalkthrough component
Replaces DualValueProps + ProductShowcase with a single before/after split: a styled <pre> block (the 'without' state) next to the existing /product/error-detail.png screenshot (the 'with' state). Three short callouts below. Section anchor #walkthrough is the target for the Hero's 'See it in action ↓' secondary CTA (added in Task 4). The 'without' panel is implemented as a styled <pre> per the spec — no asset production required. A future phase may swap to a recorded terminal screencap; that swap is a one-component change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
104
src/components/sections/ThreeAmWalkthrough.astro
Normal file
104
src/components/sections/ThreeAmWalkthrough.astro
Normal file
@@ -0,0 +1,104 @@
|
||||
---
|
||||
import Lightbox from '../Lightbox.astro';
|
||||
|
||||
interface Callout {
|
||||
title: string;
|
||||
body: string;
|
||||
}
|
||||
|
||||
const callouts: Callout[] = [
|
||||
{
|
||||
title: 'Cross-service correlation.',
|
||||
body: 'Every exchange carries its correlation ID forward. One click jumps to what the downstream route did with the same message.',
|
||||
},
|
||||
{
|
||||
title: 'Runtime detail, not guesswork.',
|
||||
body: 'Circuit breaker tripped. Fallback path ran. Request tried backend:80. The pieces a 3 AM page actually needs — already captured.',
|
||||
},
|
||||
{
|
||||
title: 'The whole story of a failure.',
|
||||
body: 'Exception class, message, stack trace, headers, payload — all pinned to the exchange. No log-grepping tour.',
|
||||
},
|
||||
];
|
||||
---
|
||||
<section id="walkthrough" class="border-b border-border bg-bg">
|
||||
<div class="max-w-content mx-auto px-6 py-24 md:py-32">
|
||||
<div class="max-w-3xl mb-14 md:mb-20">
|
||||
<p class="text-cyan font-mono text-xs tracking-[0.25em] uppercase mb-4">// When something breaks</p>
|
||||
<h2 class="text-hero font-bold text-text mb-5">
|
||||
The 3 AM page. With and without Cameleer.
|
||||
</h2>
|
||||
<p class="text-lg text-text-muted leading-relaxed">
|
||||
Same Camel app. Same failed exchange. Different night.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-2 gap-6 md:gap-8 items-stretch">
|
||||
<div class="without-card relative rounded-lg border border-dashed border-border-strong bg-bg overflow-hidden">
|
||||
<div class="px-5 pt-5 pb-3 font-mono text-[11px] tracking-[0.2em] uppercase text-text-faint border-b border-border">
|
||||
Without Cameleer · 03:12 AM
|
||||
</div>
|
||||
<pre class="font-mono text-[13px] leading-[1.65] text-text-muted px-5 py-5 overflow-x-auto whitespace-pre"><code><span class="text-text">$</span> kubectl logs camel-router-7d4f8c
|
||||
<span class="text-rose">ERROR</span> org.apache.camel.CamelExecutionException
|
||||
at org.apache.camel.processor.SendProcessor.process
|
||||
at org.apache.camel.processor.Pipeline.process
|
||||
...
|
||||
|
||||
<span class="text-text">$</span> grep "order-842" *.log
|
||||
router-3.log: <span class="text-accent">WARN</span> exchange order-842 stuck in saga-fulfillment
|
||||
router-3.log: <span class="text-rose">ERROR</span> processor backend:80 → connect timeout
|
||||
|
||||
<span class="text-text">$</span> ssh prod-integration-3
|
||||
prod-integration-3 $ kubectl logs ...
|
||||
|
||||
> <span class="text-cyan">slack #integration-team</span>
|
||||
"anyone know why order-842 is stuck??"
|
||||
<span class="text-text-faint">[3 of 4 reactions, no answer]</span>
|
||||
|
||||
<span class="text-accent">~47 min later: someone wakes up an SRE.</span></code></pre>
|
||||
</div>
|
||||
|
||||
<figure class="with-card relative rounded-lg border border-border-strong bg-bg-elevated overflow-hidden">
|
||||
<div class="px-5 pt-5 pb-3 font-mono text-[11px] tracking-[0.2em] uppercase text-accent border-b border-border">
|
||||
With Cameleer · 30 sec
|
||||
</div>
|
||||
<Lightbox
|
||||
src="/product/error-detail.png"
|
||||
alt="Cameleer Mission Control — failed exchange order-842 with full execution context"
|
||||
width={1920}
|
||||
height={945}
|
||||
loading="lazy"
|
||||
imgClass="block w-full h-auto"
|
||||
/>
|
||||
<div class="px-5 py-4 font-mono text-[13px] leading-[1.6] text-text-muted border-t border-border">
|
||||
<span class="text-accent">▸</span> Open exchange <span class="text-text">order-842</span> → see the failure pinned → click <span class="text-text">Replay</span> after fix.
|
||||
</div>
|
||||
<div class="absolute inset-0 ring-1 ring-inset ring-accent/10 pointer-events-none rounded-lg"></div>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
<ul class="grid md:grid-cols-3 gap-6 md:gap-8 mt-14">
|
||||
{callouts.map((c, i) => (
|
||||
<li class="relative pl-10">
|
||||
<span
|
||||
class="absolute left-0 top-0 inline-flex items-center justify-center w-7 h-7 rounded-full border border-accent/40 bg-accent/10 text-accent font-mono text-xs"
|
||||
aria-hidden="true"
|
||||
>
|
||||
{String(i + 1).padStart(2, '0')}
|
||||
</span>
|
||||
<h3 class="text-text font-semibold mb-1.5">{c.title}</h3>
|
||||
<p class="text-text-muted leading-relaxed">{c.body}</p>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.with-card {
|
||||
box-shadow:
|
||||
0 1px 0 rgba(240, 180, 41, 0.08) inset,
|
||||
0 30px 60px -25px rgba(0, 0, 0, 0.7),
|
||||
0 12px 30px -12px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user