ui: /settings/notifications list + edit form (3 kinds)
Add settings.html (shell + sub-tab nav + conditional list/edit body), notifications.html and notification_edit.html (glob stubs), and the supporting CSS tokens (.ch-row, .ch-icon, .toggle, .kind-grid, .kind-card, .radio-pip, .test-pill) to input.css. Rebuild styles.css. Add ui_parse_test.go to catch template regressions at test time. The kind picker is JS-driven (no full page reload); the enabled toggle mirrors the existing visual toggle pattern; the test-notification button uses HTMX and renders the JSON response as a coloured pill client-side.
This commit is contained in:
@@ -451,4 +451,103 @@
|
||||
radial-gradient(ellipse at top, color-mix(in oklch, var(--accent), transparent 95%), transparent 60%),
|
||||
var(--panel);
|
||||
}
|
||||
|
||||
/* ---------- notification channel rows (/settings/notifications) ---------- */
|
||||
.ch-row {
|
||||
display: grid; align-items: center;
|
||||
grid-template-columns: 28px 200px 1fr 100px 130px 140px;
|
||||
column-gap: 16px;
|
||||
padding: 14px 18px; font-size: 13px;
|
||||
border-bottom: 1px solid var(--line-soft);
|
||||
transition: background 100ms ease;
|
||||
}
|
||||
.ch-row:last-child { border-bottom: 0; }
|
||||
.ch-row.head {
|
||||
cursor: default; font-size: 11px; color: var(--ink-fade);
|
||||
text-transform: uppercase; letter-spacing: 0.08em;
|
||||
padding-top: 10px; padding-bottom: 10px;
|
||||
}
|
||||
.ch-row.head:hover { background: transparent; }
|
||||
/* Whole-row click → edit page (mirrors .host-row.clickable). */
|
||||
.ch-row.clickable { position: relative; cursor: pointer; }
|
||||
.ch-row.clickable .row-link {
|
||||
position: absolute; inset: 0; z-index: 0;
|
||||
text-indent: -9999px; overflow: hidden;
|
||||
}
|
||||
.ch-row.clickable:hover { background: var(--panel-hi); }
|
||||
.ch-row.clickable > * { position: relative; z-index: 1; pointer-events: none; }
|
||||
.ch-row.clickable > .row-link { pointer-events: auto; }
|
||||
.ch-row.clickable > .row-action { pointer-events: auto; }
|
||||
|
||||
/* Channel kind icons */
|
||||
.ch-icon {
|
||||
width: 24px; height: 24px;
|
||||
border-radius: 5px;
|
||||
display: inline-flex; align-items: center; justify-content: center;
|
||||
font-family: 'JetBrains Mono', monospace; font-size: 10px; font-weight: 600;
|
||||
background: var(--panel-hi); color: var(--ink-mute);
|
||||
border: 1px solid var(--line);
|
||||
}
|
||||
.ch-icon.webhook { color: var(--accent); border-color: color-mix(in oklch, var(--accent), transparent 60%); }
|
||||
.ch-icon.ntfy { color: var(--warn); border-color: color-mix(in oklch, var(--warn), transparent 60%); }
|
||||
.ch-icon.smtp { color: var(--ok); border-color: color-mix(in oklch, var(--ok), transparent 60%); }
|
||||
|
||||
/* ---------- toggle (enabled/disabled switch) ---------- */
|
||||
.toggle {
|
||||
display: inline-block; width: 30px; height: 16px; border-radius: 9999px;
|
||||
background: var(--line); position: relative; cursor: pointer;
|
||||
transition: background 120ms ease; flex-shrink: 0;
|
||||
}
|
||||
.toggle::after {
|
||||
content: ""; position: absolute; left: 2px; top: 2px;
|
||||
width: 12px; height: 12px; border-radius: 9999px;
|
||||
background: var(--ink-mid);
|
||||
transition: all 120ms ease;
|
||||
}
|
||||
.toggle.on { background: color-mix(in oklch, var(--accent), transparent 50%); }
|
||||
.toggle.on::after { left: 16px; background: var(--accent); }
|
||||
|
||||
/* ---------- kind-picker radio cards (channel edit form) ---------- */
|
||||
.kind-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 14px; }
|
||||
.kind-card {
|
||||
border: 1px solid var(--line-soft); background: var(--bg);
|
||||
border-radius: 7px; padding: 16px;
|
||||
cursor: pointer;
|
||||
transition: border-color 120ms ease, background 120ms ease;
|
||||
}
|
||||
.kind-card:hover { border-color: var(--ink-mute); }
|
||||
.kind-card.selected {
|
||||
border-color: color-mix(in oklch, var(--accent), transparent 50%);
|
||||
background: color-mix(in oklch, var(--accent), transparent 95%);
|
||||
}
|
||||
|
||||
/* Radio pip inside kind cards */
|
||||
.radio-pip {
|
||||
width: 14px; height: 14px;
|
||||
border-radius: 9999px;
|
||||
border: 1px solid var(--line);
|
||||
display: inline-flex; align-items: center; justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.radio-pip.on { border-color: var(--accent); }
|
||||
.radio-pip.on::after {
|
||||
content: ""; width: 6px; height: 6px; border-radius: 9999px;
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
/* ---------- test-result pills (notification test button) ---------- */
|
||||
.test-pill {
|
||||
display: inline-block;
|
||||
padding: 5px 10px; border-radius: 5px; font-size: 12.5px;
|
||||
}
|
||||
.test-pill-ok {
|
||||
border: 1px solid color-mix(in oklch, var(--ok), transparent 60%);
|
||||
background: color-mix(in oklch, var(--ok), transparent 92%);
|
||||
color: var(--ok);
|
||||
}
|
||||
.test-pill-fail {
|
||||
border: 1px solid color-mix(in oklch, var(--bad), transparent 60%);
|
||||
background: color-mix(in oklch, var(--bad), transparent 92%);
|
||||
color: var(--bad);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user