Add the loss-row banner class and retone degraded paste

02 ratified a warning-tone class for non-failure losses — content that
didn't arrive though nothing failed: a degraded paste, folders skipped
from a Finder drop, their future kin. Loss rows take the one-shot's
dismissable-untimed lifecycle (a loss the user didn't notice is the
harm) and rank below the true failures, above commit and attachment
notices. BannerCenter grows LossBanner, postLoss, and the
skipped-folders phrasing; the degraded-paste notice moves off its
signpost onto the new class, ending its too-quiet ranking.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
2026-07-28 07:17:27 -04:00
parent 15006ad233
commit 756e936291
6 changed files with 312 additions and 46 deletions
+14
View File
@@ -245,6 +245,7 @@ private func previewError(
.inProgress(InProgressOperation(label: "Pulling…")),
.readOnlyLock(.vanishedRoot),
.oneShot(OneShotBanner(error: previewError(.delete(title: "Ship the beta")))),
.loss(LossBanner(message: "Pasted 'Fix login' without its 3 attachments")),
.historySuspended(HistorySuspension(reason: "the repository is corrupt")),
.signpost(InfoSignpost(message: "This card changed on the remote — your edits still win")),
],
@@ -253,6 +254,19 @@ private func previewError(
.frame(width: 520)
}
/// A loss row on its own: warning tone, but unlike the standing `historySuspended` condition
/// beside it in "Stacked tones" dismissable, since a loss reports something that already
/// happened rather than an ongoing state (settled 2026-07-28, BannerCenter's `LossBanner`).
#Preview("Loss row") {
BannerStripView(
rows: [
.loss(LossBanner(message: BannerCenter.skippedFoldersMessage(count: 2))),
],
onDismiss: { _ in }
)
.frame(width: 520)
}
/// Seven rows, one of them pinned: the strip shows the spinner plus the first three of the rest,
/// and "+3 more" counts only what actually collapsed.
#Preview("Collapse") {