From 19156814b8f2503eaf014fcfd546e579084acd4f Mon Sep 17 00:00:00 2001 From: Mix Date: Mon, 12 Oct 2026 00:12:04 +0300 Subject: [PATCH] design: in-log, Why is a sheet over the page; no Deny on a Postfix reject MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Owner, 2026-10-11/12, on the Inbound log as built: - "Why сделать не столбцом, а листом поверх." Opened by the decision tag ("Тег."), drawn first, then: its content as a table ("В лист может быть таблицей?" - "Да. Но хорошо бы ещё её отцентрировать."), with a narrow column of names and only what the row does not show. - "Почему Deny у того, кто rejected?" - "Убирай": a message Postfix itself refused offers no Deny sender. Accepted mail offers Deny, mail the filter refused offers Allow. A new component, sheet (theme.css, shown on the components page next to status_tag): the browser's own popover, so no script - the tag is a button with popovertarget; Esc, a click outside and the cross close it. It rises from the bottom edge across the window; its content is a table of name and value in a 44rem column in the middle. A tag that opens a sheet carries a dotted underline to tell it from a plain tag. in-log: the Why column is gone and rows are one height. A sheet holds who decided, the verdict and the symbols (or the reply), and the subject whole. Guard: check.py WIDTH_OK gains ".sp-sheet" - the one component laid out by the window and not by the page. The owner accepted the drawing with that said. check.py: 32 screens, 52 sp- classes, 0 violations; outlines.json unchanged. Co-Authored-By: Claude Opus 5.5 --- docs/assets/panel-redesign/panel/check.py | 2 +- .../panel-redesign/panel/components.html | 1 + docs/assets/panel-redesign/panel/in-log.html | 16 ++++++------- .../panel-redesign/panel/src/components.html | 1 + .../panel-redesign/panel/src/in-log.html | 16 ++++++------- docs/assets/panel-redesign/panel/theme.css | 24 +++++++++++++++++++ 6 files changed, 43 insertions(+), 17 deletions(-) diff --git a/docs/assets/panel-redesign/panel/check.py b/docs/assets/panel-redesign/panel/check.py index 9474f16..4a693de 100644 --- a/docs/assets/panel-redesign/panel/check.py +++ b/docs/assets/panel-redesign/panel/check.py @@ -37,7 +37,7 @@ SIGNED_OUT = {"sp-signin", "sp-signin-brand", "sp-signin-form", "sp-foot"} # Selectors allowed to set a width. Everything else gets its width from the # layout it sits in — that is the whole point of the redesign. WIDTH_OK = (".navbar-brand img", ".sp-head .sp-lead", ".sp-head .sp-grow", ".sp-postmark", ".table td.sp-clip", - ".sp-h-icon", ".sp-signin", ".sp-timeline li::before", ".sp-perf") + ".sp-h-icon", ".sp-signin", ".sp-timeline li::before", ".sp-perf", ".sp-sheet") class Node: diff --git a/docs/assets/panel-redesign/panel/components.html b/docs/assets/panel-redesign/panel/components.html index 702e20e..7bb1c87 100644 --- a/docs/assets/panel-redesign/panel/components.html +++ b/docs/assets/panel-redesign/panel/components.html @@ -114,6 +114,7 @@ error, fail, mismatch, bouncedfailtag is-danger is-light unknown, off, neutral countsofftag is-light held: quarantine · role: globalquarantinetag is-primary is-light + a tag that opens a sheet
reject

sheet

What it holds
What does not fit the row, as facts
How it closes
Esc, a click outside, or the cross
button.tag + sp-sheet (popover) diff --git a/docs/assets/panel-redesign/panel/in-log.html b/docs/assets/panel-redesign/panel/in-log.html index 2e1ac02..49aabef 100644 --- a/docs/assets/panel-redesign/panel/in-log.html +++ b/docs/assets/panel-redesign/panel/in-log.html @@ -86,17 +86,17 @@
- + - - - - - - + + + + + +
Time, UTCFromToSubjectDecisionWhy
Time, UTCFromToSubjectDecision
09-21 14:00:18t.berg@uni.example
192.0.2.77
dev@lists.example.orgRe: [dev] patch series v3acceptrspamd · no action, score 0.40 / 15.00Deny sender
09-21 13:59:02invoice@partner-billing.example
203.0.113.140
owner@lists.example.orgOutstanding invoice — action requiredacceptrspamd · add header, score 9.80 / 15.00; PHISHING(5.00) FORGED_SENDER(3.00) R_SPF_FAIL(1.00)Deny sender
09-21 13:57:41promo@bulk.example
198.51.100.90
sales@lists.example.org—rejectpostfix · 550 5.1.1 <sales@lists.example.org>: Recipient address rejected: User unknown in relay recipient tableDeny sender
09-21 13:51:30billing@partner.example
198.51.100.12
owner@lists.example.org—rejectrspamd · 5.7.1 Spam message rejectedAllow sender
09-21 13:44:02hr@partner.example
192.0.2.31
jobs@acme.io—tempfailrspamd · 4.7.1 Try again laterAllow sender
09-21 13:30:55noreply@github.example
192.0.2.200
security@lists.example.org[advisory] new reportacceptrspamd · no action, score -98.10 / 15.00; SELFPOST_ALLOW_FROM(-100.00) R_DKIM_ALLOW(-0.20)Deny sender
09-21 14:00:18t.berg@uni.example
192.0.2.77
dev@lists.example.orgRe: [dev] patch series v3
accept

