@klodd/ds 3.16.0 → 3.17.1

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.
@@ -277,6 +277,7 @@
277
277
  --fs-40: 40px;
278
278
  --fs-64: 64px;
279
279
  --fs-80: 80px;
280
+ --fs-100: 100px;
280
281
 
281
282
  /* Font-weight - bara 400 och 500. Ingen 600 eller 700. */
282
283
  --fw-regular: 400;
@@ -24,7 +24,9 @@
24
24
  text vid done.
25
25
  ================================================================ */
26
26
  .hero-amount {
27
- font-size: var(--hero-amount-fz, var(--fs-80));
27
+ /* 2026-05-13: fs-80 → fs-100 default (25% storre) for hero-display-tyngd.
28
+ Apparna kan overstyra via --hero-amount-fz om mindre size behovs. */
29
+ font-size: var(--hero-amount-fz, var(--fs-100));
28
30
  /* Undantag fran 400/500-policy: display-siffra, inte UI-text.
29
31
  600 ger nodvandig visuell tyngd pa hero-storlekar. */
30
32
  font-weight: 600;
@@ -20,10 +20,11 @@
20
20
  data-animate-roll triggar animationen.
21
21
  ================================================================ */
22
22
  .hero {
23
- /* Sprint 3a 2026-05-12: horizontal padding 4→0 for alignment med
24
- andra container-element. Se DESIGN-LANGUAGE.md sektion 8. */
23
+ /* 2026-05-13: text-align center for hero-sektion. Hero-content
24
+ (amount + label + meta + actions) centreras pa horisontalt sa
25
+ pengar-display dominerar viewport-mittan. */
25
26
  padding: var(--space-20) 0 var(--space-24);
26
- text-align: left;
27
+ text-align: center;
27
28
  }
28
29
 
29
30
  .hero__heading {
@@ -53,7 +54,8 @@
53
54
  }
54
55
 
55
56
  .hero__amount {
56
- font-size: var(--fs-80);
57
+ /* 2026-05-13: fs-80 → fs-100 (25% storre) for mer display-tyngd. */
58
+ font-size: var(--fs-100);
57
59
  font-weight: var(--fw-medium);
58
60
  letter-spacing: var(--ls-tightest, -0.04em);
59
61
  color: var(--text-default);
@@ -75,6 +77,7 @@
75
77
  .hero__amount-row {
76
78
  display: flex;
77
79
  align-items: center;
80
+ justify-content: center;
78
81
  gap: var(--space-10);
79
82
  margin-bottom: var(--space-8);
80
83
  }
@@ -92,5 +95,6 @@
92
95
  display: flex;
93
96
  gap: var(--space-8);
94
97
  align-items: center;
98
+ justify-content: center;
95
99
  flex-wrap: wrap;
96
100
  }
@@ -112,18 +112,23 @@
112
112
 
113
113
  /* ================================================================
114
114
  ==== TOPBAR (in-flow header)
115
- Tre slots: back-knapp / titel / action. Display flex, full bredd.
116
-
117
- Layout-doktrin (2026-05-12):
118
- - Avatar (.avatar) ar ALLTID hogerstalld via margin-left: auto.
119
- - Gor month-pill, brand-pill, topbar__logo eller back-knapp pa
120
- vanster sida automatiskt vanster-positionerade.
121
- - Galler aven nar avatar ar wrappad i <a href> for navigation.
122
- - Doktrin gemensam for alla Klodd-appar (Ekonom, Jubb, framtida).
123
- Se DESIGN-LANGUAGE.md sektion 13.
115
+ Tre slots: pwa-avatar/back (vanster) / titel-eller-month-pill
116
+ (center) / user-avatar (hoger). Display grid med 3 kolumner.
117
+
118
+ Layout-doktrin (2026-05-13):
119
+ - Kolumn 1 (vanster, auto): .pwa-avatar ELLER .topbar__back
120
+ - Kolumn 2 (center, 1fr): .topbar__title ELLER .month-pill
121
+ - Kolumn 3 (hoger, auto): .avatar (ev. wrappad i <a>)
122
+
123
+ Grid-positioning sker via explicit grid-column-rules nedan -
124
+ HTML-ordning paverkar inte visual position.
125
+
126
+ Doktrin gemensam for alla Klodd-appar (Ekonom, Jubb, framtida).
127
+ Se DESIGN-LANGUAGE.md sektion 13.
124
128
  ================================================================ */
125
129
  .topbar {
126
- display: flex;
130
+ display: grid;
131
+ grid-template-columns: auto 1fr auto;
127
132
  align-items: center;
128
133
  gap: var(--space-12);
129
134
  min-height: var(--touch-min);
@@ -131,11 +136,27 @@
131
136
  margin-bottom: var(--space-16);
132
137
  }
133
138
 
134
- /* Avatar alltid hogerstalld. Galler bade direkt <.avatar> och
135
- wrapped <a href="/profil"><span class="avatar"></span></a>. */
139
+ /* Vanster kolumn: pwa-avatar eller back-knapp */
140
+ .topbar > .pwa-avatar,
141
+ .topbar > .topbar__back {
142
+ grid-column: 1;
143
+ justify-self: start;
144
+ }
145
+
146
+ /* Center kolumn: titel eller month-pill */
147
+ .topbar > .topbar__title,
148
+ .topbar > .topbar__logo,
149
+ .topbar > .month-pill,
150
+ .topbar > .brand-pill {
151
+ grid-column: 2;
152
+ justify-self: center;
153
+ }
154
+
155
+ /* Hoger kolumn: user-avatar (direkt eller wrappad i <a>) */
136
156
  .topbar > .avatar,
137
157
  .topbar > a:has(> .avatar) {
138
- margin-left: auto;
158
+ grid-column: 3;
159
+ justify-self: end;
139
160
  }
140
161
 
141
162
  .topbar__back {
@@ -0,0 +1,51 @@
1
+ /* ================================================================
2
+ components/pwa-avatar.css
3
+ PWA-identifierande avatar i topbar (vansterstalld).
4
+ Skiljer sig fran .avatar (user-profile, hogerstalld) genom:
5
+ - Anvands for app-brand-identifiering (Jubb-J, Ekonom-E)
6
+ - Hard-refresh-trigger via klick (se hard-refresh.js)
7
+ - Subtle accent-soft-bg + accent-text istallet for accent-9-gradient
8
+
9
+ Storlek 36x36 matchar .avatar default + .month-pill for visuell
10
+ harmoni i topbar.
11
+
12
+ Blocks:
13
+ .pwa-avatar - klickbar app-brand-avatar (button-element)
14
+ ================================================================ */
15
+ .pwa-avatar {
16
+ display: inline-flex;
17
+ align-items: center;
18
+ justify-content: center;
19
+ width: 36px;
20
+ height: 36px;
21
+ padding: 0;
22
+ background: var(--accent-soft);
23
+ color: var(--accent-text);
24
+ border: 1px solid var(--accent-a6);
25
+ border-radius: var(--radius-full);
26
+ font-family: inherit;
27
+ font-size: var(--fs-15);
28
+ font-weight: var(--fw-medium);
29
+ cursor: pointer;
30
+ flex-shrink: 0;
31
+ -webkit-tap-highlight-color: transparent;
32
+ touch-action: manipulation;
33
+ transition:
34
+ background var(--dur-fast) var(--ease-spring-snappy),
35
+ transform var(--dur-fast) var(--ease-spring-snappy);
36
+ }
37
+
38
+ @media (hover: hover) and (pointer: fine) {
39
+ .pwa-avatar:hover {
40
+ background: var(--accent-moderate);
41
+ }
42
+ }
43
+
44
+ .pwa-avatar:active {
45
+ transform: scale(0.95);
46
+ }
47
+
48
+ .pwa-avatar:focus-visible {
49
+ outline: 2px solid var(--border-focus);
50
+ outline-offset: 2px;
51
+ }
package/css/index.css CHANGED
@@ -59,6 +59,7 @@
59
59
  @import './components/upload-spinner.css';
60
60
  @import './components/tab-bar.css';
61
61
  @import './components/pill-nav.css';
62
+ @import './components/pwa-avatar.css';
62
63
 
63
64
  /* v3.1.0 - generic kategori-monster (token-binding via app-domain-CSS) */
64
65
  @import './components/colored-row.css';
@@ -0,0 +1,45 @@
1
+ /* ================================================================
2
+ hard-refresh.js
3
+ PWA hard-refresh: rensa Cache Storage + unregister Service Worker
4
+ + reload. Motsvarar webbläsarens Cmd+Shift+R men funkar inom PWA
5
+ (installerad standalone-mode dar tangentbordsgenvagen inte finns).
6
+
7
+ Auto-bind: alla .pwa-avatar-element + [data-pwa-refresh]-element
8
+ triggar hardRefresh() pa klick med confirm-dialog.
9
+
10
+ Aktivera genom att inkludera i base.html:
11
+ <script defer src="/static/js/hard-refresh.js"></script>
12
+ ================================================================ */
13
+ (function() {
14
+ 'use strict';
15
+
16
+ async function hardRefresh() {
17
+ try {
18
+ if ('caches' in window) {
19
+ const keys = await caches.keys();
20
+ await Promise.all(keys.map(k => caches.delete(k)));
21
+ }
22
+ if ('serviceWorker' in navigator) {
23
+ const regs = await navigator.serviceWorker.getRegistrations();
24
+ await Promise.all(regs.map(r => r.unregister()));
25
+ }
26
+ } catch (err) {
27
+ console.error('hard-refresh: cleanup-fel', err);
28
+ } finally {
29
+ location.reload();
30
+ }
31
+ }
32
+
33
+ document.addEventListener('click', (e) => {
34
+ const target = e.target.closest('.pwa-avatar, [data-pwa-refresh]');
35
+ if (!target) return;
36
+ e.preventDefault();
37
+ const proceed = confirm('Hard refresh: rensar cache och laddar om PWA-en. Forsatta?');
38
+ if (proceed) {
39
+ hardRefresh();
40
+ }
41
+ });
42
+
43
+ // Exponera for programmatic-anvandning
44
+ window.kloddHardRefresh = hardRefresh;
45
+ })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@klodd/ds",
3
- "version": "3.16.0",
3
+ "version": "3.17.1",
4
4
  "description": "Klodd shared design system - tokens, components, JS",
5
5
  "main": "css/index.css",
6
6
  "bin": {
@@ -200,8 +200,24 @@ För varje entry gäller:
200
200
  ### avatar (`avatar.css`)
201
201
  - **Blocks:** `.avatar`
202
202
  - **Modifiers:** `.avatar--sm`, `.avatar--lg`
203
- - **Anvand:** Cirkular initial-avatar med accent-gradient
204
- - **INTE:** Foto-avatar (overlapp via custom regel)
203
+ - **Anvand:** Cirkular initial-avatar med accent-gradient. ALLTID
204
+ hogerstalld i topbar (kolumn 3) per DESIGN-LANGUAGE sektion 13.
205
+ - **INTE:** Foto-avatar (overlapp via custom regel). Vansterstalld
206
+ i topbar (anvand `.pwa-avatar` istallet).
207
+
208
+ ### pwa-avatar (`pwa-avatar.css`) - v3.17.0
209
+ - **Blocks:** `.pwa-avatar`
210
+ - **Anvand:** App-brand-identifierare i topbar kolumn 1 (vansterstalld).
211
+ Klick triggar hard-refresh av PWA (rensar Cache Storage + unregister
212
+ SW + reload) via `js/hard-refresh.js`-auto-bind. Storlek 36x36
213
+ matchar `.avatar` for visuell harmoni.
214
+ - **INTE:** User-profile-avatar (anvand `.avatar` i kolumn 3). Anvandning
215
+ utanfor topbar.
216
+ - **Tokens:** `--accent-soft` (bg), `--accent-text` (color), `--accent-a6`
217
+ (border), `--accent-moderate` (hover-bg). Storlek 36x36, BR full.
218
+ - **JS:** `hard-refresh.js` lyssnar pa klick. Confirm-dialog innan
219
+ destruktiv cache-cleanup + reload. Activated via base.html-include:
220
+ `<script defer src="/static/js/hard-refresh.js"></script>`
205
221
 
206
222
  ### list-row (`list-row.css`)
207
223
  - **Blocks:** `.list` (sibling-wrapper, `<ul>`-reset), `.list-row` (huvud-block med BEM-element)
@@ -294,62 +294,76 @@ Future custom stylelint-plugin kan enforce:
294
294
  Tills sådan plugin finns: visual-coherence är CC-disciplin baserat
295
295
  på denna fil.
296
296
 
297
- ## 13. Topbar-layout-doktrin (alla appar)
297
+ ## 13. Topbar-layout-doktrin (3-column grid)
298
298
 
299
- **Regel:** topbar-elementen positioneras enligt strikt mall:
299
+ **Regel:** topbar är 3-column grid med strikt slot-positioning:
300
300
 
301
- | Position | Element | Användning |
302
- |---|---|---|
303
- | Vänster | `.month-pill`, `.brand-pill`, `.topbar__logo`, `.topbar__back` | Kontext/navigation per vy |
304
- | Höger | `.avatar` (ev. wrappad i `<a href="/jag">`) | Persistent profil-länk |
301
+ | Kolumn | Bredd | Element | Användning |
302
+ |---|---|---|---|
303
+ | 1 (vänster) | auto | `.pwa-avatar` ELLER `.topbar__back` | App-brand-identifierare med hard-refresh-trigger ELLER back-navigation |
304
+ | 2 (center) | 1fr | `.topbar__title`, `.topbar__logo`, `.month-pill` ELLER `.brand-pill` | View-namn ELLER månadsväljare ELLER app-namn-text |
305
+ | 3 (höger) | auto | `.avatar` (ev. wrappad i `<a href="/jag">`) | Persistent user-profile-länk |
305
306
 
306
307
  **CSS-implementation** (paketets `nav.css`):
307
308
 
308
309
  ```css
309
- .topbar > .avatar,
310
- .topbar > a:has(> .avatar) {
311
- margin-left: auto;
310
+ .topbar {
311
+ display: grid;
312
+ grid-template-columns: auto 1fr auto;
313
+ align-items: center;
314
+ gap: var(--space-12);
312
315
  }
316
+
317
+ .topbar > .pwa-avatar, .topbar > .topbar__back { grid-column: 1; justify-self: start; }
318
+ .topbar > .topbar__title, .topbar > .topbar__logo,
319
+ .topbar > .month-pill, .topbar > .brand-pill { grid-column: 2; justify-self: center; }
320
+ .topbar > .avatar, .topbar > a:has(> .avatar) { grid-column: 3; justify-self: end; }
313
321
  ```
314
322
 
315
- Avatar pushas automatiskt högerställd. Övriga element grupperas
316
- vänster med `gap: var(--space-12)`.
323
+ Elementen positioneras automatiskt baserat klass, inte HTML-ordning.
317
324
 
318
325
  **HTML-pattern:**
319
326
 
320
327
  ```html
321
- <!-- Standard topbar med kontext + avatar -->
328
+ <!-- Standard topbar: pwa-avatar + titel + user-avatar -->
322
329
  <div class="topbar">
323
- <span class="brand-pill">Jubb</span> <!-- vänster -->
324
- <a href="/jag"><span class="avatar">CE</span></a> <!-- höger -->
330
+ <button class="pwa-avatar" data-pwa-refresh aria-label="Refresh PWA">J</button>
331
+ <span class="topbar__title">Jobb</span>
332
+ <a href="/jag"><span class="avatar">CE</span></a>
325
333
  </div>
326
334
 
327
- <!-- Topbar med back-knapp + avatar -->
335
+ <!-- Topbar med back-knapp -->
328
336
  <div class="topbar">
329
- <a href="/jobb" class="topbar__back">←</a> <!-- vänster -->
330
- <span class="topbar__logo">Jobbdetalj</span> <!-- center-ish -->
331
- <a href="/jag"><span class="avatar">CE</span></a> <!-- höger -->
337
+ <a href="/jobb" class="topbar__back" aria-label="Tillbaka"><svg.../></a>
338
+ <span class="topbar__title">Jobbdetalj</span>
339
+ <a href="/jag"><span class="avatar">CE</span></a>
332
340
  </div>
333
341
 
334
- <!-- Topbar utan avatar (back-only-vyer som /installningar/X) -->
342
+ <!-- Topbar med month-pill (Ekonom dashboards) -->
335
343
  <div class="topbar">
336
- <a href="/installningar" class="topbar__back">←</a>
337
- <span class="topbar__logo">Vart hushall</span>
344
+ <button class="pwa-avatar" data-pwa-refresh aria-label="Refresh PWA">E</button>
345
+ <span class="month-pill">[‹] Maj 2026 [›]</span>
346
+ <a href="/jag"><span class="avatar">CE</span></a>
338
347
  </div>
339
348
  ```
340
349
 
350
+ **PWA-avatar = hard-refresh-trigger:**
351
+ - Klick → confirm-dialog → rensa Cache Storage + unregister SW + reload
352
+ - Auto-bind via `hard-refresh.js` (inkluderas i `base.html`)
353
+ - Konfigurerbart via `<button class="pwa-avatar" data-pwa-refresh>` eller bara `<button class="pwa-avatar">`
354
+ - Bg: `--accent-soft`, color: `--accent-text`, height 36px (matchar user-avatar)
355
+
341
356
  **Förbjudet:**
342
- - Avatar någon annanstans än i topbar
343
- - Två avatar-element i samma topbar
344
- - Manual flexbox-positioning som strider mot auto-margin-pattern
345
- - Hardkodad `margin-left: auto` avatar i app-domain-CSS (paketet
346
- hanterar det)
357
+ - Avatar någon annanstans än i topbar kolumn 3
358
+ - Två user-avatar-element i samma topbar (en pwa-avatar i kolumn 1 + en user-avatar i kolumn 3 är OK)
359
+ - Manual `margin-left: auto` / `justify-self` på topbar-children i app-domain-CSS (paketet hanterar via grid)
360
+ - Användning av `.pwa-avatar` utanför topbar
347
361
 
348
362
  **Konsekvens:** alla Klodd-appar (Ekonom, Jubb, framtida) får identisk
349
- topbar-layout. Användaren får visuell anchor: "avatar = mitt konto =
350
- alltid uppe höger".
363
+ topbar-layout: PWA-brand vänster, kontext center, user höger. Plus
364
+ universell PWA-refresh-action via tap på vänster avatar.
351
365
 
352
- **Etablerad 2026-05-12.** Lagt till paketets nav.css i samma commit.
366
+ **Etablerad 2026-05-13.** Refaktor från flex till grid samma datum.
353
367
 
354
368
  ## 12. När ändra regler
355
369