feat(presentation): align lightning talk with Build theme

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Fatih Kadir Akın
2026-06-02 16:38:49 -07:00
parent 44abe71542
commit 0d25ab70fd
7 changed files with 107 additions and 54 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 319 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

+47 -35
View File
@@ -53,10 +53,24 @@ type CardProps = {
accent?: string;
};
function PixelEdge() {
return (
<div
className="pointer-events-none absolute inset-x-0 top-0 h-1.5"
style={{
backgroundImage:
"repeating-linear-gradient(90deg, #F25022 0 7px, #FFB900 7px 14px, #7FBA00 14px 21px, #00A4EF 21px 28px)",
}}
aria-hidden
/>
);
}
function Card({ icon: Icon, title, children, accent = "text-primary" }: CardProps) {
return (
<div className="rounded-3xl border border-border/70 bg-background/70 p-6 shadow-sm backdrop-blur transition-transform duration-300 hover:-translate-y-1">
<div className={`mb-4 flex h-12 w-12 items-center justify-center rounded-2xl bg-primary/10 ${accent}`}>
<div className="relative border border-white/12 bg-white/[0.03] p-6 pt-7 shadow-sm backdrop-blur transition-transform duration-300 hover:-translate-y-1">
<PixelEdge />
<div className={`mb-4 flex h-12 w-12 items-center justify-center bg-primary/10 ${accent}`}>
<Icon className="h-6 w-6" />
</div>
<h3 className="mb-2 text-2xl font-bold text-foreground">{title}</h3>
@@ -67,7 +81,7 @@ function Card({ icon: Icon, title, children, accent = "text-primary" }: CardProp
function Pill({ children }: { children: ReactNode }) {
return (
<span className="inline-flex items-center rounded-full border border-primary/20 bg-primary/10 px-4 py-2 text-base font-semibold text-primary">
<span className="inline-flex items-center rounded-none border border-primary/40 bg-primary/10 px-4 py-2 font-mono text-sm font-semibold uppercase tracking-[0.18em] text-primary">
{children}
</span>
);
@@ -75,12 +89,12 @@ function Pill({ children }: { children: ReactNode }) {
function CodePanel({ children, title = "prompt.md" }: { children: ReactNode; title?: string }) {
return (
<div className="overflow-hidden rounded-3xl border border-border bg-zinc-950 text-zinc-100 shadow-2xl">
<div className="overflow-hidden rounded-none border border-border bg-zinc-950 text-zinc-100 shadow-2xl">
<div className="flex items-center justify-between border-b border-white/10 bg-white/5 px-5 py-3">
<div className="flex gap-2">
<span className="h-3 w-3 rounded-full bg-red-400" />
<span className="h-3 w-3 rounded-full bg-yellow-400" />
<span className="h-3 w-3 rounded-full bg-green-400" />
<span className="h-3 w-3 rounded-none bg-red-400" />
<span className="h-3 w-3 rounded-none bg-yellow-400" />
<span className="h-3 w-3 rounded-none bg-green-400" />
</div>
<span className="font-mono text-xs text-zinc-400">{title}</span>
</div>
@@ -91,8 +105,9 @@ function CodePanel({ children, title = "prompt.md" }: { children: ReactNode; tit
function FlowStep({ icon: Icon, title, text }: { icon: LucideIcon; title: string; text: string }) {
return (
<div className="relative rounded-3xl border border-border/70 bg-background/75 p-5 shadow-sm">
<div className="mb-4 flex h-12 w-12 items-center justify-center rounded-2xl bg-primary/10 text-primary">
<div className="relative border border-white/12 bg-white/[0.03] p-5 pt-6 shadow-sm">
<PixelEdge />
<div className="mb-4 flex h-12 w-12 items-center justify-center bg-primary/10 text-primary">
<Icon className="h-6 w-6" />
</div>
<h3 className="text-2xl font-bold">{title}</h3>
@@ -105,22 +120,23 @@ export default function PresentationPage() {
return (
<SlideDeck notes={speakerNotes}>
<div className="flex min-h-[70vh] flex-col items-center justify-center text-center">
<div className="mb-8 flex items-center justify-center">
<Image
src="/logo.svg"
alt="prompts.chat logo"
width={160}
height={160}
src="/presentation/build-logo.png"
alt="Microsoft Build"
width={720}
height={405}
priority
unoptimized
className="h-40 w-40 object-contain dark:hidden"
className="mb-10 h-auto w-[20rem] md:w-[24rem]"
/>
<div className="mb-7 flex items-center justify-center">
<Image
src="/logo-dark.svg"
alt="prompts.chat logo"
width={160}
height={160}
width={112}
height={112}
unoptimized
className="hidden h-40 w-40 object-contain dark:block"
className="h-24 w-24 object-contain"
/>
</div>
<SlideTitle className="max-w-5xl">prompts.chat</SlideTitle>
@@ -131,18 +147,14 @@ export default function PresentationPage() {
Smarter models don&apos;t make prompts obsolete — prompts are the{" "}
<SlideHighlight>atoms of every agent</SlideHighlight>.
</p>
<div className="mt-10 flex flex-wrap justify-center gap-3">
<Pill>Microsoft Build</Pill>
<Pill>15-min lightning talk</Pill>
</div>
</div>
<div className="grid min-h-[70vh] items-center gap-8 lg:grid-cols-[1fr_0.95fr]">
<div className="relative order-2 lg:order-1">
<div className="absolute -left-8 top-10 h-72 w-72 rounded-full bg-primary/20 blur-3xl" />
<div className="absolute -left-8 top-10 h-72 w-72 rounded-none bg-primary/20 blur-3xl" />
<div className="relative mx-auto w-full max-w-[34rem]">
<div className="absolute -inset-4 -rotate-3 rounded-[3rem] bg-gradient-to-br from-primary/30 via-primary/10 to-transparent" />
<div className="relative overflow-hidden rounded-[3rem] border border-border bg-background shadow-2xl">
<div className="absolute -inset-4 -rotate-3 rounded-none bg-gradient-to-br from-primary/30 via-primary/10 to-transparent" />
<div className="relative overflow-hidden rounded-none border border-border bg-background shadow-2xl">
<Image
src="https://github.com/f.png"
alt="Fatih Kadir Akın profile photo"
@@ -170,18 +182,18 @@ export default function PresentationPage() {
<SlideHighlight>prompts.chat</SlideHighlight>.
</SlideContent>
<div className="mt-10 flex flex-wrap items-center gap-5">
<div className="flex items-center gap-3 rounded-2xl border border-border/70 bg-background/75 px-5 py-4 shadow-sm backdrop-blur">
<div className="flex items-center gap-3 rounded-none border border-border/70 bg-background/75 px-5 py-4 shadow-sm backdrop-blur">
<Image
src="https://cdn.simpleicons.org/automattic/000000"
src="https://cdn.simpleicons.org/automattic/FFFFFF"
alt="Automattic"
width={40}
height={40}
unoptimized
className="h-10 w-10 dark:invert"
className="h-10 w-10"
/>
<span className="text-xl font-bold text-foreground">Automattic</span>
</div>
<div className="flex items-center gap-3 rounded-2xl border border-border/70 bg-background/75 px-5 py-4 shadow-sm backdrop-blur">
<div className="flex items-center gap-3 rounded-none border border-border/70 bg-background/75 px-5 py-4 shadow-sm backdrop-blur">
<Star className="h-9 w-9 text-yellow-500" />
<span className="text-xl font-bold text-foreground">GitHub Star</span>
</div>
@@ -315,8 +327,8 @@ Output: Markdown, grouped by feature / fix / chore.`}
</div>
</div>
<div className="relative mx-auto w-full max-w-[34rem]">
<div className="absolute -inset-4 -rotate-2 rounded-[3rem] bg-gradient-to-br from-primary/30 via-primary/10 to-transparent" />
<div className="relative overflow-hidden rounded-[2rem] border border-border bg-background shadow-2xl">
<div className="absolute -inset-4 -rotate-2 rounded-none bg-gradient-to-br from-primary/30 via-primary/10 to-transparent" />
<div className="relative overflow-hidden rounded-none border border-border bg-background shadow-2xl">
<Image
src="/book-cover-photo.jpg"
alt="The Interactive Book of Prompting cover"
@@ -352,8 +364,8 @@ Output: Markdown, grouped by feature / fix / chore.`}
</div>
</div>
<div className="relative mx-auto w-full max-w-[19rem]">
<div className="absolute -inset-4 rotate-2 rounded-[3rem] bg-gradient-to-br from-primary/30 via-primary/10 to-transparent" />
<div className="relative overflow-hidden rounded-[2rem] border border-border bg-background shadow-2xl">
<div className="absolute -inset-4 rotate-2 rounded-none bg-gradient-to-br from-primary/30 via-primary/10 to-transparent" />
<div className="relative overflow-hidden rounded-none border border-border bg-background shadow-2xl">
<Image
src="/presentation/kids-screenshot.png"
alt="Promi in Prompt Land — the kids game"
@@ -382,7 +394,7 @@ Output: Markdown, grouped by feature / fix / chore.`}
</div>
<div className="flex min-h-[70vh] flex-col items-center justify-center text-center">
<div className="mb-8 flex h-24 w-24 items-center justify-center rounded-[2rem] bg-primary/10 text-primary">
<div className="mb-8 flex h-24 w-24 items-center justify-center rounded-none bg-primary/10 text-primary">
<Workflow className="h-12 w-12" />
</div>
<SlideTitle className="max-w-5xl">Prompts are the new interface</SlideTitle>
@@ -397,7 +409,7 @@ Output: Markdown, grouped by feature / fix / chore.`}
</div>
<div className="flex min-h-[70vh] flex-col items-center justify-center text-center">
<div className="mb-8 flex h-24 w-24 items-center justify-center rounded-full bg-primary/10 text-primary">
<div className="mb-8 flex h-24 w-24 items-center justify-center rounded-none bg-primary/10 text-primary">
<Rocket className="h-12 w-12" />
</div>
<SlideTitle>Thank you</SlideTitle>
+56 -16
View File
@@ -3,14 +3,30 @@
import { Children, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { ChevronLeft, ChevronRight, Maximize, Minimize, MonitorPlay, StickyNote, X } from "lucide-react";
import Link from "next/link";
import { Pixelify_Sans } from "next/font/google";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
const pixelFont = Pixelify_Sans({ subsets: ["latin"], weight: ["400", "500", "600", "700"] });
interface SlideDeckProps {
children: ReactNode;
notes?: string[];
}
const BUILD_THEME = {
fontFamily:
'"Segoe UI", "Segoe UI Semibold", "Segoe Sans Display", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif',
"--background": "#000000",
"--foreground": "#ffffff",
"--muted-foreground": "#c9c6bd",
"--muted": "#1b1b1b",
"--border": "#2a2a2a",
"--primary": "#00A4EF",
"--primary-foreground": "#ffffff",
} as React.CSSProperties;
export function SlideDeck({ children, notes }: SlideDeckProps) {
const slides = useMemo(() => Children.toArray(children), [children]);
const [currentSlide, setCurrentSlide] = useState(0);
@@ -136,7 +152,8 @@ export function SlideDeck({ children, notes }: SlideDeckProps) {
return (
<div
ref={containerRef}
className="relative flex h-[100dvh] w-screen flex-col overflow-hidden bg-background text-foreground"
className="relative flex h-[100dvh] w-screen flex-col overflow-hidden bg-black text-white"
style={BUILD_THEME}
onPointerDown={(event) => {
swipeStartX.current = event.clientX;
}}
@@ -151,11 +168,30 @@ export function SlideDeck({ children, notes }: SlideDeckProps) {
else prevSlide();
}}
>
<div className="pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_top_left,var(--primary),transparent_34%),radial-gradient(circle_at_bottom_right,var(--primary),transparent_28%)] opacity-10" />
<div className="pointer-events-none absolute inset-0 bg-[linear-gradient(to_right,var(--border)_1px,transparent_1px),linear-gradient(to_bottom,var(--border)_1px,transparent_1px)] bg-[size:72px_72px] opacity-25" />
<div className="pointer-events-none absolute inset-0 bg-[linear-gradient(to_right,#ffffff0a_1px,transparent_1px),linear-gradient(to_bottom,#ffffff0a_1px,transparent_1px)] bg-[size:48px_48px]" />
<div
className="pointer-events-none absolute inset-0 bg-cover bg-center opacity-50"
style={{ backgroundImage: "url(/presentation/build-pixels-dots.png)" }}
/>
<div
className="pointer-events-none absolute inset-0 bg-cover bg-center"
style={{ backgroundImage: "url(/presentation/build-pixels-right.png)" }}
/>
<div className="pointer-events-none absolute left-6 top-5 z-50 flex items-center gap-2.5">
<span className="grid grid-cols-2 grid-rows-2 gap-[3px]">
<span className="h-3 w-3" style={{ background: "#F25022" }} />
<span className="h-3 w-3" style={{ background: "#7FBA00" }} />
<span className="h-3 w-3" style={{ background: "#00A4EF" }} />
<span className="h-3 w-3" style={{ background: "#FFB900" }} />
</span>
<span className="text-sm font-semibold tracking-tight text-white/90">
Microsoft <span className="text-white/55">Build</span>
</span>
</div>
<div className="absolute right-4 top-4 z-50 flex items-center gap-3">
<div className="rounded-full border border-border/70 bg-background/70 px-3 py-1 text-sm font-medium text-muted-foreground shadow-sm backdrop-blur">
<div className="rounded-none border border-border/70 bg-background/70 px-3 py-1 text-sm font-medium text-muted-foreground shadow-sm backdrop-blur">
{currentSlide + 1} / {totalSlides}
</div>
{notes && (
@@ -165,7 +201,7 @@ export function SlideDeck({ children, notes }: SlideDeckProps) {
size="icon"
onClick={() => setShowNotes((value) => !value)}
className={cn(
"rounded-full border border-border/70 bg-background/70 shadow-sm backdrop-blur hover:bg-background/90",
"rounded-none border border-border/70 bg-background/70 shadow-sm backdrop-blur hover:bg-background/90",
showNotes && "text-primary"
)}
title="Speaker notes (N)"
@@ -177,7 +213,7 @@ export function SlideDeck({ children, notes }: SlideDeckProps) {
variant="ghost"
size="icon"
onClick={openPresenterView}
className="rounded-full border border-border/70 bg-background/70 shadow-sm backdrop-blur hover:bg-background/90"
className="rounded-none border border-border/70 bg-background/70 shadow-sm backdrop-blur hover:bg-background/90"
title="Open presenter notes window (P)"
>
<MonitorPlay className="h-5 w-5" />
@@ -189,7 +225,7 @@ export function SlideDeck({ children, notes }: SlideDeckProps) {
variant="ghost"
size="icon"
onClick={toggleFullscreen}
className="rounded-full border border-border/70 bg-background/70 shadow-sm backdrop-blur hover:bg-background/90"
className="rounded-none border border-border/70 bg-background/70 shadow-sm backdrop-blur hover:bg-background/90"
title="Fullscreen (F)"
>
{isFullscreen ? <Minimize className="h-5 w-5" /> : <Maximize className="h-5 w-5" />}
@@ -199,7 +235,7 @@ export function SlideDeck({ children, notes }: SlideDeckProps) {
<Button
variant="ghost"
size="icon"
className="rounded-full border border-border/70 bg-background/70 shadow-sm backdrop-blur hover:bg-background/90"
className="rounded-none border border-border/70 bg-background/70 shadow-sm backdrop-blur hover:bg-background/90"
>
<X className="h-5 w-5" />
<span className="sr-only">Close</span>
@@ -234,19 +270,19 @@ export function SlideDeck({ children, notes }: SlideDeckProps) {
size="icon"
onClick={prevSlide}
disabled={currentSlide === 0}
className="h-11 w-11 rounded-full bg-background/70 shadow-sm backdrop-blur hover:bg-background/90"
className="h-11 w-11 rounded-none bg-background/70 shadow-sm backdrop-blur hover:bg-background/90"
>
<ChevronLeft className="h-5 w-5" />
<span className="sr-only">Previous</span>
</Button>
<div className="flex max-w-[58vw] items-center gap-1.5 overflow-hidden rounded-full border border-border/60 bg-background/60 px-3 py-2 shadow-sm backdrop-blur">
<div className="flex max-w-[58vw] items-center gap-1.5 overflow-hidden rounded-none border border-border/60 bg-background/60 px-3 py-2 shadow-sm backdrop-blur">
{slides.map((_, index) => (
<button
key={index}
onClick={() => setCurrentSlide(index)}
className={cn(
"h-2.5 rounded-full transition-all duration-300",
"h-2.5 rounded-none transition-all duration-300",
index === currentSlide ? "w-8 bg-primary" : "w-2.5 bg-muted-foreground/30 hover:bg-muted-foreground/50"
)}
aria-label={`Go to slide ${index + 1}`}
@@ -259,7 +295,7 @@ export function SlideDeck({ children, notes }: SlideDeckProps) {
size="icon"
onClick={nextSlide}
disabled={currentSlide === totalSlides - 1}
className="h-11 w-11 rounded-full bg-background/70 shadow-sm backdrop-blur hover:bg-background/90"
className="h-11 w-11 rounded-none bg-background/70 shadow-sm backdrop-blur hover:bg-background/90"
>
<ChevronRight className="h-5 w-5" />
<span className="sr-only">Next</span>
@@ -267,7 +303,7 @@ export function SlideDeck({ children, notes }: SlideDeckProps) {
</div>
{showNotes && (
<div className="absolute inset-x-4 bottom-24 z-50 mx-auto max-w-3xl rounded-2xl border border-border bg-background/95 p-4 shadow-2xl backdrop-blur">
<div className="absolute inset-x-4 bottom-24 z-50 mx-auto max-w-3xl border border-border bg-background/95 p-4 shadow-2xl backdrop-blur">
<div className="mb-1 text-xs font-bold uppercase tracking-[0.24em] text-primary">Speaker note</div>
<p className="text-sm leading-relaxed text-foreground">{currentNote || "No note for this slide."}</p>
</div>
@@ -275,8 +311,11 @@ export function SlideDeck({ children, notes }: SlideDeckProps) {
<div className="absolute inset-x-0 bottom-0 h-1.5 bg-muted">
<div
className="h-full bg-primary transition-all duration-500 ease-out"
style={{ width: `${((currentSlide + 1) / totalSlides) * 100}%` }}
className="h-full transition-all duration-500 ease-out"
style={{
width: `${((currentSlide + 1) / totalSlides) * 100}%`,
backgroundImage: "linear-gradient(to right, #F25022, #FFB900, #7FBA00, #00A4EF)",
}}
/>
</div>
</div>
@@ -287,7 +326,8 @@ export function SlideTitle({ children, className }: { children: ReactNode; class
return (
<h1
className={cn(
"mb-7 text-balance bg-gradient-to-br from-foreground to-foreground/65 bg-clip-text text-4xl font-bold leading-tight tracking-tight text-transparent md:text-6xl lg:text-7xl",
pixelFont.className,
"mb-7 text-balance text-4xl font-bold leading-[1.05] text-white md:text-5xl lg:text-6xl",
className
)}
>