Skip to content

Commit 84bee65

Browse files
committed
Atomic migration: Merge CalloutCTA into Callout with optional CTA slot
## Simplification **Before:** Two components (Callout + CalloutCTA) forced "which one?" decision **After:** One Callout component with optional `<slot name="cta">` composition ## Implementation ### Callout.astro - Add CTA section styling (CVA variants matching parent callout) - Add conditional `{Astro.slots.has('cta')}` rendering - Maintain all existing props/variants - Zero breaking changes for Callout-only usage ### Migration (23 instances) - statsbomb.mdx: 2 CalloutCTA → Callout with CTA slot - callout-cta-demo.astro: 10 CalloutCTA → Callout (+ demo page renamed to callout-demo.astro) - Callout.stories.ts: Added 3 CTA slot examples ### Cleanup - Delete src/components/CalloutCTA.astro (wrapper component no longer needed) - Rename callout-cta-demo.astro → callout-demo.astro - Delete GITHUB-SETTINGS-CHECKLIST.md (completed manual task) ### Documentation - CLAUDE.md: Update component examples and forbidden patterns - README.md: Update repo structure and story points - Callout.stories.ts: Add CTA slot examples (PrimaryWithCTA, SecondaryWithCTA, WarningWithCTA) ## Usage Patterns **Without CTA slot (information only):** ```astro <Callout variant="primary" title="Insight" icon="lightbulb"> <Body>Making illegal states unrepresentable...</Body> </Callout> ``` **With CTA slot (dedicated action section):** ```astro <Callout variant="secondary" title="Dive Deeper" icon="code"> <Body>ANTLR grammar, XState machines...</Body> <Fragment slot="cta"> <Button variant="ghost" size="sm" href="#">View Appendix →</Button> </Fragment> </Callout> ``` ## Cognitive Overhead Reduction - ✅ One component to learn (not two) - ✅ Composition pattern (slots) instead of wrapper - ✅ Simpler mental model: "Need CTA? Add slot!" - ✅ Atomic migration (zero CalloutCTA references remain) ## Complexity: 11 story points - Callout.astro update: 3 points - Migrate 23 instances: 5 points - Update documentation: 2 points - Cleanup + verification: 1 point
1 parent 9ef014c commit 84bee65

File tree

8 files changed

+154
-278
lines changed

8 files changed

+154
-278
lines changed

