Skip to content

Commit f503985

Browse files
committed
get the mvp ready
1 parent 850334d commit f503985

File tree

5 files changed

+148
-0
lines changed

5 files changed

+148
-0
lines changed

astro.config.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ export default defineConfig({
3939
title: 'Docs',
4040
favicon: '/images/favicons/favicon.ico',
4141
customCss: ['./src/styles/global.css'],
42+
components: {
43+
TwoColumnContent: './src/components/ContentWithPricing.astro',
44+
},
4245
head: [
4346
{
4447
tag: 'script',
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
import Default from '@astrojs/starlight/components/TwoColumnContent.astro';
3+
import PricingBadge from './PricingBadge.astro';
4+
5+
// Check if this is an AWS service page (but not the index page)
6+
const route = Astro.locals.starlightRoute;
7+
const isAwsServicePage = route.id.startsWith('aws/services/') && !route.id.includes('/index');
8+
---
9+
10+
<Default>
11+
<!-- Show pricing info at the top of content for AWS service pages -->
12+
{isAwsServicePage && <PricingBadge />}
13+
14+
<!-- Regular page content -->
15+
<slot />
16+
17+
<!-- Pass through right sidebar slot -->
18+
<slot name="right-sidebar" slot="right-sidebar" />
19+
</Default>

src/components/PricingBadge.astro

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
import PricingBadge from './PricingBadge.tsx';
3+
4+
// Get the current page's frontmatter data
5+
const route = Astro.locals.starlightRoute;
6+
const tags = route.entry?.data?.tags || [];
7+
8+
---
9+
10+
{tags.length > 0 && <PricingBadge tags={tags} client:load />}
11+
12+
13+
<style>
14+
:global(.pricing-badge-container) {
15+
margin-bottom: 1.5rem;
16+
padding: 1rem;
17+
background: var(--sl-color-bg-sidebar);
18+
border: 1px solid var(--sl-color-gray-5);
19+
border-radius: 0.5rem;
20+
border-left: 4px solid var(--sl-color-accent);
21+
}
22+
23+
:global(.pricing-badge-header) {
24+
margin-bottom: 0.5rem;
25+
}
26+
27+
:global(.pricing-badge-details) {
28+
display: flex;
29+
align-items: center;
30+
flex-wrap: wrap;
31+
gap: 0.25rem;
32+
}
33+
</style>

src/components/PricingBadge.tsx

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import React from 'react';
2+
3+
type PricingTier = 'Free' | 'Base' | 'Ultimate';
4+
5+
interface PricingBadgeProps {
6+
tags: string[];
7+
}
8+
9+
const PricingBadge: React.FC<PricingBadgeProps> = ({ tags }) => {
10+
// Find pricing tags from the tags array
11+
const pricingTags = tags.filter((tag): tag is PricingTier =>
12+
['Free', 'Base', 'Ultimate'].includes(tag)
13+
);
14+
15+
if (pricingTags.length === 0) return null;
16+
17+
// Sort by hierarchy and take the highest tier
18+
const sortedTags = pricingTags.sort((a, b) => {
19+
const order: Record<PricingTier, number> = { 'Free': 0, 'Base': 1, 'Ultimate': 2 };
20+
return order[a] - order[b];
21+
});
22+
23+
const primaryPlan = sortedTags[sortedTags.length - 1];
24+
25+
// Determine which plans have access based on inheritance
26+
const getAvailablePlans = (plan: PricingTier): PricingTier[] => {
27+
switch (plan) {
28+
case 'Free':
29+
return ['Free', 'Base', 'Ultimate'];
30+
case 'Base':
31+
return ['Base', 'Ultimate'];
32+
case 'Ultimate':
33+
return ['Ultimate'];
34+
}
35+
};
36+
37+
const availablePlans = getAvailablePlans(primaryPlan);
38+
39+
const getBadgeColor = (plan: PricingTier) => {
40+
switch (plan) {
41+
case 'Free':
42+
return '#10b981'; // green
43+
case 'Base':
44+
return '#3b82f6'; // blue
45+
case 'Ultimate':
46+
return '#f59e0b'; // amber
47+
}
48+
};
49+
50+
return (
51+
<div className="pricing-badge-container">
52+
<div className="pricing-badge-header">
53+
<span
54+
className="pricing-badge-main"
55+
style={{
56+
backgroundColor: getBadgeColor(primaryPlan),
57+
color: 'white',
58+
padding: '0.25rem 0.75rem',
59+
borderRadius: '0.375rem',
60+
fontSize: '0.875rem',
61+
fontWeight: 600
62+
}}
63+
>
64+
Available on {primaryPlan}
65+
</span>
66+
</div>
67+
<div className="pricing-badge-details">
68+
<span style={{ fontSize: '0.875rem', color: '#6b7280' }}>
69+
This service is available on: {' '}
70+
</span>
71+
{availablePlans.map((plan, index) => (
72+
<span key={plan}>
73+
<span
74+
style={{
75+
fontWeight: 600,
76+
color: getBadgeColor(plan)
77+
}}
78+
>
79+
{plan}
80+
</span>
81+
{index < availablePlans.length - 1 && (
82+
<span style={{ color: '#6b7280' }}></span>
83+
)}
84+
</span>
85+
))}
86+
</div>
87+
</div>
88+
);
89+
};
90+
91+
export { PricingBadge };
92+
export default PricingBadge;

src/content.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export const collections = {
1212
deployment: z.array(z.string()).optional(),
1313
pro: z.boolean().optional(),
1414
leadimage: z.string().optional(),
15+
tags: z.array(z.string()).optional(),
1516
}),
1617
}),
1718
}),

0 commit comments

Comments
 (0)