Files
buzz/desktop/src/shared/ui/VideoReviewTimecodeButton.tsx
T
17d2147eca Fix video comment effect wrapping (#5748)
## What changed

- render video-review timecode chips inside the first Markdown paragraph
so comment text wraps naturally around them
- reuse the canonical video-review chip treatment across the timeline,
Inbox previews, and Inbox detail
- preserve video-review context in Inbox so timestamp chips remain
interactive

## Why

Video comments now support Markdown-like effects, but non-player
surfaces rendered the timestamp beside a separate text layout. That kept
the chip and comment from sharing the same inline flow and made Inbox
behavior inconsistent with the player.

## Validation

- `pnpm --dir desktop check`
- 100 focused Markdown, timecode, video-review, and Inbox unit tests
- `pnpm --dir desktop build:e2e`
- focused `video-attachment.spec.ts` Playwright scenario
- pre-push desktop typecheck and 4,761-test desktop suite
- native Builderlab staging with the configured profile

Focused timeline and Inbox snapshots will be attached in a PR comment.

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz>
Co-authored-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz>
2026-08-14 17:16:28 +01:00

79 lines
2.1 KiB
TypeScript

import type * as React from "react";
import { cn } from "@/shared/lib/cn";
const TIMECODE_ACCENT_CLASS =
"bg-[hsl(var(--buzz-video-review-accent,var(--primary))/0.15)] text-[hsl(var(--buzz-video-review-accent-foreground,var(--buzz-video-review-accent,var(--primary))))]";
const TIMECODE_ACCENT_HOVER_CLASS =
"hover:bg-[hsl(var(--buzz-video-review-accent,var(--primary))/0.3)]";
const MESSAGE_TIMECODE_ACCENT_CLASS =
"bg-primary/15 text-primary hover:bg-primary/30";
function timecodeClasses({
className,
interactive,
surface,
}: {
className?: string;
interactive: boolean;
surface: "message" | "review";
}) {
return cn(
"inline-flex h-5 shrink-0 items-center rounded px-1.5 align-middle font-mono text-2xs font-semibold",
interactive &&
"outline-hidden transition-colors focus-visible:ring-2 focus-visible:ring-white/60",
surface === "review"
? [TIMECODE_ACCENT_CLASS, interactive && TIMECODE_ACCENT_HOVER_CLASS]
: interactive
? MESSAGE_TIMECODE_ACCENT_CLASS
: "bg-primary/15 text-primary",
className,
);
}
export function VideoReviewTimecodeButton({
className,
onClick,
surface = "review",
timecode,
}: {
className?: string;
onClick: React.MouseEventHandler<HTMLButtonElement>;
surface?: "message" | "review";
timecode: string;
}) {
return (
<button
aria-label={`Jump to ${timecode}`}
className={timecodeClasses({ className, interactive: true, surface })}
data-testid="video-review-comment-timecode"
type="button"
onClick={onClick}
>
{timecode}
</button>
);
}
/** Renders a non-interactive timecode with the same visual treatment. */
export function VideoReviewTimecodeChip({
className,
surface = "review",
timecode,
}: {
className?: string;
surface?: "message" | "review";
timecode: string;
}) {
return (
<span
className={timecodeClasses({ className, interactive: false, surface })}
data-testid="video-review-comment-timecode"
>
{timecode}
</span>
);
}
export const VIDEO_REVIEW_TIMECODE_ACCENT_CLASS = TIMECODE_ACCENT_CLASS;