source: Klonkt/src/assets/css/guardian.css@ 70677e96

main
Last change on this file since 70677e96 was 70677e96, checked in by Robin Genis <roboburr@…>, 6 weeks ago

Guardian-PWA: een paneel per kind

/guardian was een platte lijst van zeven secties: de wards' berichten, de
volgverzoeken, de hulpvragen, adopteren, verzonden aanvragen, wards, meldingen.
Wie een kind wilde overzien moest tussen die secties heen en weer, en nergens
stond bij elkaar wat er over dat ene kind speelt. Een guardian denkt niet per
functie maar per kind.

Nu is de wards-lijst de ingang: elk kind is een regel die opent naar een paneel
met zijn instellingen, zijn volgverzoeken, zijn hulpvragen en zijn recente
berichten. De regel zelf draagt de tellers (hulpvragen, volgverzoeken), zodat
een dicht paneel nooit iets verbergt dat een antwoord nodig heeft; dat is
belangrijk voor de volgverzoeken, want daar zit de follow-gating in.

De hulpvragen blijven daarnaast bovenaan staan, over alle kinderen heen, want
dat is waar deze app voor bestaat en het moet opvallen zonder dat je eerst een
kind opent. Ze verschijnen dus bewust twee keer: bovenaan de recente, in het
paneel de volledige geschiedenis van dat kind.

De hulpvraag is geen alarm. Er wordt niemand automatisch gewaarschuwd; een
guardian kan hem stil oplossen. De kaart is daarom rustig gehouden.

Changed files:
src/views/pages/guardian.ejs

  • feed-section en follow-section weg als losse secties

src/assets/js/guardian.js

  • helpCard, feedCard en followCard losgetrokken zodat beide plekken ze delen
  • wardPanel: instellingen, volgverzoeken, hulpvragen, berichten, acties
  • openPanels onthoudt wat open staat, zodat verversen niet dichtklapt
  • feed en volgverzoeken vullen nu een cache en hertekenen de wards-lijst

src/assets/css/guardian.css

  • opmaak voor het paneel en de tellers op de regel

src/routes/guardian.js

  • authorUri en wardUri meegeven: de sleutels waarop gegroepeerd wordt
  • de nieuwe labels toegevoegd aan uiStrings

src/services/i18n.js

  • 39 strings voor het paneel in nl, en, de

New file:
test/guardian-panel.test.js

  • de client schrijft nergens naar een verdwenen sectie
  • elke paneelsectie heeft zijn groepeersleutel
  • elk label dat de client gebruikt wordt ook geserveerd

remarks: geverifieerd in de browser op een wegwerp-database met twee kinderen:
elk paneel toont alleen zijn eigen volgverzoek, hulpvraag en post, een geopend
paneel blijft open over een ververs-ronde heen, en op 375px loopt niets buiten
beeld. De afhandel-lifecycle (oppakken/afgehandeld, shaer-jxi) en luid publiek
als tweede gated feature (shaer-3kp) komen hierna in dit paneel.

-robo
Co-Authored-By: Claude Opus 4.8 <noreply@…>

  • Property mode set to 100644
