Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/app/docs/DocsLayoutClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { usePathname } from "next/navigation";
import { Button } from "@/components/ui/button";
import { Menu, X, ChevronDown, ChevronUp } from "lucide-react";
import { Background } from "@/components/background";
import { LabCTA } from "@/components/mdx/lab-cta";
import { LabsCarousel } from "@/components/mdx/labs-carousel";
import labs from "@/data/labs.yaml";

interface NavItem {
title: string;
Expand Down Expand Up @@ -190,6 +193,16 @@ export default function DocsLayoutClient({ navigation, children }: DocsLayoutCli
{/* Main content */}
<div className="prose-lg p-4 md:p-8 lg:p-16 flex-1 prose-li:marker:text-muted-foreground prose-ol:list-decimal prose-ul:list-disc prose-blockquote:border-l-4 prose-blockquote:border-primary prose-blockquote:italic overflow-x-hidden">
{children}

{labs?.labs && labs.labs.length > 1 ? (
<LabsCarousel labs={labs.labs} />
) : labs?.labs?.length === 1 ? (
<LabCTA
title={labs.labs[0].title}
description={labs.labs[0].description}
href={labs.labs[0].href}
/>
) : null}
</div>
</div>
</div>
Expand Down
52 changes: 52 additions & 0 deletions src/components/mdx/lab-cta.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"use client"

import * as React from "react"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import KagentLogo from "@/components/icons/kagent-logo"

export interface LabCTAProps {
title: string
description: string
href: string
ctaLabel?: string
}

export function LabCTA({ title, description, href, ctaLabel = "Start the Lab" }: LabCTAProps) {
return (
<Card className="relative mt-16 overflow-hidden bg-gradient-to-br from-primary/5 to-primary/10">
<div className="pointer-events-none absolute -right-24 -top-24 h-64 w-64 rounded-full bg-primary/20 blur-3xl" />
<CardHeader className="px-8 pt-14 pb-8">
<div className="flex items-start gap-6">
<div className="flex items-center justify-center text-primary">
<KagentLogo animate width={100} height={75} aria-hidden="true" />
</div>
<div className="max-w-2xl">
<CardTitle className="text-2xl leading-tight">{title}</CardTitle>
<CardDescription className="mt-2 text-base leading-relaxed">
{description}
</CardDescription>
<div className="mt-4 hidden sm:block">
<Button size="lg" className="shadow-lg" asChild>
<a href={href} target="_blank" rel="noopener noreferrer">
{ctaLabel}
</a>
</Button>
</div>
</div>
</div>
</CardHeader>
<CardContent className="px-8 pb-8 sm:hidden">
<Button size="lg" className="w-full shadow-lg" asChild>
<a href={href} target="_blank" rel="noopener noreferrer">
{ctaLabel}
</a>
</Button>
</CardContent>
</Card>
)
}

export default LabCTA


65 changes: 65 additions & 0 deletions src/components/mdx/labs-carousel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"use client"

import * as React from "react"
import { LabCTA } from "@/components/mdx/lab-cta"
import { Button } from "@/components/ui/button"
import { ChevronLeft, ChevronRight } from "lucide-react"

interface LabItem {
id: string
title: string
description: string
href: string
}

interface LabsCarouselProps {
labs: LabItem[]
}

export function LabsCarousel({ labs }: LabsCarouselProps) {
const [index, setIndex] = React.useState(0)
const hasMultiple = labs?.length > 1

const goPrev = () => setIndex((prev) => (prev - 1 + labs.length) % labs.length)
const goNext = () => setIndex((prev) => (prev + 1) % labs.length)

if (!labs || labs.length === 0) return null

const current = labs[index]

return (
<div className="mt-10">
<div className="relative">
{hasMultiple && (
<div className="absolute -top-10 right-0 flex items-center gap-2">
<Button variant="outline" size="icon" onClick={goPrev} aria-label="Previous lab">
<ChevronLeft className="h-4 w-4" />
</Button>
<Button variant="outline" size="icon" onClick={goNext} aria-label="Next lab">
<ChevronRight className="h-4 w-4" />
</Button>
</div>
)}

<LabCTA title={current.title} description={current.description} href={current.href} />
</div>

{hasMultiple && (
<div className="mt-4 flex justify-center gap-2">
{labs.map((_, i) => (
<button
key={i}
aria-label={`Go to slide ${i + 1}`}
onClick={() => setIndex(i)}
className={`h-2 w-2 rounded-full transition-colors ${i === index ? 'bg-primary' : 'bg-muted-foreground/30 hover:bg-muted-foreground/60'}`}
/>
))}
</div>
)}
</div>
)
}

export default LabsCarousel


5 changes: 5 additions & 0 deletions src/data/labs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
labs:
- id: kagent-kmcp-discover
title: "Kagent Lab: Discover kagent and kmcp"
description: "Free, on‑demand lab: build custom AI agents with kagent and integrate tools via kmcp on Kubernetes."
href: "https://www.solo.io/resources/lab/kagent-lab-discover-kagent-kmcp/?utm_source=kagent-website&utm_medium=referral"
2 changes: 2 additions & 0 deletions src/mdx-components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { PlatformTabs } from "./components/mdx/platform-tabs";
import { Tabs } from "./components/mdx/tabs";
import SmartLink from "./components/mdx/smart-link";
import { CodeBlock } from "./components/mdx/code-block";
import { LabCTA } from "./components/mdx/lab-cta";
import Image from "next/image";
import { generateAnchorId } from "@/lib/utils";

Expand Down Expand Up @@ -167,6 +168,7 @@ export function useMDXComponents(components: MDXComponents): MDXComponents {
PlatformTabs,
Tabs,
YouTube,
LabCTA,
...components,
}),
[components]
Expand Down