{
const target = keyframeTarget(kf, groupAware);
+ const focusId = timelineKeyframeFocusId(elementId, target);
const kfKey = timelineKeyframeSelectionKey(elementId, target);
// While dragging this diamond, render it at the live preview clip-%.
const renderPct = preview?.kfKey === kfKey ? preview.clipPct : kf.percentage;
@@ -297,7 +325,8 @@ export const TimelineDiamondLane = memo(function TimelineDiamondLane({
// content origin is inset past the label column, Figma-style) so it stays
// fully visible instead of being clipped by the sticky label column.
const marker = markerMetrics[i]!;
- const leftPx = (renderPct / 100) * clipWidthPx - marker.hitWidth / 2;
+ const boundary = kf.percentage < 0 ? "before" : kf.percentage > 100 ? "after" : null;
+ const leftPx = keyframeCenterX(kf, renderPct) - marker.hitWidth / 2;
const isKfSelected = selectedKeyframes.has(kfKey);
const atPlayhead = isSelected && Math.abs(kf.percentage - currentPercentage) < 0.5;
const isHighlighted = isKfSelected || atPlayhead;
@@ -350,10 +379,15 @@ export const TimelineDiamondLane = memo(function TimelineDiamondLane({
key={`${i}-${kf.percentage}`}
type="button"
className="absolute"
+ data-timeline-focus-id={focusId}
data-keyframe-group={groupAware ? kf.propertyGroup : undefined}
data-keyframe-percentage={
groupAware ? (kf.tweenPercentage ?? kf.percentage) : undefined
}
+ data-keyframe-outside-clip={boundary ?? undefined}
+ tabIndex={focusId === rovingTargetId ? 0 : -1}
+ aria-label={`${kf.propertyGroup ?? "Motion"} keyframe at ${keyframeTimeLabel(clipStart, clipDuration, kf.percentage)}${boundary ? ` (${boundary} clip)` : ""}`}
+ aria-pressed={isKfSelected}
style={{
left: leftPx,
top: centerY,
@@ -375,6 +409,13 @@ export const TimelineDiamondLane = memo(function TimelineDiamondLane({
onPointerDown={onPointerDown}
onPointerMove={canDrag ? (e) => retimeHandleRef.current?.update(e) : undefined}
onPointerUp={onPointerUp}
+ onClick={(e) => {
+ if (e.detail !== 0) return;
+ e.stopPropagation();
+ suppressNextClick();
+ if (e.shiftKey) onShiftClickKeyframe?.(target);
+ else onClickKeyframe?.(target);
+ }}
onPointerCancel={
canDrag
? (e) => {
@@ -388,7 +429,7 @@ export const TimelineDiamondLane = memo(function TimelineDiamondLane({
e.stopPropagation();
onContextMenuKeyframe?.(e, target);
}}
- title={`${kf.percentage}%`}
+ title={`${kf.percentage}%${boundary ? ` · ${boundary} clip` : ""}`}
>