@klodd/ds 3.3.0 → 3.4.0
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.
- package/SKILL.md +56 -0
- package/bin/klodd-ds.js +25 -0
- package/bin/precache.js +43 -0
- package/bin/sync.js +33 -0
- package/bin/verify.js +66 -0
- package/css/00-primitives.css +13 -4
- package/css/10-semantic.css +3 -3
- package/css/components/dropdown.css +1 -1
- package/css/components/setting-row.css +1 -1
- package/css/components/tab-bar.css +1 -1
- package/css/components/tooltip.css +1 -1
- package/css/utilities.css +101 -67
- package/package.json +12 -3
- package/references/01-tokens.md +182 -0
- package/references/02-components.md +260 -0
- package/references/03-quality-bar.md +238 -0
- package/references/04-locked-decisions/0001-three-layer-token-architecture.md +41 -0
- package/references/04-locked-decisions/0002-bem-naming.md +37 -0
- package/references/04-locked-decisions/0003-radix-colors-oklch.md +39 -0
- package/references/04-locked-decisions/0004-pixel-numeric-spacing.md +31 -0
- package/references/04-locked-decisions/0005-data-app-theming.md +42 -0
- package/references/04-locked-decisions/0006-mauve-neutral.md +40 -0
- package/references/04-locked-decisions/0007-font-weight-400-500.md +46 -0
- package/references/04-locked-decisions/0008-npm-package-distribution.md +40 -0
- package/references/05-open-decisions/0001-tx-row-to-list-row-migration-CLOSED.md +80 -0
- package/references/05-open-decisions/0002-parallel-classnames-cleanup-CLOSED.md +75 -0
- package/references/05-open-decisions/0003-js-duplicates-migration-CLOSED.md +79 -0
- package/references/05-open-decisions/0004-halsomentorn-legacy-css.md +51 -0
- package/references/05-open-decisions/0005-cat-class-location-CLOSED.md +37 -0
- package/references/05-open-decisions/0006-bar-kind-template-migration-CLOSED.md +75 -0
- package/references/05-open-decisions/0007-ekonom-base-import-gap-CLOSED.md +111 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Token-arkitektur
|
|
2
|
+
|
|
3
|
+
## Tre lager med strikt inkapsling
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
00-primitives.css raa varden (Radix OKLCH-ramper, exakta pixelvarden)
|
|
7
|
+
10-semantic.css komponenter laser HARIFRAN
|
|
8
|
+
apps/<app>.css per-app accent + surface-overrides (5-15 rader)
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Komponenter refererar ALDRIG primitives direkt.** De laser bara semantic
|
|
12
|
+
tokens. Apps/-filerna ar enda platsen som mappar primitives till semantic.
|
|
13
|
+
|
|
14
|
+
### Varfor tre lager
|
|
15
|
+
|
|
16
|
+
- **Primitives ar "implementation detail".** Att byta Radix-skala (eller
|
|
17
|
+
hela fargmodellen) ska inte krava komponent-omskrivning.
|
|
18
|
+
- **Semantic ar bryggan.** Komponentens regel `background: var(--surface-raised)`
|
|
19
|
+
fungerar i alla apps utan andring. Apps/-filen avgor vad `--surface-raised`
|
|
20
|
+
faktiskt blir per-app.
|
|
21
|
+
- **Apps/-overrides racker.** En ny app introduceras genom 5-15 rader CSS,
|
|
22
|
+
inte via komponent-fork.
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## Radix Colors via OKLCH
|
|
26
|
+
|
|
27
|
+
Officiella Radix-skalor (Mauve, Blue, Plum, Violet, Green, Amber, Red)
|
|
28
|
+
i dark-mode-varden, hamtade rakt fran radix-ui.com/colors.
|
|
29
|
+
|
|
30
|
+
### Varfor
|
|
31
|
+
|
|
32
|
+
- **Pre-kalibrerade.** Perceptuellt jamn ljushet steg-for-steg. Hand-tunade
|
|
33
|
+
OKLCH skulle introducera subtila WCAG-kontrast-buggar.
|
|
34
|
+
- **WCAG-verifierade.** Steg 11 har garanterad 4.5:1 mot steg 1-2 (text
|
|
35
|
+
pa app-bakgrund). Steg 12 har 7:1 (high-contrast text).
|
|
36
|
+
- **OKLCH-bakad.** Modern color-mix() i komponenter ger perceptuellt
|
|
37
|
+
korrekt opacity utan handkalibrering.
|
|
38
|
+
- **Dokumenterad rollkarta.** Steg 1-2 = app-bg, 3 = vila, 4 = hover,
|
|
39
|
+
5 = active, 6 = subtil border, 7 = interaktiv border, 8 = stark border,
|
|
40
|
+
9 = solid bakgrund (knappar/badges), 10 = solid hover, 11 = low-contrast
|
|
41
|
+
text, 12 = high-contrast text.
|
|
42
|
+
|
|
43
|
+
### Mauve som neutral
|
|
44
|
+
|
|
45
|
+
`--gray-1` till `--gray-12` mappas till **Radix Mauve Dark**, inte ren gray.
|
|
46
|
+
|
|
47
|
+
**Varfor:** Mauve ar Radix officiella rekommendation som komplement till
|
|
48
|
+
Blue och Plum. Subtle lila-tonad ger varmare bottenton som matchar bagge
|
|
49
|
+
app-accenterna utan att klinga med nagon.
|
|
50
|
+
|
|
51
|
+
**Trade-off:** Mauve passar inte for en framtida gron- eller orange-accent-
|
|
52
|
+
app. Inte planerat - om det blir aktuellt valjer vi neutral utifran den
|
|
53
|
+
appens accent vid den punkten.
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
## Pixel-numerisk spacing/typografi/radius
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
--space-N dar N = exakt antal pixlar (--space-12 = 12px)
|
|
60
|
+
--fs-N dar N = exakt antal pixlar (--fs-14 = 14px)
|
|
61
|
+
--radius-N dar N = exakt antal pixlar (--radius-12 = 12px)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Varfor
|
|
65
|
+
|
|
66
|
+
- **LLM-vanligt.** En CC-session kan resonera om spacing utan att memorera
|
|
67
|
+
en mappnings-tabell (md = 12, lg = 16 etc.).
|
|
68
|
+
- **Designerns Figma-varde matchar token-namnet 1:1.** Mental aritmetik
|
|
69
|
+
elimineras.
|
|
70
|
+
- **Ingen ordinal-explosion.** Inga --space-md vs --space-md-2 vs --space-lg
|
|
71
|
+
vs --space-lg-tight.
|
|
72
|
+
|
|
73
|
+
**Trade-off:** branschstandard ar ordinala namn (Tailwind, Material,
|
|
74
|
+
Bootstrap). Designer som kommer fran de ekosystemen far anpassa sig.
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
## Semantic-token-referens
|
|
78
|
+
|
|
79
|
+
### Surfaces (NAV Aksel-lagermodell - ljusare = hogre i z-stacken)
|
|
80
|
+
|
|
81
|
+
| Token | Anvand for | INTE for |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| `--surface-page` | `<html>`, `<body>`, page-background | Kort, paneler, modaler |
|
|
84
|
+
| `--surface-default` | Sektionsbakgrunder, tab-innehall | Sidans yttersta bg eller upphojda kort |
|
|
85
|
+
| `--surface-raised` | Kort, paneler, sidopaneler | Modaler/popovers |
|
|
86
|
+
| `--surface-overlay` | Dialog-bg, tooltip, context-menu, sheets | Inbaddade kort |
|
|
87
|
+
| `--surface-hover` | `:hover`-bg pa knappar, rader, kort | Statiska ytor |
|
|
88
|
+
| `--surface-active` | `:active`-bg, `.nav-pod.active` | Hover |
|
|
89
|
+
| `--surface-sunken` | Input-bg, code-block | Interaktiva ytor |
|
|
90
|
+
|
|
91
|
+
### Text
|
|
92
|
+
|
|
93
|
+
| Token | Anvand for | INTE for |
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| `--text-default` | Rubriker, knapptext, viktig metadata | Hjalptext, datum, placeholder |
|
|
96
|
+
| `--text-subtle` | Metadata, datum, kompletterande info | Rubriker eller primar info |
|
|
97
|
+
| `--text-muted` | Placeholder, hint, micro-labels | Lasbar info med hog prioritet |
|
|
98
|
+
| `--text-disabled` | Disabled-state pa knappar/inputs | Aktiva element |
|
|
99
|
+
| `--text-on-accent` | Text inuti `--accent-9`-bg | Text pa neutral bg |
|
|
100
|
+
| `--text-on-status` | Text inuti `--bg-success/warning/danger` | Text pa neutral bg |
|
|
101
|
+
|
|
102
|
+
### Borders
|
|
103
|
+
|
|
104
|
+
| Token | Anvand for | INTE for |
|
|
105
|
+
|---|---|---|
|
|
106
|
+
| `--border-subtle` | Tunna dividers, table-row-borders | Interaktiva element |
|
|
107
|
+
| `--border-default` | Kortkanter, input-borders, btn-borders | Fokus-states |
|
|
108
|
+
| `--border-strong` | Hover-state pa inputs, emphasis | Vila-state |
|
|
109
|
+
| `--border-focus` | `:focus-visible` outline | Hover eller statiska borders |
|
|
110
|
+
|
|
111
|
+
### Accent (byts per app via `data-app`)
|
|
112
|
+
|
|
113
|
+
| Token | Anvand for | INTE for |
|
|
114
|
+
|---|---|---|
|
|
115
|
+
| `--accent-soft` | Selected-state-bg, highlight-rader | Knappar |
|
|
116
|
+
| `--accent-moderate` | Hover-state pa `--accent-soft`-ytor | Vila-bg |
|
|
117
|
+
| `--accent-9` | Solid button-bg, badges, accent-bar | Subtila bg |
|
|
118
|
+
| `--accent-10` | `:hover` pa `--accent-9` | Vila-state |
|
|
119
|
+
| `--accent-text` | Lankar, accentfargade etiketter | Text pa --accent-9-bg |
|
|
120
|
+
| `--accent-a1..a12` | Pre-kalibrerade alpha-tints (Radix-stil) | Solid bg |
|
|
121
|
+
|
|
122
|
+
### Status
|
|
123
|
+
|
|
124
|
+
| Token | Anvand for | INTE for |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| `--positive` | Gain-belopp, success-chip-text | Aktion-knappar |
|
|
127
|
+
| `--negative` | Loss-belopp, error-text | Destruktiva aktioner |
|
|
128
|
+
| `--warning` | Warning-banners, score-pill-medium | Errors |
|
|
129
|
+
| `--accent-danger` | Delete-knappar, destructive bekraftelser | Faktiskt negativt belopp |
|
|
130
|
+
| `--bg-success/warning/danger` | Solid status-bg med vit text | Tonad bg (anvand --positive-dim etc) |
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
## Alpha-varianter
|
|
134
|
+
|
|
135
|
+
### Officiella Radix-alpha (v3.0.0+)
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
--accent-a1 --accent-a2 --accent-a3
|
|
139
|
+
--accent-a6 --accent-a8
|
|
140
|
+
--accent-a10 --accent-a12
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Pre-kalibrerade transparency-skalor som overrides per app. Stegs-mappning
|
|
144
|
+
samma som solid-skalan: a1-2 = subtilest, a3 = vila-tint, a6 = subtil
|
|
145
|
+
border-emphasis, a8 = stark border, a10 = solid hover (alpha), a12 = text.
|
|
146
|
+
|
|
147
|
+
### color-mix() for ad-hoc-alpha
|
|
148
|
+
|
|
149
|
+
Om en specific komponent behover en alpha-niva som inte finns i
|
|
150
|
+
Radix-stegen, anvand `color-mix(in oklch, var(--accent-9) 25%, transparent)`.
|
|
151
|
+
|
|
152
|
+
**Varfor color-mix() istallet for hardkodad rgba():**
|
|
153
|
+
- Perceptuellt korrekt over olika fargscalor (oklch interpolerar
|
|
154
|
+
i ljushet, inte rgb-kanaler)
|
|
155
|
+
- Foljer accent-byte automatiskt - en color-mix mot --accent-9 ger Blue
|
|
156
|
+
i Jubb och Plum i Ekonom utan komponent-andring
|
|
157
|
+
- Modern browser-stod (Chrome 111+, Safari 16.4+, Firefox 113+) som
|
|
158
|
+
redan kravs av Radix-ramparna
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
## Component tokens (DRY-mekanism)
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
--bottom-nav-height-semantic
|
|
165
|
+
--bottom-nav-clearance
|
|
166
|
+
--touch-min: 44px
|
|
167
|
+
--card-radius
|
|
168
|
+
--btn-radius
|
|
169
|
+
--input-radius
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Kombination som anvands i 3+ komponenter blir token. Forhindrar drift
|
|
173
|
+
mellan komponenter. Komponenter far referera dessa eftersom de ar
|
|
174
|
+
avledda fran semantic.
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
## Light-mode (forberedd, ej produktion-verifierad)
|
|
178
|
+
|
|
179
|
+
`[data-theme="light"]` i 10-semantic.css overrider surface + text +
|
|
180
|
+
borders. Apps fortsatter att anvanda `data-app` for accent-byte oavsett
|
|
181
|
+
tema. Status: forberedd, inte aktivt produktion-verifierad - se
|
|
182
|
+
`05-open-decisions/` om aktualiseras.
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# Komponentkatalog
|
|
2
|
+
|
|
3
|
+
33 komponenter i `@klodd/ds@3.x`. Alla refererar bara semantic tokens -
|
|
4
|
+
inga primitives. BEM-konvention (block__element--modifier).
|
|
5
|
+
|
|
6
|
+
## Grundkomponenter
|
|
7
|
+
|
|
8
|
+
### button (`button.css`)
|
|
9
|
+
- **Klasser:** `.btn`, `.btn--primary/-secondary/-ghost/-danger`, `.btn--sm/-lg/-icon/-circle`, `.btn--loading`
|
|
10
|
+
- **Anvand:** alla aktioner med tap-target >=44px
|
|
11
|
+
- **INTE:** Cirkel-link i topbar (anvand `.btn--icon.btn--circle`)
|
|
12
|
+
- **Tokens:** `--surface-default/-hover/-active`, `--text-default/-on-accent`, `--border-default/-focus`, `--accent-9/-10`, `--bg-danger`, `--touch-min`
|
|
13
|
+
|
|
14
|
+
### input (`input.css`)
|
|
15
|
+
- **Klasser:** `.input`, `.textarea`, `.select`, `.input-group__label/__hint/__error`, `.input-icon`
|
|
16
|
+
- **Anvand:** form-falt med 17px font-size (anti iOS auto-zoom)
|
|
17
|
+
- **INTE:** Inline-edit-pattern (anvand `.inline-edit__input`)
|
|
18
|
+
- **Tokens:** `--surface-sunken/-default`, `--accent-9`, `--accent-a3` (focus-ring), `--bg-danger` (error-state)
|
|
19
|
+
|
|
20
|
+
### badge (`badge.css`)
|
|
21
|
+
- **Klasser:** `.badge`, `.badge--success/-warning/-danger/-accent`, `.score-pill`, `.score-pill--strong/-medium/-low`
|
|
22
|
+
- **Anvand:** Status-pills (statiska)
|
|
23
|
+
- **INTE:** Klickbara chips (anvand `.chip`)
|
|
24
|
+
- **Tokens:** `--positive/-dim/-border`, `--warning/-dim/-border`, `--bg-danger`, `--accent-text/-a2/-a6`
|
|
25
|
+
|
|
26
|
+
### card (`card.css`)
|
|
27
|
+
- **Klasser:** `.card`, `.card--interactive/-flush`, `.card-header/-body/-footer/-divider`
|
|
28
|
+
- **Anvand:** Standardcontainer for paneler. `--interactive` ger hover/press-feedback
|
|
29
|
+
- **INTE:** Settings-hub-kort (anvand `.hub-card`)
|
|
30
|
+
- **Tokens:** `--surface-raised/-overlay/-hover`, `--border-subtle/-default/-focus`
|
|
31
|
+
|
|
32
|
+
### nav (`nav.css`)
|
|
33
|
+
- **Klasser:** `.bottom-nav`, `.bottom-nav-item.active`, `.topbar`, `.topbar-back/-title/-action`, `.tab-bar`, `.tab.active`
|
|
34
|
+
- **Anvand:** Mobile bottom-nav (fixed), in-flow topbar, segmented tabs
|
|
35
|
+
- **INTE:** Generisk navigations-meny (anvand `.dropdown`)
|
|
36
|
+
- **Tokens:** `--surface-default`, `--text-muted/-default`, `--accent-text` (active), `--border-subtle/-focus`, `--touch-min`, `--safe-bottom`
|
|
37
|
+
|
|
38
|
+
### feedback (`feedback.css`)
|
|
39
|
+
- **Klasser:** `.toast`, `.toast--success/-error/-warning`, `.empty-state`, `.skeleton`, `.skeleton--text/-circle/-card`, `.spinner`
|
|
40
|
+
- **Anvand:** Transient feedback + loading-states
|
|
41
|
+
- **INTE:** Inline error-meddelanden (anvand `.input-group__error`)
|
|
42
|
+
- **Tokens:** `--surface-overlay`, `--bg-success/-warning/-danger`, `--text-on-status`, `--shadow-float`. Respekterar `prefers-reduced-motion`.
|
|
43
|
+
|
|
44
|
+
### overlay (`overlay.css`)
|
|
45
|
+
- **Klasser:** `.dialog`, `.sheet`, `.dialog-backdrop` (med cursor: pointer), `.dialog-header/-body/-footer`, `.sheet-handle/-body/-divider`
|
|
46
|
+
- **Anvand:** Native `<dialog>` (centrerad modal) eller `<dialog class="sheet">` (bottom-attached)
|
|
47
|
+
- **INTE:** Tooltip eller dropdown (egna komponenter)
|
|
48
|
+
- **Tokens:** `--surface-raised/-overlay`, `--border-subtle`, `--shadow-float`, `--z-overlay`, `--safe-bottom`
|
|
49
|
+
|
|
50
|
+
### icon (`icon.css`)
|
|
51
|
+
- **Klasser:** `.icon`, `.icon--xs/-sm/-md/-lg/-xl`, `.icon-custom`
|
|
52
|
+
- **Anvand:** Lucide via CDN (cdn.jsdelivr.net) ELLER inline-SVG via `.icon-custom`
|
|
53
|
+
- **INTE:** Inline `style="width:Xpx"` pa ikoner (anvand size-modifier)
|
|
54
|
+
- **Tokens:** `currentColor` - parent-element styr fargen
|
|
55
|
+
|
|
56
|
+
### hero-roll (`hero-roll.css`)
|
|
57
|
+
- **Klasser:** `.hero-amount[data-animate-roll]`, `.hero-digit-track`
|
|
58
|
+
- **Anvand:** Display-siffer-animation pa hero-vyer (kodlas-rullning)
|
|
59
|
+
- **INTE:** Vanliga numeriska varden (anvand `.hero__amount` utan data-animate-roll)
|
|
60
|
+
- **Tokens:** `--text-default`, `--lh-tight`, `--ls-tightest`, `--fs-80`. **Undantag:** `font-weight: 600` (display-undantaget fran 400/500-policyn).
|
|
61
|
+
|
|
62
|
+
### divider (`divider.css`)
|
|
63
|
+
- **Klasser:** `.divider`, `.divider--vertical/-strong`
|
|
64
|
+
- **Anvand:** Horisontell eller vertikal separator
|
|
65
|
+
- **INTE:** Visuell separator inom card (anvand `.card-divider`)
|
|
66
|
+
- **Tokens:** `--border-subtle/-default`
|
|
67
|
+
|
|
68
|
+
### progress (`progress.css`)
|
|
69
|
+
- **Klasser:** `.progress`, `.progress-bar`, `.progress-bar--success/-warning/-danger`
|
|
70
|
+
- **Anvand:** Linjar progress med data-bar-width-pattern (CSP-safe via bar-styles.js)
|
|
71
|
+
- **INTE:** Progress med text-overlay (eget komposit-pattern)
|
|
72
|
+
- **Tokens:** `--surface-raised`, `--accent-9`, `--bg-success/-warning/-danger`. Respekterar `prefers-reduced-motion`.
|
|
73
|
+
|
|
74
|
+
### tooltip (`tooltip.css`)
|
|
75
|
+
- **Klasser:** `.tooltip-wrapper`, `.tooltip`
|
|
76
|
+
- **Anvand:** Pure-CSS tooltip via `:hover/:focus-within` pa wrappern
|
|
77
|
+
- **INTE:** Long-content tooltips (anvand `.dialog`)
|
|
78
|
+
- **Tokens:** `--surface-overlay`, `--text-default`, `--border-default`, `--z-tooltip`
|
|
79
|
+
|
|
80
|
+
### dropdown (`dropdown.css`)
|
|
81
|
+
- **Klasser:** `.dropdown.is-open`, `.dropdown-menu`, `.dropdown-item`, `.dropdown-item--danger`, `.dropdown-divider`
|
|
82
|
+
- **Anvand:** Kontextuell meny (kebab/more-actions). JS togglar `.is-open`
|
|
83
|
+
- **INTE:** Permanent visible navigation (anvand `.nav` eller `.tab-bar`)
|
|
84
|
+
- **Tokens:** `--surface-overlay/-hover/-active`, `--text-default`, `--border-default/-subtle/-focus`, `--bg-danger` (item--danger), `--z-dropdown`
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
## Layout-komponenter (v3.0.0+)
|
|
88
|
+
|
|
89
|
+
### banner (`banner.css`)
|
|
90
|
+
- **Klasser:** `.banner`, `.banner--hero/-accent/-positive/-negative/-warning`, `.banner__title/__sub/__content`
|
|
91
|
+
- **Anvand:** Bred informations-rad i flode (top-of-page eller mellan sektioner)
|
|
92
|
+
- **INTE:** Toast-notifikation (anvand `.toast`)
|
|
93
|
+
|
|
94
|
+
### panel (`panel.css`)
|
|
95
|
+
- **Klasser:** `.panel`, `.panel--info/-info-warning/-danger/-attention`, `.panel__title/__title-row/__title-meta/__title-link/__step-row/__step-badge`
|
|
96
|
+
- **Anvand:** Sektion med ramad styling och titel
|
|
97
|
+
- **INTE:** Klickbart kort (anvand `.card--interactive`)
|
|
98
|
+
|
|
99
|
+
### hub-card (`hub-card.css`)
|
|
100
|
+
- **Klasser:** `.hub-card`, `.hub-card__icon/__text/__title/__subtitle/__chev`, `.hub-list`, `.hub-category`
|
|
101
|
+
- **Anvand:** Settings-hub navigation (kort-listor som lankar till sub-sidor)
|
|
102
|
+
- **INTE:** Generic listrader (anvand `.list-row`)
|
|
103
|
+
|
|
104
|
+
### stat (`stat.css`)
|
|
105
|
+
- **Klasser:** `.stat-grid`, `.stat-grid--single`, `.stat-card`, `.stat-card__value/__label/__unit/__sub`, `.stat-card__value--positive/-negative/-accent/-warning`
|
|
106
|
+
- **Anvand:** Sma kort med stor siffra + label (read-only metric-display)
|
|
107
|
+
- **INTE:** Editerbart varde (anvand `.setting-row`)
|
|
108
|
+
|
|
109
|
+
### form (`form.css`)
|
|
110
|
+
- **Klasser:** `.form-card`, `.form-section`, `.form-section__title`, `.form-group`, `.form-group__label`, `.form-hint`, `.form-row`, `.form-row--inline`
|
|
111
|
+
- **Anvand:** Wrapper-strukturen for formularet
|
|
112
|
+
- **INTE:** Inputs sjalva (egen `.input`)
|
|
113
|
+
|
|
114
|
+
### setting-row (`setting-row.css`)
|
|
115
|
+
- **Klasser:** `.setting-list`, `.setting-row`, `.setting-row--static/-danger`, `.setting-row__text/__label/__sub/__value/__amount/__chevron/__avatar/__pill`, `.setting-toggle/__track/__thumb`
|
|
116
|
+
- **Anvand:** Tap-to-edit-rad som triggar bottom-sheet
|
|
117
|
+
- **INTE:** Klickbart kort med rich content (anvand `.hub-card`)
|
|
118
|
+
|
|
119
|
+
### collapsible (`collapsible.css`)
|
|
120
|
+
- **Klasser:** `.collapsible-card`, `.collapsible__header/__header-text/__chev/__body`, `[data-expanded]`
|
|
121
|
+
- **Anvand:** Panel som expanderar pa klick. JS togglar `data-expanded`
|
|
122
|
+
- **INTE:** Modal-content (anvand `.dialog` eller `.sheet`)
|
|
123
|
+
|
|
124
|
+
### hbar (`hbar.css`)
|
|
125
|
+
- **Klasser:** `.hbar`, `.hbar__item/__track/__fill/__label/__value`, `.hbar__fill--positive/-warning/-negative`
|
|
126
|
+
- **Anvand:** Generisk horisontell bar med label + value + track + fill
|
|
127
|
+
- **INTE:** Status-progress (anvand `.progress`)
|
|
128
|
+
|
|
129
|
+
### split-bar (`split-bar.css`)
|
|
130
|
+
- **Klasser:** `.split-bar`, `.split-bar__segment`, `.split-bar__segment--primary/-secondary/-positive/-negative/-warning`, `.split-bar__label/__labels`
|
|
131
|
+
- **Anvand:** Flersegment-bar for cost-split, debt-vs-equity m.fl.
|
|
132
|
+
- **INTE:** Single-bar-progress (anvand `.hbar`)
|
|
133
|
+
|
|
134
|
+
### hero (`hero.css`)
|
|
135
|
+
- **Klasser:** `.hero`, `.hero__heading/__amount/__amount--card/__amount--fluid/__amount-row/__label/__label--muted/__meta/__actions`
|
|
136
|
+
- **Anvand:** Stora display-rubriker (80px-skala default, 40px card)
|
|
137
|
+
- **INTE:** Vanlig `<h1>` (anvand `.heading-1`)
|
|
138
|
+
|
|
139
|
+
### chip (`chip.css`)
|
|
140
|
+
- **Klasser:** `.chip`, `.chip--accent/-positive/-negative/-warning/-faint`, `.chip-list`, `.chip-list__item/__delete/__add`, `.brand-pill`, `.month-pill`, `.score-pill`, `.install-chip`
|
|
141
|
+
- **Anvand:** Kort-format pills med dot-prefix (status, kategori, count)
|
|
142
|
+
- **INTE:** Form-inputs (anvand `.input`)
|
|
143
|
+
|
|
144
|
+
### avatar (`avatar.css`)
|
|
145
|
+
- **Klasser:** `.avatar`, `.avatar--sm/-lg`
|
|
146
|
+
- **Anvand:** Cirkular initial-avatar med accent-gradient
|
|
147
|
+
- **INTE:** Foto-avatar (overlapp via custom regel)
|
|
148
|
+
|
|
149
|
+
### list-row (`list-row.css`)
|
|
150
|
+
- **Klasser:** `.list`, `.list-row`, `.list-row--excluded/-pending/-clickable`, `.list-row__icon/__body/__desc/__meta/__date/__amount`, `.list-row__amount--positive/-negative`
|
|
151
|
+
- **Anvand:** Generisk listrad med ikon + body + amount (transaktioner, audit-log, jobs)
|
|
152
|
+
- **INTE:** Settings-rad (anvand `.setting-row`)
|
|
153
|
+
|
|
154
|
+
### table (`table.css`)
|
|
155
|
+
- **Klasser:** `.table`, `.table .num`
|
|
156
|
+
- **Anvand:** Tabell med tabular-nums-stod
|
|
157
|
+
- **INTE:** Layout-grid (anvand CSS Grid utility)
|
|
158
|
+
|
|
159
|
+
### auth (`auth.css`)
|
|
160
|
+
- **Klasser:** `.auth-container`, `.auth-container__title/__subtitle`
|
|
161
|
+
- **Anvand:** Centrerad layout for inloggning + onboarding
|
|
162
|
+
- **INTE:** Settings-vyer
|
|
163
|
+
|
|
164
|
+
### swipe-stack (`swipe-stack.css`)
|
|
165
|
+
- **Klasser:** `.swipe-stack`, `.swipe-card`, `.swipe-card--back/-gone`, `.swipe-card__header/__title/__body/__footer`, `.swipe-decision-overlay`, `.swipe-decision-overlay--save/-dismiss/-visible`, `.swipe-actions`, `.swipe-action-btn`, `.swipe-action-btn--save/-dismiss`, `.swipe-meta`, `.swipe-meta-sep`, `.swipe-progress`, `.swipe-empty`, `.swipe-hint`
|
|
166
|
+
- **Anvand:** Tinder-stil swipe-stack med drag-physics
|
|
167
|
+
- **INTE:** Card-galleri (anvand `.card-grid`)
|
|
168
|
+
|
|
169
|
+
### inline-edit (`inline-edit.css`)
|
|
170
|
+
- **Klasser:** `.inline-edit`, `.inline-edit__text/__btn/__form/__input`
|
|
171
|
+
- **Anvand:** Inline-edit av profil-namn, etiketter (pencil-knapp togglar form)
|
|
172
|
+
- **INTE:** Form-fields (anvand `.form-group`)
|
|
173
|
+
- **Special:** `.inline-edit__form[hidden]` har explicit `display: none` (paritet med globalt `[hidden]`-stod i base/pwa.css)
|
|
174
|
+
|
|
175
|
+
### upload-spinner (`upload-spinner.css`)
|
|
176
|
+
- **Klasser:** `.upload-spinner-overlay`, `.upload-spinner-overlay.is-visible`, `.upload-spinner`, `.upload-spinner-overlay__label/__hint`
|
|
177
|
+
- **Anvand:** Viewport-overlay for langa async-operationer (OCR, AI-anrop)
|
|
178
|
+
- **INTE:** Inline-spinner (anvand `.spinner`)
|
|
179
|
+
|
|
180
|
+
### tab-bar (`tab-bar.css`)
|
|
181
|
+
- **Klasser:** `.tab-bar`, `.tab-bar__item.is-active`
|
|
182
|
+
- **Anvand:** Inline tab-grupp for format-val (CSV/Avi etc.)
|
|
183
|
+
- **INTE:** Bottom-nav (anvand `.bottom-nav`)
|
|
184
|
+
|
|
185
|
+
### colored-row (`colored-row.css`) - v3.1.0
|
|
186
|
+
- **Klasser:** `.colored-row`, `.colored-row--sm/-lg`
|
|
187
|
+
- **Anvand:** Kategoriserade rader, fargkodade listor, statusrader -
|
|
188
|
+
med vansterkant fran `--row-accent`-token (default: `--border-subtle`)
|
|
189
|
+
- **INTE:** Rader utan fargkodning (anvand `.list-row` eller plain `.tx-row`)
|
|
190
|
+
- **Tokens:** `--row-accent` (sattes av app-bindning), `--border-subtle` (default)
|
|
191
|
+
- **Pattern:** Se "Kategori-monstret" nedan
|
|
192
|
+
|
|
193
|
+
### colored-bar (`colored-bar.css`) - v3.1.0
|
|
194
|
+
- **Klasser:** `.colored-bar`, `.colored-bar--sm/-md/-lg`, `.colored-bar--vertical`
|
|
195
|
+
- **Anvand:** Budget-staplar, kategori-staplar, progress med semantisk
|
|
196
|
+
farg fran `--bar-accent`-token (default: `--accent-9`)
|
|
197
|
+
- **INTE:** Generisk progress utan kategori (anvand `.progress`)
|
|
198
|
+
- **Tokens:** `--bar-accent` (sattes av app-bindning), `--accent-9` (default)
|
|
199
|
+
- **Pattern:** Se "Kategori-monstret" nedan
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
## Kategori-monstret
|
|
203
|
+
|
|
204
|
+
Paketet ager komponenten, appen ager kategorin. Token-definition och
|
|
205
|
+
token-bindning ar appens ansvar - paketet vet ingenting om kategorier.
|
|
206
|
+
|
|
207
|
+
### I paketet (@klodd/ds)
|
|
208
|
+
|
|
209
|
+
```css
|
|
210
|
+
.colored-row {
|
|
211
|
+
border-left: 3px solid var(--row-accent, var(--border-subtle));
|
|
212
|
+
}
|
|
213
|
+
.colored-bar {
|
|
214
|
+
background: var(--bar-accent, var(--accent-9));
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### I app-domain-filen (t.ex. ds/ekonom-domain.css)
|
|
219
|
+
|
|
220
|
+
Definiera tokens + bindningar:
|
|
221
|
+
|
|
222
|
+
```css
|
|
223
|
+
/* Token-definition - VARDEN som ar app-specifika */
|
|
224
|
+
:root {
|
|
225
|
+
--my-category: #A78BFA;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/* Token-bindning - kopplar app-tokens till paketets komponenter */
|
|
229
|
+
.my-cat-row { --row-accent: var(--my-category); }
|
|
230
|
+
.my-cat-bar { --bar-accent: var(--my-category); }
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### I template
|
|
234
|
+
|
|
235
|
+
```html
|
|
236
|
+
<div class="colored-row my-cat-row">...</div>
|
|
237
|
+
<div class="colored-bar my-cat-bar"></div>
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Resultat
|
|
241
|
+
|
|
242
|
+
- Paketets `.colored-row` ar generic och ovetande om kategorier
|
|
243
|
+
- App:s `.my-cat-row` sattes som wrapper som overrider `--row-accent`
|
|
244
|
+
- Element-baserade `style="--row-accent: ..."` kan ocksa anvandas men
|
|
245
|
+
app-domain-CSS-bindningar ar att foredra (data-attribute-konvention
|
|
246
|
+
+ lasbar template)
|
|
247
|
+
|
|
248
|
+
Jubb, Ekonom, framtida appar foljer samma monster med sina egna tokens.
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
## Anti-patterns
|
|
252
|
+
|
|
253
|
+
- **`color: #FFF` i komponent-CSS.** Anvand `var(--text-on-accent)` eller `oklch(0.98 0 0)` som primitiv om absolut nodvandig.
|
|
254
|
+
- **`background: rgba(...)`** istallet for `color-mix(in oklch, var(--accent-9) 20%, transparent)` eller en `--accent-aN`-token.
|
|
255
|
+
- **`padding: 13px`** istallet for `--space-12` eller `--space-14` (narmaste pixel-numerisk).
|
|
256
|
+
- **`font-size: 16px`** utan token. Inputs ska ha `--fs-17` (= 17px) for anti-iOS-zoom.
|
|
257
|
+
- **Inline `style="width: 50%"` pa progress-bar.** Anvand `data-bar-width="50%"` + `bar-styles.js` (CSP-safe).
|
|
258
|
+
- **`var(--gray-9)` i komponent-CSS.** Komponenter laser bara semantic.
|
|
259
|
+
- **Egen .button-style.** Anvand `.btn` med modifier istallet.
|
|
260
|
+
- **`font-weight: 700`.** Anvand `--fw-medium` (500). Display-siffror ar dokumenterat undantag.
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# Kvalitetskrav (icke-forhandlingsbara)
|
|
2
|
+
|
|
3
|
+
Lista over absoluta krav som inte ska brytas. Varje krav har konkret
|
|
4
|
+
"hur man foljer" + rationale.
|
|
5
|
+
|
|
6
|
+
## 1. BEM-konvention pa alla CSS-klasser
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
.block
|
|
10
|
+
.block__element
|
|
11
|
+
.block--modifier
|
|
12
|
+
.block__element--modifier
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**Hur man foljer:**
|
|
16
|
+
- Block: substantiv (`.card`, `.banner`, `.hub-card`)
|
|
17
|
+
- Element: barn-del med `__` (`.card__title`, `.banner__content`)
|
|
18
|
+
- Modifier: variant med `--` (`.btn--primary`, `.banner--warning`)
|
|
19
|
+
- INGA hyphen-flat-namn (`.btn-primary` ar fel - ska vara `.btn--primary`)
|
|
20
|
+
|
|
21
|
+
**Varfor:**
|
|
22
|
+
- Specificity-balans: alla klasser ar 0,1,0 (en klass) - ingen
|
|
23
|
+
cascade-overraskning
|
|
24
|
+
- Lasbart agentvanlig: en CC-session kan resonera om struktur utan
|
|
25
|
+
att lasa CSS:en
|
|
26
|
+
- Etablerad branschstandard - manga developer-erfarenheter
|
|
27
|
+
- Forhindrar "magic specificity" via descendant-selektorer
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## 2. WCAG AA minimum pa alla interaktiva komponenter
|
|
31
|
+
|
|
32
|
+
**Konkreta krav:**
|
|
33
|
+
- **Text-kontrast 4.5:1** mot bakgrund (Radix steg 11 mot steg 1-2 ar
|
|
34
|
+
pre-verifierad)
|
|
35
|
+
- **Tap-target 44x44px** minimum (`--touch-min` = 44px)
|
|
36
|
+
- **Synlig fokus-ring** pa alla interaktiva element via `:focus-visible`
|
|
37
|
+
(`outline: 2px solid var(--border-focus); outline-offset: 2px`)
|
|
38
|
+
- **`prefers-reduced-motion`** respekteras pa alla animationer
|
|
39
|
+
- **`prefers-contrast: more`** stegrar borders och muted-text 1-2 steg
|
|
40
|
+
(implementerat i 10-semantic.css)
|
|
41
|
+
- **`hidden`-attribut respekteras** via global `[hidden] { display: none
|
|
42
|
+
!important }` i base/pwa.css
|
|
43
|
+
- **ARIA-roles** pa alla interaktiva non-button-element (.dropdown-item
|
|
44
|
+
ska ha role="menuitem", .swipe-card ska ha role="article")
|
|
45
|
+
|
|
46
|
+
**Varfor:**
|
|
47
|
+
- Lagkrav i EU (Tillgangs-direktivet, EAA fran 2025)
|
|
48
|
+
- Bredde tillganglighet ar PWA-default - inte feature i Klodd-apparna
|
|
49
|
+
som anvander mobilen i bil/buss/svaga ljusforhallanden
|
|
50
|
+
- Radix Colors ar pre-WCAG-kalibrerade - att bryta mot dem kraver
|
|
51
|
+
medvetet val + ny dokumentation
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## 3. Inga hardkodade farg-, spacing- eller fs-varden i komponent-CSS
|
|
55
|
+
|
|
56
|
+
**Hur man foljer:**
|
|
57
|
+
- ALDRIG `color: #FF0000` - anvand `var(--negative)` eller `var(--red-9)`
|
|
58
|
+
- ALDRIG `padding: 13px` - anvand `var(--space-12)` eller `var(--space-14)`
|
|
59
|
+
- ALDRIG `font-size: 16px` direkt - anvand `var(--fs-17)` for inputs
|
|
60
|
+
eller anvand klasser som `.text-base`
|
|
61
|
+
- ALDRIG `border-radius: 10px` - anvand `var(--radius-10)`
|
|
62
|
+
- ALDRIG `rgba(0, 0, 0, 0.4)` - anvand `color-mix(in oklch, ...)` eller
|
|
63
|
+
semantic alpha-token
|
|
64
|
+
|
|
65
|
+
**Varfor:**
|
|
66
|
+
- Single source of truth: andring i 00-primitives.css landar omedelbart
|
|
67
|
+
i alla komponenter
|
|
68
|
+
- App-byte fungerar: hardkodad #0090ff i en komponent skulle ge fel farg
|
|
69
|
+
for Ekonom (som har Plum-accent)
|
|
70
|
+
- Token-search ar viktigare an pixel-precision: designern andrar `--fs-14`
|
|
71
|
+
fran 14px till 15px i en sprint, alla komponenter foljer med
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
## 4. Pixel-numerisk spacing/typografi/radius
|
|
75
|
+
|
|
76
|
+
**Hur man foljer:**
|
|
77
|
+
- `--space-N` dar N = exakt antal pixlar
|
|
78
|
+
- Tillgangliga steg: 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32,
|
|
79
|
+
40, 48, 56, 64, 80
|
|
80
|
+
- Vanliga val: 4-8 (tight), 10-14 (komponent-internt), 16-20 (kort-padding),
|
|
81
|
+
24-32 (sektioner), 40+ (hero-spacing)
|
|
82
|
+
- Behover du `--space-15`? Fragstall det forst - oftast funkar 14 eller 16.
|
|
83
|
+
Lagga till nya steg kraver token-uppdatering + dokumentation
|
|
84
|
+
|
|
85
|
+
**Varfor:**
|
|
86
|
+
- LLM-vanligt: `--space-12 = 12px` ar trivialt att resonera om
|
|
87
|
+
- Designerns Figma-varde matchar token-namnet 1:1 utan mappning
|
|
88
|
+
- Forhindrar ordinal-explosion (md/lg/xl/2xl/3xl-stelhet)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
## 5. Font-weight 400 eller 500 - inga undantag utan dokumentation
|
|
92
|
+
|
|
93
|
+
**Hur man foljer:**
|
|
94
|
+
- `--fw-regular: 400` for vanlig text
|
|
95
|
+
- `--fw-medium: 500` for emphasis (knapptext, etiketter, rubriker)
|
|
96
|
+
- INGA 600 eller 700 utom dokumenterade undantag
|
|
97
|
+
- Display-siffror (`.hero-amount`) har `font-weight: 600` - dokumenterat
|
|
98
|
+
i `components/hero-roll.css` med kommentar
|
|
99
|
+
|
|
100
|
+
**Varfor:**
|
|
101
|
+
- Mer val skapar inkonsistens: en designer valjer 600 nagon gang, en
|
|
102
|
+
annan 700, snart finns alla varianter och inget mover hierarki
|
|
103
|
+
- Tva-steg ger tillrackligt med visual hierarchy: medium ar emphasis,
|
|
104
|
+
regular ar default
|
|
105
|
+
- Display-undantaget ar OK eftersom 80px-display behover visual tyngd
|
|
106
|
+
som UI-text inte gor
|
|
107
|
+
|
|
108
|
+
**Trade-off:**
|
|
109
|
+
- Bold-text-effekt ar narvarande pa display-skala. Vid framtida
|
|
110
|
+
feature-arbete dar bold-text behovs (banners-hero?), maste den
|
|
111
|
+
motiveras + dokumenteras.
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
## 6. color-mix() istallet for hardkodade alpha-varden
|
|
115
|
+
|
|
116
|
+
**Hur man foljer:**
|
|
117
|
+
```css
|
|
118
|
+
/* Korrekt */
|
|
119
|
+
background: color-mix(in oklch, var(--accent-9) 20%, transparent);
|
|
120
|
+
|
|
121
|
+
/* Eller anvand semantic alpha-token */
|
|
122
|
+
background: var(--accent-a3);
|
|
123
|
+
|
|
124
|
+
/* Felaktigt */
|
|
125
|
+
background: rgba(0, 144, 255, 0.2); /* hardkodad rgb */
|
|
126
|
+
background: rgba(var(--accent-rgb), 0.2); /* token-baserad rgb */
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Varfor:**
|
|
130
|
+
- color-mix(in oklch, ...) ar perceptuellt korrekt - rgb-alpha ger
|
|
131
|
+
olika visuell intensitet beroende pa fargen
|
|
132
|
+
- Foljer accent-byte automatiskt: en color-mix mot --accent-9 ger Blue
|
|
133
|
+
i Jubb och Plum i Ekonom utan komponent-andring
|
|
134
|
+
- Modern browser-stod (Chrome 111+, Safari 16.4+, Firefox 113+) som
|
|
135
|
+
redan kravs av Radix-OKLCH-ramparna - ingen polyfill behovs
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
## 7. Per-app-overrides bara i apps/<app>.css - aldrig i komponent-CSS
|
|
139
|
+
|
|
140
|
+
**Hur man foljer:**
|
|
141
|
+
- Ny app introduceras genom 5-15 rader CSS i `apps/foo.css`
|
|
142
|
+
- Komponenter forandras INTE for ny app
|
|
143
|
+
- Per-app-overrides ar bara accent-tokens (+ ev. surface-tokens om appen
|
|
144
|
+
vill avvika fran neutral-default)
|
|
145
|
+
|
|
146
|
+
**Varfor:**
|
|
147
|
+
- Komponenten ar source of truth - en regel galler i alla apps
|
|
148
|
+
- Driften mellan apparna minimeras
|
|
149
|
+
- Ny app ar trivial att introducera - INTE en re-fork av komponenter
|
|
150
|
+
- App-byten i samma DOM (om relevant) blir trivialt - bara `data-app`-flip
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
## 8. Komponent-states: alla 4 states pa interaktiva komponenter
|
|
154
|
+
|
|
155
|
+
**Hur man foljer:**
|
|
156
|
+
Varje interaktiv komponent SKA ha:
|
|
157
|
+
- `:hover` - bakgrund eller fargandring (anvand `--surface-hover` eller `--accent-10`)
|
|
158
|
+
- `:active` - press-feedback (anvand `--surface-active` plus `transform: scale(0.97)`)
|
|
159
|
+
- `:focus-visible` - tangentbordsfokusring (`outline: 2px solid var(--border-focus); outline-offset: 2px`)
|
|
160
|
+
- `:disabled` eller `[disabled]` - opacity 0.5 + cursor: not-allowed + pointer-events: none
|
|
161
|
+
- Loading-state om relevant (sa knapp inte kan dubbel-klickas)
|
|
162
|
+
|
|
163
|
+
**Varfor:**
|
|
164
|
+
- Tangentbordsanvandare ser inte hover - de behover focus-visible
|
|
165
|
+
- Touch-anvandare maste fa visuell feedback vid press
|
|
166
|
+
- Disabled-state ska var visuellt och funktionellt blockerande
|
|
167
|
+
- Konsekvens utover komponentbiblioteket - en knapp i Jubb beter sig
|
|
168
|
+
identiskt som en knapp i Ekonom
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
## 9. CSP-saker JS-driven styling
|
|
172
|
+
|
|
173
|
+
**Hur man foljer:**
|
|
174
|
+
- Inline `style="width: 50%"` blockeras av CSP (style-src utan unsafe-inline)
|
|
175
|
+
- Anvand `data-bar-width="50%"` + `bar-styles.js` som applicerar via
|
|
176
|
+
JS-runtime (`element.style.width = el.dataset.barWidth`)
|
|
177
|
+
- JS-runtime-styling ar tillaten av CSP - bara HTML-parser-styling ar
|
|
178
|
+
blockerad
|
|
179
|
+
|
|
180
|
+
**Varfor:**
|
|
181
|
+
- Mozilla Observatory A+ kraver inga `unsafe-inline` i style-src
|
|
182
|
+
- Inline-styles ar svara att audit:a (kommandot `git grep style=` borde
|
|
183
|
+
hitta noll matches i template-filer)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
## 10. En enda skugga tillaten (DNB Eufemia "arlig materialitet")
|
|
187
|
+
|
|
188
|
+
**Hur man foljer:**
|
|
189
|
+
- ENDAST `var(--shadow-card)` i hela systemet
|
|
190
|
+
- Aldrig `--shadow-resting/-raised/-floating` eller liknande hierarkisk
|
|
191
|
+
skugg-skala
|
|
192
|
+
- Aldrig hardkodade `box-shadow: 0 X Y rgba(...)`
|
|
193
|
+
- Hierarki uppnas via surface-tokens (`--surface-page` < `-default` <
|
|
194
|
+
`-raised` < `-overlay`), INTE via olika skugg-djupa
|
|
195
|
+
|
|
196
|
+
**Varfor:**
|
|
197
|
+
- Dark-mode-first design: skuggor syns inte tydligt mot mork bakgrund -
|
|
198
|
+
ljushet-hierarki ar mer effektiv
|
|
199
|
+
- DNB Eufemias "arliga materialitet": skuggor som bara existerar nar
|
|
200
|
+
fysiskt motiverat (kort som svarar mot bakgrund). Inga fake gradient-
|
|
201
|
+
skuggor som imiterar djup som inte finns.
|
|
202
|
+
- Forhindrar skugg-explosion: en designer valjer 0.5 nagon gang, en
|
|
203
|
+
annan 0.7, snart finns alla varianter och visuellt sprak ar splittrat
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
## 11. Inter font + Linear-stack
|
|
207
|
+
|
|
208
|
+
**Hur man foljer:**
|
|
209
|
+
- Anvand `var(--font-sans)` overallt - ALDRIG specifika font-family-
|
|
210
|
+
stackar i komponenter
|
|
211
|
+
- Default-stack ar `Inter, SF Pro Display, -apple-system, system-ui, ...`
|
|
212
|
+
(Linear-konventionen)
|
|
213
|
+
- Inter laddas via Google Fonts i `base/typography.css` om enheten
|
|
214
|
+
saknar den lokalt
|
|
215
|
+
- Numeriska data: `font-variant-numeric: tabular-nums` for kolumn-
|
|
216
|
+
justering (siffror packar identiskt)
|
|
217
|
+
|
|
218
|
+
**Varfor:**
|
|
219
|
+
- Inter ar designad for UI-text och fungerar konsekvent over alla
|
|
220
|
+
storlekar
|
|
221
|
+
- SF Pro Display ar Apples designspraket (synkad UX-feeling pa iOS)
|
|
222
|
+
- system-ui som universell fallback for nischade plattformar
|
|
223
|
+
- Linear, Vercel och liknande modern SaaS anvander samma stack
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
## 12. Audit-aliaser halls levande tills hela migration genomford
|
|
227
|
+
|
|
228
|
+
**Hur man foljer:**
|
|
229
|
+
- Gamla token-namn (--text-primary, --bg-base, --accent-dim) finns kvar
|
|
230
|
+
i 10-semantic.css's "LEGACY ALIASES"-block
|
|
231
|
+
- Komponent-CSS som migrerats anvander nya semantic-namn
|
|
232
|
+
(--text-default, --surface-page, --accent-a3)
|
|
233
|
+
- Tar INTE bort legacy-aliaser forrans alla call-sites migrerats
|
|
234
|
+
|
|
235
|
+
**Varfor:**
|
|
236
|
+
- Migrations-bro: app-CSS som inte uppdaterats fortsatter funka
|
|
237
|
+
- Big-bang-migrationer ar riskabla - per-template-migration ar saker
|
|
238
|
+
- Open punkter dokumenterade i `05-open-decisions/`
|