Why

Decided byrspamd
Verdictno action, score 0.40 / 15.00
SubjectRe: [dev] patch series v3
Deny sender
09-21 13:59:02invoice@partner-billing.example
203.0.113.140
owner@lists.example.orgOutstanding invoice — action required
accept

Why

Decided byrspamd
Verdictadd header, score 9.80 / 15.00
SymbolsPHISHING(5.00)
FORGED_SENDER(3.00)
R_SPF_FAIL(1.00)
SubjectOutstanding invoice — action required
Deny sender
09-21 13:57:41promo@bulk.example
198.51.100.90
sales@lists.example.org—
reject

Why

Decided bypostfix
Reply550 5.1.1 <sales@lists.example.org>: Recipient address rejected: User unknown in relay recipient table
Subject—
09-21 13:51:30billing@partner.example
198.51.100.12
owner@lists.example.org—
reject

Why

Decided byrspamd
Reply5.7.1 Spam message rejected
Subject—
Allow sender
09-21 13:44:02hr@partner.example
192.0.2.31
jobs@acme.io—
tempfail

Why

Decided byrspamd
Reply4.7.1 Try again later
Subject—
Allow sender
09-21 13:30:55noreply@github.example
192.0.2.200
security@lists.example.org[advisory] new report
accept

Why

Decided byrspamd
Verdictno action, score -98.10 / 15.00
SymbolsSELFPOST_ALLOW_FROM(-100.00)
R_DKIM_ALLOW(-0.20)
Subject[advisory] new report
Deny sender
-
Page 1 of 38Older →Allow / Deny sender opens Filter lists with the entry filled in
+
Page 1 of 38Older →A decision opens its reason · Allow / Deny sender opens Filter lists with the entry filled in
diff --git a/docs/assets/panel-redesign/panel/src/components.html b/docs/assets/panel-redesign/panel/src/components.html index 20c5f4a..45d0ea4 100644 --- a/docs/assets/panel-redesign/panel/src/components.html +++ b/docs/assets/panel-redesign/panel/src/components.html @@ -48,6 +48,7 @@ error, fail, mismatch, bouncedfailtag is-danger is-light unknown, off, neutral countsofftag is-light held: quarantine · role: globalquarantinetag is-primary is-light + a tag that opens a sheet
reject

sheet

What it holds
What does not fit the row, as facts
How it closes
Esc, a click outside, or the cross
button.tag + sp-sheet (popover) diff --git a/docs/assets/panel-redesign/panel/src/in-log.html b/docs/assets/panel-redesign/panel/src/in-log.html index b2df05b..da1879c 100644 --- a/docs/assets/panel-redesign/panel/src/in-log.html +++ b/docs/assets/panel-redesign/panel/src/in-log.html @@ -20,15 +20,15 @@
- + - - - - - - + + + + + +
Time, UTCFromToSubjectDecisionWhy
Time, UTCFromToSubjectDecision
09-21 14:00:18t.berg@uni.example
192.0.2.77
dev@lists.example.orgRe: [dev] patch series v3acceptrspamd · no action, score 0.40 / 15.00Deny sender
09-21 13:59:02invoice@partner-billing.example
203.0.113.140
owner@lists.example.orgOutstanding invoice — action requiredacceptrspamd · add header, score 9.80 / 15.00; PHISHING(5.00) FORGED_SENDER(3.00) R_SPF_FAIL(1.00)Deny sender
09-21 13:57:41promo@bulk.example
198.51.100.90
sales@lists.example.org—rejectpostfix · 550 5.1.1 <sales@lists.example.org>: Recipient address rejected: User unknown in relay recipient tableDeny sender
09-21 13:51:30billing@partner.example
198.51.100.12
owner@lists.example.org—rejectrspamd · 5.7.1 Spam message rejectedAllow sender
09-21 13:44:02hr@partner.example
192.0.2.31
jobs@acme.io—tempfailrspamd · 4.7.1 Try again laterAllow sender
09-21 13:30:55noreply@github.example
192.0.2.200
security@lists.example.org[advisory] new reportacceptrspamd · no action, score -98.10 / 15.00; SELFPOST_ALLOW_FROM(-100.00) R_DKIM_ALLOW(-0.20)Deny sender
09-21 14:00:18t.berg@uni.example
192.0.2.77
dev@lists.example.orgRe: [dev] patch series v3
accept

