fix: align route priority drag preview (#375)

This commit is contained in:
Cita
2026-04-01 19:43:00 +08:00
committed by GitHub
parent 37a86d1380
commit ce77bde95a
5 changed files with 47 additions and 4 deletions
@@ -213,5 +213,20 @@ describe('RouteCard', () => {
expect(text).toContain('P1 · 1');
expect(text).toContain('user_a');
expect(text).toContain('user_b');
const p0RailNode = root.root.find((node) => (
node.type === 'div'
&& collectText(node) === 'P0 · 1'
&& node.props?.style?.borderRadius === 999
));
const p1RailNode = root.root.find((node) => (
node.type === 'div'
&& collectText(node) === 'P1 · 1'
&& node.props?.style?.borderRadius === 999
));
expect(p0RailNode.props.style.background).not.toBe('var(--color-bg)');
expect(p1RailNode.props.style.background).not.toBe('var(--color-bg)');
expect(p0RailNode.props.style.color).not.toBe(p1RailNode.props.style.color);
});
});
+14 -3
View File
@@ -42,11 +42,13 @@ import {
isExplicitGroupRoute,
resolveRouteTitle,
resolveRouteIcon,
getPriorityTagStyle,
} from './utils.js';
import {
buildPriorityBuckets,
} from './priorityBuckets.js';
import {
buildPriorityDragPreviewStyle,
buildPriorityRailSections,
createPriorityRailNewLayerId,
isPriorityRailNewLayerId,
@@ -160,15 +162,18 @@ function PriorityRailNewLayerRow({
function PriorityDragPreview({
channel,
displayPriority,
activeRowWidth,
}: {
channel: RouteChannel;
displayPriority: number;
activeRowWidth?: number | null;
}) {
return (
<div
style={{
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'space-between',
gap: 8,
padding: '8px 12px',
borderRadius: 'var(--radius-md)',
@@ -177,6 +182,7 @@ function PriorityDragPreview({
boxShadow: 'var(--shadow-sm)',
color: 'var(--color-text-primary)',
fontSize: 12,
...buildPriorityDragPreviewStyle(activeRowWidth),
}}
>
<span
@@ -275,6 +281,7 @@ function RouteCardInner({
const priorityBuckets = buildPriorityBuckets(channels || []);
const priorityRailSections = buildPriorityRailSections(channels || []);
const [activeDragChannelId, setActiveDragChannelId] = useState<number | null>(null);
const [activeDragRowWidth, setActiveDragRowWidth] = useState<number | null>(null);
const [dragOverId, setDragOverId] = useState<string | number | null>(null);
const activeDragChannel = activeDragChannelId == null
? null
@@ -291,12 +298,14 @@ function RouteCardInner({
const clearDragState = () => {
setActiveDragChannelId(null);
setActiveDragRowWidth(null);
setDragOverId(null);
};
const handleDragStart = (event: DragStartEvent) => {
const nextId = Number(event.active.id);
setActiveDragChannelId(Number.isFinite(nextId) ? nextId : null);
setActiveDragRowWidth(event.active.rect.current.initial?.width ?? null);
setDragOverId(event.active.id);
};
@@ -670,6 +679,7 @@ function RouteCardInner({
const hoveredExistingLayer = activeDragChannelId != null && hoveredBucketIndex === bucketIndex;
const hoveredCrossLayer = hoveredExistingLayer && activeDragBucketIndex !== bucketIndex;
const hoveredNewLayer = activeDragChannelId != null && hoveredNewLayerBucketIndex === bucketIndex;
const railTone = getPriorityTagStyle(bucketIndex);
return (
<div
@@ -729,11 +739,11 @@ function RouteCardInner({
minWidth: 72,
padding: '6px 10px',
borderRadius: 999,
border: `1px solid ${hoveredExistingLayer ? 'var(--color-primary)' : 'var(--color-border)'}`,
border: `1px solid ${hoveredExistingLayer ? 'var(--color-primary)' : 'color-mix(in srgb, currentColor 24%, transparent)'}`,
background: hoveredExistingLayer
? 'color-mix(in srgb, var(--color-primary) 10%, var(--color-bg))'
: 'var(--color-bg)',
color: hoveredExistingLayer ? 'var(--color-primary)' : 'var(--color-text-secondary)',
: railTone.background,
color: hoveredExistingLayer ? 'var(--color-primary)' : railTone.color,
fontSize: 11,
fontWeight: 600,
textAlign: 'center',
@@ -801,6 +811,7 @@ function RouteCardInner({
<PriorityDragPreview
channel={activeDragChannel}
displayPriority={Math.max(0, activeDragBucketIndex)}
activeRowWidth={activeDragRowWidth}
/>
) : null}
</DragOverlay>
@@ -50,7 +50,7 @@ export function SortableChannelRow({
const rowStyle: CSSProperties = {
transform: CSS.Transform.toString(transform),
transition,
opacity: isDragging ? 0.72 : channel.enabled === false ? 0.5 : 1,
opacity: isDragging ? (mobile ? 0.72 : 0) : channel.enabled === false ? 0.5 : 1,
zIndex: isDragging ? 10 : 1,
display: 'grid',
gridTemplateColumns: managementLocked || mobile ? 'minmax(0, 1fr)' : 'minmax(0, 1fr) auto auto auto',
@@ -1,6 +1,7 @@
import { describe, expect, it } from 'vitest';
import {
applyPriorityRailDrop,
buildPriorityDragPreviewStyle,
buildPriorityRailDragTargets,
buildPriorityRailSections,
createPriorityRailNewLayerId,
@@ -74,4 +75,11 @@ describe('priorityRail helpers', () => {
{ id: 21, priority: 2 },
]);
});
it('uses the active row width for drag preview alignment when available', () => {
expect(buildPriorityDragPreviewStyle(640)).toMatchObject({
width: 640,
maxWidth: 'calc(100vw - 32px)',
});
});
});
@@ -1,3 +1,4 @@
import type { CSSProperties } from 'react';
import type { PriorityRailDragTarget, PriorityRailSection } from './types.js';
type PriorityRailChannelLike = {
@@ -117,3 +118,11 @@ export function applyPriorityRailDrop<T extends PriorityRailChannelLike>(
)),
);
}
export function buildPriorityDragPreviewStyle(activeRowWidth?: number | null): CSSProperties {
const resolvedWidth = Number.isFinite(activeRowWidth ?? Number.NaN) ? activeRowWidth ?? undefined : undefined;
return {
width: resolvedWidth,
maxWidth: 'calc(100vw - 32px)',
};
}