This commit is contained in:
Andrés Villagrán 2026-05-19 10:40:55 +07:00 committed by GitHub
commit 26711664a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 103 additions and 4 deletions

View File

@ -0,0 +1,64 @@
import { describe, expect, test } from "bun:test";
import {
getTimelineElementClassName,
getTimelineElementClassNameForElement,
TIMELINE_ELEMENT_THEME,
TIMELINE_TRACK_THEME,
} from "../theme";
describe("getTimelineElementClassName", () => {
test("returns the configured class for each track type", () => {
expect(getTimelineElementClassName({ type: "audio" })).toBe(
TIMELINE_TRACK_THEME.audio.elementClassName.trim(),
);
expect(getTimelineElementClassName({ type: "text" })).toBe(
TIMELINE_TRACK_THEME.text.elementClassName.trim(),
);
});
});
describe("getTimelineElementClassNameForElement", () => {
test("uses the element-level theme when one is defined", () => {
expect(
getTimelineElementClassNameForElement({
elementType: "video",
trackType: "video",
}),
).toBe(TIMELINE_ELEMENT_THEME.video?.elementClassName.trim());
});
test("distinguishes video and image even though they share the video track", () => {
const videoClass = getTimelineElementClassNameForElement({
elementType: "video",
trackType: "video",
});
const imageClass = getTimelineElementClassNameForElement({
elementType: "image",
trackType: "video",
});
expect(videoClass).not.toBe(imageClass);
});
test("falls back to the track-level theme when an element type has no override", () => {
expect(
getTimelineElementClassNameForElement({
elementType: "audio",
trackType: "audio",
}),
).toBe(TIMELINE_TRACK_THEME.audio.elementClassName.trim());
expect(
getTimelineElementClassNameForElement({
elementType: "text",
trackType: "text",
}),
).toBe(TIMELINE_TRACK_THEME.text.elementClassName.trim());
expect(
getTimelineElementClassNameForElement({
elementType: "sticker",
trackType: "graphic",
}),
).toBe(TIMELINE_TRACK_THEME.graphic.elementClassName.trim());
});
});

View File

@ -1,4 +1,4 @@
import type { TrackType } from "@/timeline";
import type { ElementType, TrackType } from "@/timeline";
export const TIMELINE_AUDIO_WAVEFORM_COLOR = "rgba(255, 255, 255, 0.7)";
@ -19,6 +19,22 @@ export const TIMELINE_TRACK_THEME: Record<
effect: { elementClassName: "bg-[#5d93ba]" },
} as const;
/**
* Per-element-type background tint applied to clips on the timeline.
*
* Falls back to the track-level theme when an element type has no
* dedicated entry. Used so that clips on the same track (e.g. video
* and image, which both live on the "video" track) can still be
* visually distinguished from each other and from the timeline
* background.
*/
export const TIMELINE_ELEMENT_THEME: Partial<
Record<ElementType, { elementClassName: string }>
> = {
video: { elementClassName: "bg-sky-500/20" },
image: { elementClassName: "bg-amber-500/20" },
} as const;
export const SELECTED_TRACK_ROW_CLASS = "bg-accent/50";
export const DEFAULT_TIMELINE_BOOKMARK_COLOR = "#009dff";
@ -29,3 +45,17 @@ export function getTimelineElementClassName({
}): string {
return TIMELINE_TRACK_THEME[type].elementClassName.trim();
}
export function getTimelineElementClassNameForElement({
elementType,
trackType,
}: {
elementType: ElementType;
trackType: TrackType;
}): string {
const elementTheme = TIMELINE_ELEMENT_THEME[elementType];
if (elementTheme) {
return elementTheme.elementClassName.trim();
}
return TIMELINE_TRACK_THEME[trackType].elementClassName.trim();
}

View File

@ -23,7 +23,11 @@ import {
timelineTimeToSnappedPixels,
} from "@/timeline";
import { getTrackHeight } from "./track-layout";
import { getTimelineElementClassName, TIMELINE_TRACK_THEME } from "./theme";
import {
getTimelineElementClassName,
getTimelineElementClassNameForElement,
TIMELINE_TRACK_THEME,
} from "./theme";
import {
ContextMenu,
ContextMenuContent,
@ -585,8 +589,9 @@ function ElementInner({
<div
className={cn(
"flex shrink-0 items-center overflow-hidden",
getTimelineElementClassName({
type: getTrackTypeForElementType({
getTimelineElementClassNameForElement({
elementType: element.type,
trackType: getTrackTypeForElementType({
elementType: element.type,
}),
}),