The drag replicas cast the shadow the pickup lift already promised
DragReplicaStyle spells the pathfinder's constant ambient shadow once (black 16%, radius 2.5, y 1.5) and all three replica faces — card, lane, trashed lane — wear it via one modifier; the ghost fans compose from the same faces so every copy inherits it, dimmed by its own opacity. 03 § Motion's "pickup lift (scale + shadow)" supplies the scale from the system session but no shadow on the preview image — the replica is the only place it can come from. BoardMetrics.replicaPadding was already written to keep exactly this shadow from clipping and was simply unused until now. Drag-perf card 24397310. Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
This commit is contained in:
@@ -512,6 +512,7 @@ struct CardFaceView: View, Equatable {
|
|||||||
)
|
)
|
||||||
.background(RoundedRectangle(cornerRadius: cornerRadius).fill(.background.secondary))
|
.background(RoundedRectangle(cornerRadius: cornerRadius).fill(.background.secondary))
|
||||||
.overlay(alignment: .leading) { accentStripe }
|
.overlay(alignment: .leading) { accentStripe }
|
||||||
|
.dragReplicaShadow()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Context menus
|
// MARK: - Context menus
|
||||||
|
|||||||
@@ -78,3 +78,23 @@ struct DragCountBadge: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The pickup lift's shadow figures — 03-board-ui.md § Motion's "the pickup lift (scale + shadow as
|
||||||
|
/// it detaches from the card)": the system drag session supplies the scale and the tracking, but
|
||||||
|
/// paints no shadow onto its preview image, so the shadow can only come from the replica view
|
||||||
|
/// itself. Values are the pathfinder's own constant ambient shadow, reused verbatim rather than
|
||||||
|
/// re-derived (`~/Documents/indie/Kanban` CardView.swift:623) — its drags read subtly raised, and
|
||||||
|
/// that read is the point.
|
||||||
|
enum DragReplicaStyle {
|
||||||
|
static let shadowColor = Color.black.opacity(0.16)
|
||||||
|
static let shadowRadius: CGFloat = 2.5
|
||||||
|
static let shadowY: CGFloat = 1.5
|
||||||
|
}
|
||||||
|
|
||||||
|
extension View {
|
||||||
|
/// The pickup lift's shadow (`DragReplicaStyle`), for a drag replica's face — shared by the
|
||||||
|
/// card, lane, and trashed-lane replicas so the figures are spelled once.
|
||||||
|
func dragReplicaShadow() -> some View {
|
||||||
|
shadow(color: DragReplicaStyle.shadowColor, radius: DragReplicaStyle.shadowRadius, y: DragReplicaStyle.shadowY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -650,6 +650,7 @@ struct LaneView: View, Equatable {
|
|||||||
.frame(width: replicaWidth, height: replicaHeight, alignment: .topLeading)
|
.frame(width: replicaWidth, height: replicaHeight, alignment: .topLeading)
|
||||||
.background(RoundedRectangle(cornerRadius: cornerRadius).fill(.background))
|
.background(RoundedRectangle(cornerRadius: cornerRadius).fill(.background))
|
||||||
.clipShape(RoundedRectangle(cornerRadius: cornerRadius))
|
.clipShape(RoundedRectangle(cornerRadius: cornerRadius))
|
||||||
|
.dragReplicaShadow()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The replica's size — **the lane's own**, floored for a lane that has not measured itself yet
|
/// The replica's size — **the lane's own**, floored for a lane that has not measured itself yet
|
||||||
|
|||||||
@@ -279,6 +279,7 @@ struct TrashLaneRowView: View {
|
|||||||
alignment: .leading
|
alignment: .leading
|
||||||
)
|
)
|
||||||
.background(RoundedRectangle(cornerRadius: cornerRadius).fill(.background.tertiary))
|
.background(RoundedRectangle(cornerRadius: cornerRadius).fill(.background.tertiary))
|
||||||
|
.dragReplicaShadow()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - The row's two rows of menu
|
// MARK: - The row's two rows of menu
|
||||||
|
|||||||
Reference in New Issue
Block a user