feat(presentation): align lightning talk with Build theme
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
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 |
@@ -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'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>
|
||||
|
||||
@@ -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
|
||||
)}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user