CLAUDE.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -415,12 +415,13 @@ if (!prefersReducedMotion()) {
415415
<Card variant="default">Content</Card>
416416
<Link href="/about">About</Link>
417417
<Callout variant="primary" title="Insight">Info without action</Callout>
418-
<CalloutCTA variant="secondary" title="Title" icon="code">
418+
419+
<Callout variant="secondary" title="Title" icon="code">
419420
<Body size="sm">Content with primary action...</Body>
420421
<Fragment slot="cta">
421422
<Button variant="ghost" size="sm" href="#">Action →</Button>
422423
</Fragment>
423-
</CalloutCTA>
424+
</Callout>
424425
```
425426

426427
**Typography Components:**
@@ -479,7 +480,7 @@ if (!prefersReducedMotion()) {
479480
- Arbitrary colors: `text-gray-*`, `bg-[#...]`, `text-slate-*`
480481
- Arbitrary sizes: `text-[22px]`, `p-[18px]`, `mb-13`
481482
- Custom CTA wrappers: `<div class="bg-surface ...">` with manual buttons
482-
- Inline action links in Callout: Use CalloutCTA with Button in cta slot instead
483+
- Inline action links instead of CTA slot: Use CTA slot for dedicated action sections with visual separation
483484

484485
**Why**: Type-safe CVA variants prevent class drift, ensure WCAG AA compliance
485486

@@ -557,7 +558,7 @@ classDef system fill:#D1FAE5,stroke:#10B981,stroke-width:2px,color:#065F46
557558
- ✅ Statsbomb case study (25-min read, 6 sections, complete)
558559
- ✅ Photo gallery with PhotoSwipe integration
559560
- ✅ Bio, resume, contact pages
560-
-CalloutCTA component (3 story points)
561+
-Callout with optional CTA slot (3 story points)
561562
- ✅ Scroll progress redesign (3 story points)
562563
- ✅ LinkedIn announcement published
563564

GITHUB-SETTINGS-CHECKLIST.md

Lines changed: 0 additions & 177 deletions
This file was deleted.

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ This entire codebase was developed through iterative collaboration with Claude C
2222
```astro
2323
<Button variant="primary" size="md" href="/portfolio">
2424
<Badge variant="skill">TypeScript</Badge>
25-
<CalloutCTA variant="secondary" title="Explore">
25+
<Callout variant="secondary" title="Explore">
2626
<Body>Content with semantic typography...</Body>
2727
<Fragment slot="cta">
2828
<Button variant="ghost" size="sm" href="#">Action →</Button>
2929
</Fragment>
30-
</CalloutCTA>
30+
</Callout>
3131
```
3232

3333
### Egyptian Heritage Design Language
@@ -52,7 +52,7 @@ Mermaid diagrams with custom theme using semantic node taxonomy (atomic/derived/
5252
│ ├── components/ # 30+ production components
5353
│ │ ├── Button.astro # CVA variants: primary, secondary, ghost
5454
│ │ ├── Badge.astro # Semantic: skill, category, status
55-
│ │ ├── CalloutCTA.astro # Compound component with action slot
55+
│ │ ├── Callout.astro # With optional CTA slot composition
5656
│ │ ├── patterns/ # Egyptian geometric patterns
5757
│ │ │ ├── PyramidGrid.astro
5858
│ │ │ └── WaterFlow.astro
@@ -295,7 +295,7 @@ Why story points? Time lies. AI acceleration unpredictable. Complexity is stable
295295
**Examples from this project:**
296296
- Responsive design system: 8 points (cross-cutting architecture)
297297
- Diagram design system: 6 points (new visual taxonomy)
298-
- CalloutCTA component: 3 points (compound component with slots)
298+
- Callout with optional CTA slot: 3 points (composition pattern)
299299
- Scroll progress redesign: 3 points (mobile/desktop variants)
300300

301301
---

src/components/Callout.astro

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,37 @@ const content = cva([
4545
'[&>p:last-child]:mb-0', // Remove bottom margin from last paragraph
4646
]);
4747
48+
// CTA section styling - cohesive with parent Callout variant
49+
const ctaSection = cva(
50+
[
51+
'flex',
52+
'flex-wrap',
53+
'gap-3',
54+
'items-center',
55+
'border-t',
56+
],
57+
{
58+
variants: {
59+
variant: {
60+
primary: 'border-primary/20', // Gold accent (matches callout left border)
61+
secondary: 'border-secondary/20', // Blue accent
62+
warning: 'border-warning/20', // Amber accent
63+
success: 'border-success/20', // Emerald accent
64+
neutral: 'border-neutral/30', // Gray (higher opacity for visibility)
65+
},
66+
size: {
67+
default: 'pt-6 mt-6', // 24px Fibonacci spacing
68+
compact: 'pt-4 mt-4', // 16px Fibonacci spacing
69+
inline: 'pt-3 mt-3', // 12px Fibonacci spacing
70+
},
71+
},
72+
defaultVariants: {
73+
variant: 'primary',
74+
size: 'default',
75+
},
76+
}
77+
);
78+
4879
// Icon type - SEMANTIC ONLY
4980
type IconName = 'lightbulb' | 'layers' | 'alert' | 'code' | 'quote' | 'info' | 'none';
5081
@@ -88,4 +119,10 @@ const IconComponent = iconMap[icon];
88119
<div class={content()}>
89120
<slot />
90121
</div>
122+
123+
{Astro.slots.has('cta') && (
124+
<div class={clsx(ctaSection({ variant, size }))} role="group" aria-label="Actions">
125+
<slot name="cta" />
126+
</div>
127+
)}
91128
</aside>

src/components/Callout.stories.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,46 @@ export const VisualRhythmExample = {
230230
</div>`,
231231
},
232232
};
233+
234+
// =============================================================================
235+
// CTA SLOT EXAMPLES (Optional Action Section)
236+
// =============================================================================
237+
238+
export const PrimaryWithCTA = {
239+
args: {
240+
variant: "primary",
241+
size: "default",
242+
title: "For Engineers: Technical Deep Dive",
243+
icon: "code",
244+
},
245+
slots: {
246+
default: `<p class="text-text-lighter">ANTLR grammar, XState machines, functional pipelines, event graphs, and production debugging strategies.</p>`,
247+
cta: `<a href="#technical" class="inline-flex items-center gap-2 px-4 py-2 rounded-md bg-transparent border border-primary text-primary hover:bg-primary hover:text-background transition-colors">View Technical Appendix →</a>`,
248+
},
249+
};
250+
251+
export const SecondaryWithCTA = {
252+
args: {
253+
variant: "secondary",
254+
size: "default",
255+
title: "Ready to discuss your project?",
256+
icon: "info",
257+
},
258+
slots: {
259+
default: `<p class="text-text-lighter">Let's explore how functional architecture patterns can solve your team's engineering challenges.</p>`,
260+
cta: `<a href="/contact" class="inline-flex items-center gap-2 px-4 py-2 rounded-md bg-secondary text-background hover:bg-secondary/90 transition-colors">Start a Conversation</a>`,
261+
},
262+
};
263+
264+
export const WarningWithCTA = {
265+
args: {
266+
variant: "warning",
267+
size: "default",
268+
title: "⚠️ Breaking Change Notice",
269+
icon: "alert",
270+
},
271+
slots: {
272+
default: `<p class="text-text-lighter">The authentication API will be updated next week. Please review the migration guide and update your integration before the deadline.</p>`,
273+
cta: `<a href="#migration" class="inline-flex items-center gap-2 px-4 py-2 rounded-md bg-transparent border border-warning text-warning hover:bg-warning hover:text-background transition-colors">View Migration Guide</a>`,
274+
},
275+
};

src/components/CalloutCTA.astro

Lines changed: 0 additions & 50 deletions
This file was deleted.

0 commit comments

Comments
 (0)