@klodd/ds 5.2.2 → 5.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,9 +45,9 @@
45
45
  sentence-case i template ("Din dagsbudget", inte "DIN DAGSBUDGET").
46
46
  Det matchar svensk grafisk konvention + var hero-hierarki kommer
47
47
  fran font-size och weight, inte fran caps. */
48
- font-size: var(--fs-12);
48
+ font-size: var(--fs-16);
49
49
  font-weight: var(--fw-medium);
50
- color: var(--text-muted);
50
+ color: var(--text-subtle);
51
51
  letter-spacing: var(--ls-tight);
52
52
  margin: 0 0 var(--space-12);
53
53
  }
@@ -106,7 +106,7 @@
106
106
 
107
107
  .hero__meta {
108
108
  font-size: var(--fs-13);
109
- color: var(--text-subtle);
109
+ color: var(--text-muted);
110
110
  margin: 0 0 var(--space-20);
111
111
  }
112
112
 
@@ -57,6 +57,25 @@ dialog.sheet::backdrop {
57
57
  inset: auto;
58
58
  }
59
59
 
60
+ /* Native <dialog class="dialog"> via showModal() far :modal-pseudo-class
61
+ som triggar UA-stylesheet med high-specificity inset:0 + margin:auto.
62
+ Den vinner over .dialog's transform-baserade centrering ovan (UA
63
+ regel ar 0,1,1 mot .dialog 0,1,0) sa transform forsvinner men
64
+ inset:0 + margin:auto inte appliceras pa rad sa elementet hamnar
65
+ i top-left. Fix: matcha UA's metod med dialog.dialog:modal-selectorn
66
+ (specificity 0,2,1) som vinner. inset:0 + margin:auto ar native-
67
+ metoden for dialog-centrering per MDN 2024+.
68
+ .dialog-regeln ovanfor bevaras for icke-modal <div role="dialog">-
69
+ anvandning som inte triggrar :modal. Verifierat Jubb v192
70
+ (2026-05-19) - se ADR 0009-turbo-nav-script-init.md for
71
+ diagnos-spar via Chrome MCP. */
72
+ dialog.dialog:modal {
73
+ position: fixed;
74
+ inset: 0;
75
+ margin: auto;
76
+ transform: none;
77
+ }
78
+
60
79
  .dialog__header {
61
80
  display: flex;
62
81
  align-items: center;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@klodd/ds",
3
- "version": "5.2.2",
3
+ "version": "5.2.4",
4
4
  "description": "Klodd shared design system - tokens, components, JS",
5
5
  "main": "css/index.css",
6
6
  "bin": {
@@ -0,0 +1,148 @@
1
+ # 0009 - Per-page-JS-init under turbo-nav
2
+
3
+ ## Status
4
+
5
+ Locked. Upptäckt v192 (2026-05-19) under Chrome MCP-diagnos av
6
+ brief-progress-flödet i Jubb.
7
+
8
+ ## Context
9
+
10
+ `turbo-nav.js` (paketet) implementerar same-document-navigation
11
+ istället för full document-load. Vid klick på en intern länk:
12
+
13
+ 1. Fetchar måldokumentets HTML
14
+ 2. Swappar **bara `<main id="main">` + `<title>` + body-data-attribut**
15
+ 3. Behåller resten av `<body>` oförändrad mellan sidor (bottom-nav,
16
+ pwa-overlay, scripts efter `</main>` etc)
17
+
18
+ Den arkitekturen är dokumenterad i JSDoc-header av `turbo-nav.js`
19
+ ("Vad vi swappar"). Den ger snabbare upplevd navigation + bevarar
20
+ JS-state som inte är page-specifik.
21
+
22
+ **Konsekvens som inte var explicit dokumenterad innan denna ADR:**
23
+ Scripts som ligger i Jinja-mönstret `{% block scripts %}` (typiskt
24
+ placerat efter `</main>` i base.html, paritet med shadcn/Rails-
25
+ turbo-konventionen) re-exekveras **aldrig** efter turbo-swap. Block
26
+ scripts är utanför swap-region. Vid initial full-load körs blocket
27
+ en gång på den första sidan; om den sidan inte har scripten är
28
+ tagget tom; vid senare turbo-nav till en sida som DEFINIERAR `{%
29
+ block scripts %}` med en script-tag, swappas bara `<main>`-content
30
+ och scripten visas aldrig i körd DOM.
31
+
32
+ Symptom (Jubb 2026-05-19):
33
+
34
+ - `brief-progress.js` lades i `{% block scripts %}` i `job_detail.html`
35
+ efter att en tidigare diagnos felaktigt identifierat
36
+ `<main>`-position som rotorsak
37
+ - v191 deploy
38
+ - Calle navigerade till `/jobb/X` via klick från `/jobb-listan` (turbo)
39
+ - `window.JubbBriefProgress` förblev `undefined` på destination-sidan
40
+ - Diagnos via Chrome MCP: Performance API visade ingen
41
+ `initiatorType: "script"`-entry för brief-progress.js. Filen
42
+ hämtades aldrig som script. Block scripts var utanför swap-region
43
+
44
+ ## Decision
45
+
46
+ **Per-page-JS som behöver re-init på navigation skall laddas globalt
47
+ i base.html, inte via `{% block scripts %}`.** Globalt laddat script
48
+ exekveras en gång vid full-reload och förblir tillgängligt över alla
49
+ turbo-swaps. Per-page-init görs genom att lyssna på
50
+ `turbo:navigated`-event:
51
+
52
+ ```html
53
+ <!-- base.html, efter alla andra defer-scripts, före {% block scripts %}: -->
54
+ <script src="/static/js/per-page-feature.js?v={{ static_version }}" defer></script>
55
+ ```
56
+
57
+ ```javascript
58
+ // per-page-feature.js
59
+ (function () {
60
+ function maybeInit() {
61
+ // Defensive: kör bara om relevant DOM-element finns på nuvarande sida.
62
+ const root = document.getElementById("feature-root");
63
+ if (!root) return;
64
+ // ... init-logik (idempotent) ...
65
+ }
66
+
67
+ // Initial-load
68
+ if (document.readyState === "loading") {
69
+ document.addEventListener("DOMContentLoaded", maybeInit);
70
+ } else {
71
+ maybeInit();
72
+ }
73
+
74
+ // Turbo-aware re-init vid varje same-document-swap
75
+ document.addEventListener("turbo:navigated", maybeInit);
76
+ })();
77
+ ```
78
+
79
+ ### Krav på det globala scriptet
80
+
81
+ 1. **Idempotent init.** Eftersom `maybeInit` körs en gång vid
82
+ initial-load och en gång per turbo:navigated, måste den vara
83
+ safe att köra flera gånger utan side-effects (dubbla handlers,
84
+ dubbla pollers, etc).
85
+ 2. **Defensive DOM-checks.** Scriptet exekveras på alla sidor (inkl.
86
+ sidor som inte använder featuren). Init-logik måste kolla att
87
+ relevant DOM-element finns innan den agerar.
88
+ 3. **Document-level event-delegation för clicks.** addEventListener
89
+ på elements som swappas av Turbo försvinner med swap (gamla
90
+ elementet GC:as). Använd antingen document-level delegation
91
+ (single global listener som filtrerar på event.target.id/class)
92
+ eller re-registrera handlers i maybeInit.
93
+
94
+ ### Förbjudet mönster
95
+
96
+ ```jinja2
97
+ {# job_detail.html - DETTA FUNGERAR INTE under Turbo #}
98
+ {% block scripts %}
99
+ <script src="/static/js/per-page-feature.js?v={{ static_version }}" defer></script>
100
+ {% endblock %}
101
+ ```
102
+
103
+ `{% block scripts %}` är användbart för att lägga in **markup**
104
+ (t.ex. en `<noscript>` eller en page-specifik `<meta>`-tag) i base.html-
105
+ strukturen, men för scripts måste path:en gå genom base.html.
106
+
107
+ ## Undantag - data-turbo="false"
108
+
109
+ Sidor vars länkar har `data-turbo="false"` är utanför Turbo-scopet
110
+ och får full document-reload. Per-page-scripts inom `<main>` kan
111
+ användas för sådana sidor eftersom hela dokumentet laddas om vid
112
+ navigation.
113
+
114
+ Triage-vyn i Jubb är det enda kända undantaget i klodd-ds-portfolion
115
+ (2026-05-19). Triage-länken har `data-turbo="false"` per
116
+ `partials/_bottom_nav.html` eftersom triage-vyn har komplexa
117
+ per-page-scripts (swipe-cards, decision-overlays) som inte tål
118
+ re-init via turbo:navigated på den volymen.
119
+
120
+ Nya per-page-scripts ska DEFAULT följa det globalt-laddade-med-
121
+ turbo:navigated-mönstret. Disable Turbo bara om det finns en
122
+ dokumenterad anledning att inte göra det.
123
+
124
+ ## Consequences
125
+
126
+ - Alla per-page-JS som behöver init på `/jobb/X`, `/insikter`,
127
+ `/körningar` etc måste flyttas till global laddning i base.html
128
+ om de inte redan är där. Dokumentera med JSDoc-header som
129
+ refererar till denna ADR.
130
+ - `{% block scripts %}` i base.html bevaras för markup-injection
131
+ (t.ex. `<script type="application/ld+json">` med page-specifik
132
+ data) men inte för script-src-tags.
133
+ - Future audit: scanna app/templates/ för `{% block scripts %}`
134
+ med `<script src="...">`-mönster och migrera dem.
135
+ - I Jubb (2026-05-19): `brief-progress.js` migrerad till global
136
+ laddning per denna ADR. Inga andra per-page-scripts identifierade
137
+ som drabbade.
138
+
139
+ ## Diagnos-spår för framtida förebyggning
140
+
141
+ Chrome DevTools Performance API var nyckeln till diagnos:
142
+ `performance.getEntriesByType('resource')` filtrerad på
143
+ `initiatorType` visar exakt hur en resurs laddades. Saknas
144
+ `initiatorType: "script"`-entry för en `<script src>`-tag som
145
+ syns i DOM, är scriptet aldrig exekverat. Möjliga orsaker
146
+ inkluderar block-scripts efter turbo-swap, CSP-block, eller MIME-
147
+ type-fel. Performance API är trusted-truth - DOM-inspection ensam
148
+ räcker inte.