mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-08-29 05:05:38 -04:00
- Add global MotionConfig reducedMotion="user" in root layout
- Add color-scheme: dark, theme-color meta, skip-to-main-content link
- Add aria-hidden={true} to ~60+ decorative icons across 33 files
- Add aria-label to all icon-only buttons (logout, star rating, play, delete, etc.)
- Replace transition-all with specific properties (11 files)
- Add motion-safe: prefix for CSS hover transforms and animate-pulse
- Add prefers-reduced-motion: reduce override in globals.css
- Add useReducedMotion guard to status-dot pulsing animation
- Fix focus-visible styles on auth form inputs (focus → focus-visible, stronger ring)
- Add text-balance to all headings (13 files)
- Replace "..." with "…" (U+2026) in all loading/placeholder text
- Add autocomplete, spellCheck, role="alert" to auth form
- Add aria-label to Switch controls and filmography select
- Fix heading hierarchy (h3 → h2 where h2 was skipped)
- Add break-words to title overview, overscroll-contain to drawer
- Add confirmation dialog for destructive library removal
- Add group-focus-within:opacity-100 for keyboard-accessible backup actions
- Add role="radio" + aria-checked to star rating buttons
- Add aria-label to carousel region, role="img" to TMDB logo SVG
- Add text-foreground to native select for dark mode consistency
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
68 lines
2.2 KiB
TypeScript
68 lines
2.2 KiB
TypeScript
"use client";
|
|
|
|
import { IconPlayerPlayFilled } from "@tabler/icons-react";
|
|
import dynamic from "next/dynamic";
|
|
import { useState } from "react";
|
|
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
|
|
|
const YoutubeVideo = dynamic(() => import("youtube-video-element/react"), {
|
|
ssr: false,
|
|
});
|
|
const MediaThemeSutro = dynamic(() => import("@player.style/sutro/react"), {
|
|
ssr: false,
|
|
});
|
|
|
|
export function TrailerDialog({
|
|
videoKey,
|
|
variant = "badge",
|
|
}: {
|
|
videoKey: string;
|
|
variant?: "badge" | "backdrop";
|
|
}) {
|
|
const [open, setOpen] = useState(false);
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={setOpen}>
|
|
{variant === "backdrop" ? (
|
|
<button
|
|
type="button"
|
|
aria-label="Play trailer"
|
|
onClick={() => setOpen(true)}
|
|
className="group flex size-12 items-center justify-center rounded-full bg-white/10 ring-1 ring-white/20 backdrop-blur-md transition-[transform,background-color,box-shadow] duration-300 hover:scale-105 hover:bg-white/20 hover:ring-white/30 active:scale-100 sm:size-16"
|
|
>
|
|
<IconPlayerPlayFilled className="size-6 text-white drop-shadow-lg sm:size-8" />
|
|
</button>
|
|
) : (
|
|
<button
|
|
type="button"
|
|
onClick={() => setOpen(true)}
|
|
className="inline-flex h-5 items-center gap-1 rounded border border-border/50 px-2 text-xs text-muted-foreground transition-colors hover:border-border hover:text-foreground"
|
|
>
|
|
<IconPlayerPlayFilled aria-hidden={true} className="h-2.5 w-2.5" />
|
|
Trailer
|
|
</button>
|
|
)}
|
|
<DialogContent className="sm:max-w-4xl p-0 overflow-hidden bg-black border-white/10">
|
|
<DialogTitle className="sr-only">Trailer</DialogTitle>
|
|
<div className="aspect-video w-full">
|
|
<MediaThemeSutro
|
|
style={
|
|
{
|
|
width: "100%",
|
|
height: "100%",
|
|
} as React.CSSProperties
|
|
}
|
|
>
|
|
<YoutubeVideo
|
|
slot="media"
|
|
src={`https://www.youtube-nocookie.com/watch?v=${videoKey}`}
|
|
playsInline
|
|
crossOrigin="anonymous"
|
|
/>
|
|
</MediaThemeSutro>
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
}
|