import { createSignal, createEffect, onMount, onCleanup } from "solid-js" import { Dialog } from "@opencode-ai/ui/dialog" import { Button } from "@opencode-ai/ui/button" import { useDialog } from "@opencode-ai/ui/context/dialog" import { useSettings } from "@/context/settings" export type Highlight = { title: string description: string media?: { type: "image" | "video" src: string alt?: string } } export function DialogReleaseNotes(props: { highlights: Highlight[] }) { const dialog = useDialog() const settings = useSettings() const [index, setIndex] = createSignal(0) const total = () => props.highlights.length const last = () => Math.max(0, total() - 1) const feature = () => props.highlights[index()] ?? props.highlights[last()] const isFirst = () => index() === 0 const isLast = () => index() >= last() const paged = () => total() > 1 function handleNext() { if (isLast()) return setIndex(index() + 1) } function handleClose() { dialog.close() } function handleDisable() { settings.general.setReleaseNotes(false) handleClose() } let focusTrap: HTMLDivElement | undefined function handleKeyDown(e: KeyboardEvent) { if (e.key === "Escape") { e.preventDefault() handleClose() return } if (!paged()) return if (e.key === "ArrowLeft" && !isFirst()) { e.preventDefault() setIndex(index() - 1) } if (e.key === "ArrowRight" && !isLast()) { e.preventDefault() setIndex(index() + 1) } } onMount(() => { focusTrap?.focus() document.addEventListener("keydown", handleKeyDown) onCleanup(() => document.removeEventListener("keydown", handleKeyDown)) }) // Refocus the trap when index changes to ensure escape always works createEffect(() => { index() // track index focusTrap?.focus() }) return ( {/* Hidden element to capture initial focus and handle escape */}
{/* Left side - Text content */}
{/* Top section - feature content (fixed position from top) */}

{feature()?.title ?? ""}

{feature()?.description ?? ""}

{/* Spacer to push buttons to bottom */}
{/* Bottom section - buttons and indicators (fixed position) */}
{isLast() ? ( ) : ( )}
{paged() && (
{props.highlights.map((_, i) => ( ))}
)}
{/* Right side - Media content (edge to edge) */} {feature()?.media && (
{feature()!.media!.type === "image" ? ( {feature()!.media!.alt ) : (
)}
) }