fix: align route priority drag preview (#375)
This commit is contained in:
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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)',
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user