File size: 6.7 KB
RevLine 
[318d0c2]1/* Guardian PWA (FEP-633c): its own calm, dark surface; the buoy orange is
2 the accent. Standalone: this page never inherits the site theme. */
3:root {
4 --bg: #141a24;
5 --card: #1e2632;
6 --ink: #e8ecf2;
7 --sub: #93a0b4;
[c26cc18]8 --line: #2c3646;
[318d0c2]9 --accent: #ff6b35;
10 --ok: #4caf7d;
11}
12* { box-sizing: border-box; }
13body {
14 margin: 0;
15 background: var(--bg);
16 color: var(--ink);
17 font: 16px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
[c26cc18]18 padding-bottom: 48px;
[318d0c2]19}
20.g-head {
21 display: flex;
22 align-items: center;
[c26cc18]23 gap: 12px;
24 padding: 16px;
[318d0c2]25 background: var(--card);
[c26cc18]26 border-bottom: 1px solid var(--line);
[318d0c2]27 position: sticky;
28 top: 0;
[c26cc18]29 z-index: 2;
[318d0c2]30}
[c26cc18]31.g-head-txt { flex: 1; }
32.g-head h1 { font-size: 1.15rem; margin: 0; }
33.g-head .g-sub { margin: 0; color: var(--sub); font-size: .78rem; }
34.g-buoy { font-size: 1.7rem; }
35.g-me { color: var(--sub); font-size: .85rem; }
[318d0c2]36#site-picker {
37 background: var(--bg); color: var(--ink);
[c26cc18]38 border: 1px solid var(--line); border-radius: 8px; padding: 6px 8px;
[318d0c2]39}
[c26cc18]40main { max-width: 640px; margin: 0 auto; padding: 8px 16px; }
41
42section { padding: 18px 0; border-bottom: 1px solid var(--line); }
43section:last-child { border-bottom: 0; }
44.g-sec-head { display: flex; align-items: center; gap: 8px; }
45.g-sec-head h2 { font-size: 1.02rem; margin: 0; }
46.g-badge {
47 background: var(--accent); color: #fff; font-size: .72rem; font-weight: 700;
48 min-width: 20px; text-align: center; border-radius: 10px; padding: 1px 7px;
49}
50.g-sec-sub { color: var(--sub); font-size: .84rem; margin: 4px 0 12px; }
51.g-empty { color: var(--sub); font-size: .9rem; margin: 6px 0 0; }
52.g-msg { font-size: .85rem; color: var(--ok); margin: 8px 0 0; }
[318d0c2]53.g-msg.err { color: #ff7a7a; }
54.g-list { display: flex; flex-direction: column; gap: 8px; }
55
[c26cc18]56.g-card { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; }
[318d0c2]57.g-card.help { border-left: 3px solid var(--accent); }
58.g-card .row { display: flex; align-items: center; gap: 10px; }
[c26cc18]59.g-card .row .grow { flex: 1; min-width: 0; }
60.g-card .who { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
61.g-card .when { color: var(--sub); font-size: .76rem; white-space: nowrap; }
62.g-card .body { margin-top: 8px; font-size: .92rem; overflow-wrap: anywhere; }
63.g-card .body img { max-width: 100%; border-radius: 8px; margin-top: 6px; }
64.g-link { display: inline-block; margin-top: 8px; color: var(--accent); font-size: .82rem; text-decoration: none; }
65
66.tag { font-size: .72rem; font-weight: 600; padding: 3px 9px; border-radius: 20px; white-space: nowrap; }
67.tag.wait { background: #3a2f1a; color: #e8b04b; }
68.tag.ok { background: #17301f; color: var(--ok); }
[780a7c6]69.tag.co { background: #2a1f3a; color: #c39bff; }
[318d0c2]70
[c26cc18]71#adopt-form { display: flex; gap: 8px; }
[318d0c2]72#adopt-form input {
[c26cc18]73 flex: 1; min-width: 0;
74 background: var(--bg); color: var(--ink);
75 border: 1px solid var(--line); border-radius: 10px; padding: 11px 12px;
[318d0c2]76}
77button {
78 background: var(--accent); color: #fff; border: 0;
[c26cc18]79 border-radius: 10px; padding: 11px 18px; font-weight: 600; cursor: pointer;
[318d0c2]80}
[c26cc18]81button:disabled { opacity: .5; cursor: default; }
82button.quiet { background: transparent; color: var(--sub); border: 1px solid var(--line); font-weight: 500; }
83button.quiet.is-on { color: var(--ok); border-color: var(--ok); }
84button.small { padding: 6px 12px; font-size: .82rem; }
[f1c50f9]85
86/* Wards' corner (v2 meekijken) */
87.g-card.feed .g-when { color: var(--muted, #888); font-size: .8em; margin-left: auto; }
88.g-card.feed .feed-body { margin-top: 6px; line-height: 1.4; }
89.g-card.feed .feed-body img { max-width: 100%; border-radius: 8px; }
[d9ad6c5]90
91/* ── The body of a post ────────────────────────────────────────────────────
92 The 🛟 card shows a real post, so it is rendered by the same partial de
93 Krant and Berichten use (partials/note-body). These are that partial's
94 classes, in the PWA's own colours: the dashboard is standalone and does not
95 load the site's stylesheet. */
96.g-note .tl-content { line-height: 1.5; overflow-wrap: anywhere; }
97.g-note .tl-content p { margin: .35rem 0; }
98.g-note .tl-content p:first-child { margin-top: 0; }
99.g-note .tl-content p:last-child { margin-bottom: 0; }
100.g-note .tl-content a { color: var(--accent); }
101.g-note img.emoji { height: 1.25em; width: auto; margin: 0 .05em; vertical-align: -.2em;
102 display: inline-block; border-radius: 0; background: none; }
103
104/* Quote card and link preview: one card, two origins. */
105.g-note .tl-quote { margin: 8px 0 0; padding: 8px 10px; border-radius: 10px;
106 border: 1px solid var(--line); background: var(--card-2, rgba(128,128,128,.07)); }
107.g-note .tl-quote-head { display: flex; align-items: center; gap: 6px; margin: 0 0 4px; min-width: 0; }
108.g-note .tl-quote-avatar { flex: 0 0 auto; width: 20px; height: 20px; border-radius: 50%; object-fit: cover; }
109.g-note .tl-quote-name { font-weight: 600; font-size: .82rem; white-space: nowrap; }
110.g-note .tl-quote-handle { color: var(--sub); font-size: .76rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
111.g-note .tl-quote-body { color: var(--sub); font-size: .88rem; line-height: 1.45; max-height: 14em; overflow: hidden; }
112.g-note .tl-quote-media { display: block; margin: 6px 0 0; }
113
114/* The capture a 🛟 usually carries. */
115.g-note .tl-media { display: flex; flex-direction: column; gap: 6px; margin: 8px 0 0; }
116.g-note .tl-media-img { display: block; border-radius: 10px; overflow: hidden; }
117.g-note .tl-media-img img { width: 100%; height: auto; display: block; background: #fff; }
118.g-note .tl-media-video, .g-note .tl-media-audio { width: 100%; margin: 8px 0 0; border-radius: 10px; display: block; }
119.g-note .tl-media-video { max-height: 320px; background: #000; }
[70677e96]120
121/* ── Paneel per ward ───────────────────────────────────────────────────────
122 Een guardian denkt per kind, niet per functie: achter de regel van een kind
123 zit alles over dat kind. De regel zelf draagt de tellers, zodat een dicht
124 paneel nooit iets verbergt dat een antwoord nodig heeft. */
125.g-card.ward > .row { gap: 8px; }
126.g-panel { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); }
127.g-panel[hidden] { display: none; }
128.g-panel-sec + .g-panel-sec { margin-top: 16px; }
129.g-panel-sec h3 { margin: 0 0 6px; font-size: .82rem; font-weight: 600; letter-spacing: .03em;
130 text-transform: uppercase; color: var(--sub); }
131.g-panel-sec .g-card { background: transparent; border-color: var(--line); }
132.g-panel-sec .g-card + .g-card { margin-top: 6px; }
133.g-panel-sec .row { flex-wrap: wrap; }
134.g-empty.small { margin: 0; font-size: .85rem; }
135.tag.help { color: var(--accent); border-color: var(--accent); }
Note: See TracBrowser for help on using the repository browser.