Why

Decided byrspamd
Verdictno action, score 0.40 / 15.00
SubjectRe: [dev] patch series v3
Deny sender
09-21 13:59:02invoice@partner-billing.example
203.0.113.140
owner@lists.example.orgOutstanding invoice — action required
accept

Why

Decided byrspamd
Verdictadd header, score 9.80 / 15.00
SymbolsPHISHING(5.00)
FORGED_SENDER(3.00)
R_SPF_FAIL(1.00)
SubjectOutstanding invoice — action required
Deny sender
09-21 13:57:41promo@bulk.example
198.51.100.90
sales@lists.example.org—
reject

Why

Decided bypostfix
Reply550 5.1.1 <sales@lists.example.org>: Recipient address rejected: User unknown in relay recipient table
Subject—
09-21 13:51:30billing@partner.example
198.51.100.12
owner@lists.example.org—
reject

Why

Decided byrspamd
Reply5.7.1 Spam message rejected
Subject—
Allow sender
09-21 13:44:02hr@partner.example
192.0.2.31
jobs@acme.io—
tempfail

Why

Decided byrspamd
Reply4.7.1 Try again later
Subject—
Allow sender
09-21 13:30:55noreply@github.example
192.0.2.200
security@lists.example.org[advisory] new report
accept

Why

Decided byrspamd
Verdictno action, score -98.10 / 15.00
SymbolsSELFPOST_ALLOW_FROM(-100.00)
R_DKIM_ALLOW(-0.20)
Subject[advisory] new report
Deny sender
-
Page 1 of 38Older →Allow / Deny sender opens Filter lists with the entry filled in
+
Page 1 of 38Older →A decision opens its reason · Allow / Deny sender opens Filter lists with the entry filled in
diff --git a/docs/assets/panel-redesign/panel/theme.css b/docs/assets/panel-redesign/panel/theme.css index 7fd471d..71bb96a 100644 --- a/docs/assets/panel-redesign/panel/theme.css +++ b/docs/assets/panel-redesign/panel/theme.css @@ -270,3 +270,27 @@ code { background: var(--sp-well); color: var(--sp-ink); border-radius: 3px; pad .sp-record-head small { margin-left: 0; text-align: left; flex-basis: 100%; } .sp-postmark { display: none; } } + +/* sheet: what does not fit a table row, opened over the page from the row's + tag. It is the browser's own popover (the tag is a button with + popovertarget), so it needs no script: Esc, a click outside and the close + button all shut it, and focus returns to the tag. It rises from the bottom + edge across the whole window - the one component that is not laid out by the + page, hence the widths - with its content, a table of name and value, in a + column of reading width in the middle. */ +.sp-sheet { + inset: auto 0 0 0; width: auto; margin: 0; padding: 0; border: 0; border-top: 3px solid var(--sp-brick); + max-height: 75vh; overflow: auto; background: #fff; color: inherit; box-shadow: 0 -12px 40px rgba(40, 20, 15, .22); +} +.sp-sheet-in { max-width: 44rem; margin: 0 auto; padding: 0 1.25rem; } +.sp-sheet::backdrop { background: rgba(40, 20, 15, .38); } +.sp-sheet-head { display: flex; align-items: center; gap: .7rem; padding: 1rem 0 .8rem; border-bottom: 1px solid var(--sp-rule); } +.sp-sheet-head h2 { font-size: 1.15rem; font-weight: 600; margin-right: auto; } +.sp-sheet-head button { border: 0; background: none; cursor: pointer; font-size: 1.3rem; color: var(--sp-muted); } +.sp-sheet-body { padding: .4rem 0 1.4rem; } +/* The sheet's content is a table of name and value: the name is a label, set like the dt of facts. */ +.sp-sheet .table th { font-family: var(--sp-mono); font-size: var(--sp-fs-xs); font-weight: 500; letter-spacing: .08em; text-transform: uppercase; color: var(--sp-muted); white-space: nowrap; vertical-align: top; width: 1%; padding-right: 2rem; } +.sp-sheet .table td { overflow-wrap: anywhere; } +/* A tag that opens a sheet is a button: it keeps the tag's look and says it can + be pressed with the dotted underline links to more detail carry. */ +button.tag { border: 0; cursor: pointer; text-decoration: underline dotted; text-underline-offset: 3px; }