@klodd/ds 3.5.0 → 3.5.2
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 +30 -2
- package/css/base/typography.css +58 -0
- package/css/components/button.css +33 -0
- package/css/components/chip.css +14 -0
- package/css/components/panel.css +36 -0
- package/css/components/setting-row.css +7 -0
- package/css/components/sheet-content.css +399 -0
- package/css/index.css +3 -0
- package/package.json +2 -2
- package/references/03-quality-bar.md +14 -9
- package/references/04-locked-decisions/0009-no-flat-components-css.md +94 -0
- package/references/05-open-decisions/{0008-legacy-token-migration.md → 0008-legacy-token-migration-CLOSED.md} +17 -0
package/SKILL.md
CHANGED
|
@@ -7,7 +7,8 @@ description: Design memory for the @klodd/ds shared design system across all Klo
|
|
|
7
7
|
|
|
8
8
|
## Vad detta är
|
|
9
9
|
Gemensamt designsystem på npm (`@klodd/ds@3.x`). Tre-lagers tokens,
|
|
10
|
-
|
|
10
|
+
34+ komponenter (sheet-content tillagd v3.5.1), konsumeras av Jubb
|
|
11
|
+
och Ekonom. Fler appar planerade.
|
|
11
12
|
Denna Skill fångar både reglerna ("vad") och resonemanget ("varför").
|
|
12
13
|
|
|
13
14
|
## Läs i denna ordning
|
|
@@ -76,4 +77,31 @@ på push och PR.
|
|
|
76
77
|
Läs relevant ADR. Täcks frågan inte av något ADR — flagga det explicit:
|
|
77
78
|
"Jag ser inget beslut på detta — ska vi skapa ett i references/05-open-decisions/?"
|
|
78
79
|
|
|
79
|
-
|
|
80
|
+
## Distribution
|
|
81
|
+
|
|
82
|
+
Källan är `~/dev/klodd-ds/` (committad i git, synkas mellan maskiner).
|
|
83
|
+
Skillen aktiveras via symlink på varje maskin - inga kopior i app-repos.
|
|
84
|
+
|
|
85
|
+
**Mac:**
|
|
86
|
+
```bash
|
|
87
|
+
mkdir -p ~/.claude/skills/
|
|
88
|
+
ln -s ~/dev/klodd-ds ~/.claude/skills/klodd-ds
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Windows:**
|
|
92
|
+
```cmd
|
|
93
|
+
mklink /D %USERPROFILE%\.claude\skills\klodd-ds %USERPROFILE%\dev\klodd-ds
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
En källa, alla projekt ser samma skill automatiskt. Ändringar i
|
|
97
|
+
`~/dev/klodd-ds/SKILL.md`, `POLICY.md` eller `references/` syns
|
|
98
|
+
omedelbart i nästa CC-session - ingen synk-fas behövs.
|
|
99
|
+
|
|
100
|
+
Updated: 2026-05-08 (matchar @klodd/ds 3.5.2 - sprint C fas 1: ny
|
|
101
|
+
sheet-content.css-komponent (24 BEM-klasser för Sprint-65-pattern),
|
|
102
|
+
foreman-typografi-utokning (.text-caption/-tiny/-num/-num--display/-positive/-warning),
|
|
103
|
+
btn-modifiers (--block, --add), och utokningar i panel/setting-row/chip).
|
|
104
|
+
v3.5.2 rattade .panel--attention__pill (felaktig BEM) till .panel__pill +
|
|
105
|
+
context-styling via .panel--attention .panel__pill.
|
|
106
|
+
ds/components.css raderingen i Ekonom rollback:ad samma kvall efter audit -
|
|
107
|
+
template-migration (sprint C fas 2) ar nasta steg.)
|
package/css/base/typography.css
CHANGED
|
@@ -125,3 +125,61 @@
|
|
|
125
125
|
.text-on-accent {
|
|
126
126
|
color: var(--text-on-accent);
|
|
127
127
|
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
/* ================================================================
|
|
131
|
+
==== FOREMAN-VARIANTER (v3.5.1, 2026-05-08)
|
|
132
|
+
Tillagda fran Ekonoms ds/components.css som flyttades till paketet
|
|
133
|
+
nar sprint C-migration paboorjades. Generiska namn med semantic
|
|
134
|
+
tokens.
|
|
135
|
+
================================================================ */
|
|
136
|
+
|
|
137
|
+
/* Smaa metadata-text under content (citations, byline, helptext).
|
|
138
|
+
Skiljer sig fran .text-meta genom explicit letter-spacing for
|
|
139
|
+
lasbarhet pa 11px. */
|
|
140
|
+
.text-caption {
|
|
141
|
+
font-size: var(--fs-11);
|
|
142
|
+
font-weight: var(--fw-regular);
|
|
143
|
+
line-height: var(--lh-base);
|
|
144
|
+
letter-spacing: 0.01em;
|
|
145
|
+
color: var(--text-muted);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* Mycket liten uppercase-tracker (10px). Anvands for category-rubriker,
|
|
149
|
+
meta-info ovanfor titel etc. Liknande tracking som .heading-4 men
|
|
150
|
+
mindre. */
|
|
151
|
+
.text-tiny {
|
|
152
|
+
font-size: var(--fs-10);
|
|
153
|
+
font-weight: var(--fw-medium);
|
|
154
|
+
letter-spacing: 0.08em;
|
|
155
|
+
text-transform: uppercase;
|
|
156
|
+
color: var(--text-muted);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* Inline-numerik med tabular-nums (14px). Default-storlek for siffror
|
|
160
|
+
inom panel-titlar, setting-row-amounts, kategori-totaler. */
|
|
161
|
+
.text-num {
|
|
162
|
+
font-size: var(--fs-14);
|
|
163
|
+
font-weight: var(--fw-medium);
|
|
164
|
+
line-height: var(--lh-snug);
|
|
165
|
+
letter-spacing: -0.015em;
|
|
166
|
+
font-variant-numeric: tabular-nums;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* Display-numerik (32px). Anvands for stora siffror i kort/panels.
|
|
170
|
+
Komposition: <span class="text-num text-num--display">. */
|
|
171
|
+
.text-num--display {
|
|
172
|
+
font-size: var(--fs-32);
|
|
173
|
+
line-height: var(--lh-tight);
|
|
174
|
+
letter-spacing: -0.02em;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/* Color-aliaser - foljer paketets befintliga .text-on-accent-konvention.
|
|
178
|
+
Anvands for inline emphasis i text-block. */
|
|
179
|
+
.text-positive {
|
|
180
|
+
color: var(--positive);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.text-warning {
|
|
184
|
+
color: var(--warning);
|
|
185
|
+
}
|
|
@@ -165,6 +165,39 @@
|
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
|
|
168
|
+
/* ================================================================
|
|
169
|
+
==== BLOCK-MODIFIER (v3.5.1)
|
|
170
|
+
Full-bredd-knapp for sheet-actions, danger-block, primary-cta i
|
|
171
|
+
form-flode. Komponerar med variant-modifiers (.btn--primary,
|
|
172
|
+
.btn--danger, .btn--add).
|
|
173
|
+
================================================================ */
|
|
174
|
+
.btn--block {
|
|
175
|
+
display: block;
|
|
176
|
+
width: 100%;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
/* ================================================================
|
|
181
|
+
==== ADD-MODIFIER (v3.5.1)
|
|
182
|
+
"Lagg till"-knapp med dashed border. Signalerar tomt slot.
|
|
183
|
+
Komposition: .btn .btn--add .btn--block (full-bredd add-knapp).
|
|
184
|
+
================================================================ */
|
|
185
|
+
.btn--add {
|
|
186
|
+
background: transparent;
|
|
187
|
+
color: var(--text-subtle);
|
|
188
|
+
border-color: var(--text-disabled);
|
|
189
|
+
border-style: dashed;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
@media (hover: hover) and (pointer: fine) {
|
|
193
|
+
.btn--add:hover {
|
|
194
|
+
background: var(--surface-hover);
|
|
195
|
+
color: var(--text-default);
|
|
196
|
+
border-color: var(--text-muted);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
|
|
168
201
|
/* ================================================================
|
|
169
202
|
==== LOADING-STATE
|
|
170
203
|
Doljer text och visar spinner via ::after. Behaller knappens
|
package/css/components/chip.css
CHANGED
|
@@ -65,6 +65,20 @@
|
|
|
65
65
|
white-space: nowrap;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/* Text-element inom chip-list-item. Tight line-height for visual
|
|
69
|
+
centering med padding. v3.5.1. */
|
|
70
|
+
.chip-list__text {
|
|
71
|
+
line-height: 1;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Form-element inom chip-list (when item ar inline-form med delete-btn).
|
|
75
|
+
Default UA-margin nollstalls. v3.5.1. */
|
|
76
|
+
.chip-list__form {
|
|
77
|
+
display: inline-flex;
|
|
78
|
+
margin: 0;
|
|
79
|
+
padding: 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
68
82
|
.chip-list__delete {
|
|
69
83
|
display: inline-flex;
|
|
70
84
|
align-items: center;
|
package/css/components/panel.css
CHANGED
|
@@ -34,6 +34,17 @@
|
|
|
34
34
|
}
|
|
35
35
|
.panel__title-row .panel__title { margin-bottom: 0; }
|
|
36
36
|
|
|
37
|
+
/* Likt .panel__title-row men med baseline-alignment (titel + meta-text
|
|
38
|
+
i hoger kolumn pa olika fontsizes ska vila pa samma baslinje).
|
|
39
|
+
v3.5.1. */
|
|
40
|
+
.panel__header-row {
|
|
41
|
+
display: flex;
|
|
42
|
+
justify-content: space-between;
|
|
43
|
+
align-items: baseline;
|
|
44
|
+
margin-bottom: var(--space-12);
|
|
45
|
+
}
|
|
46
|
+
.panel__header-row .panel__title { margin-bottom: 0; }
|
|
47
|
+
|
|
37
48
|
.panel__title-meta {
|
|
38
49
|
font-size: var(--fs-12);
|
|
39
50
|
color: var(--text-muted);
|
|
@@ -72,6 +83,31 @@
|
|
|
72
83
|
color: var(--warning);
|
|
73
84
|
}
|
|
74
85
|
|
|
86
|
+
/* Pill-element inom panel - generisk, neutral default. Anvands for
|
|
87
|
+
count-badges, status-indikatorer i panel-headers. v3.5.2 (rattad
|
|
88
|
+
fran v3.5.1 .panel--attention__pill till korrekt BEM). */
|
|
89
|
+
.panel__pill {
|
|
90
|
+
display: inline-flex;
|
|
91
|
+
align-items: center;
|
|
92
|
+
height: 24px;
|
|
93
|
+
padding: 0 var(--space-10);
|
|
94
|
+
background: var(--surface-default);
|
|
95
|
+
color: var(--text-muted);
|
|
96
|
+
font-size: var(--fs-12);
|
|
97
|
+
font-weight: var(--fw-medium);
|
|
98
|
+
border: 1px solid var(--border-default);
|
|
99
|
+
border-radius: var(--radius-full);
|
|
100
|
+
white-space: nowrap;
|
|
101
|
+
font-variant-numeric: tabular-nums;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* Context-styling: pill inom attention-panel arver warning-fargschema. */
|
|
105
|
+
.panel--attention .panel__pill {
|
|
106
|
+
background: var(--warning-dim);
|
|
107
|
+
color: var(--warning);
|
|
108
|
+
border-color: var(--warning-border);
|
|
109
|
+
}
|
|
110
|
+
|
|
75
111
|
.panel__step-row {
|
|
76
112
|
display: flex;
|
|
77
113
|
align-items: center;
|
|
@@ -136,6 +136,13 @@
|
|
|
136
136
|
white-space: nowrap;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
/* Wrapper for <form>-element som hostar setting-rows (single-row-form
|
|
140
|
+
med per-field POST). Default UA-margin nollstalls. v3.5.1. */
|
|
141
|
+
.setting-row__form {
|
|
142
|
+
display: block;
|
|
143
|
+
margin: 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
139
146
|
|
|
140
147
|
/* ================================================================
|
|
141
148
|
==== TOGGLE (iOS-stil)
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
/* ================================================================
|
|
2
|
+
components/sheet-content.css
|
|
3
|
+
Sheet-innehallets typografi + form-monster. Kompletterar
|
|
4
|
+
.sheet/.sheet-handle/.sheet-body/.sheet-divider i overlay.css.
|
|
5
|
+
|
|
6
|
+
Generiska BEM-klasser - inga domain-namn (cat → item, tx →
|
|
7
|
+
description, excluded → subform). Apparna binder bara data
|
|
8
|
+
(kategori-tokens etc) via app-domain-CSS.
|
|
9
|
+
|
|
10
|
+
Strukturer:
|
|
11
|
+
- Title + description (sektionsrubrik + kontext-text)
|
|
12
|
+
- Form (vertikal stack med fields)
|
|
13
|
+
- Field (label + input-wrap eller standalone-input + hint)
|
|
14
|
+
- Items grid (selectable items 2-kol)
|
|
15
|
+
- Actions (multi-step button-grid)
|
|
16
|
+
- Toggle (boolean-field row)
|
|
17
|
+
- Subform (sub-block med border-top)
|
|
18
|
+
- Action-buttons (save/delete fixed sizes)
|
|
19
|
+
================================================================ */
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
/* ================================================================
|
|
23
|
+
==== TITLE + DESCRIPTION
|
|
24
|
+
================================================================ */
|
|
25
|
+
.sheet__title {
|
|
26
|
+
font-size: var(--fs-13);
|
|
27
|
+
font-weight: var(--fw-medium);
|
|
28
|
+
letter-spacing: 0.04em;
|
|
29
|
+
text-transform: uppercase;
|
|
30
|
+
color: var(--text-muted);
|
|
31
|
+
margin: 0 0 var(--space-8);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.sheet__description {
|
|
35
|
+
font-size: var(--fs-14);
|
|
36
|
+
color: var(--text-default);
|
|
37
|
+
margin: 0 0 var(--space-18);
|
|
38
|
+
word-break: break-word;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
/* ================================================================
|
|
43
|
+
==== FORM-STRUKTUR
|
|
44
|
+
.sheet__form ar vertikal flex-stack med 16px gap mellan fields.
|
|
45
|
+
.sheet__form--inline tar bort margin sa <form> kan vara inline.
|
|
46
|
+
.sheet__field ar per-field-container (label + input + hint).
|
|
47
|
+
================================================================ */
|
|
48
|
+
.sheet__form {
|
|
49
|
+
display: flex;
|
|
50
|
+
flex-direction: column;
|
|
51
|
+
gap: var(--space-16);
|
|
52
|
+
margin: 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.sheet__form--inline {
|
|
56
|
+
margin: 0;
|
|
57
|
+
}
|
|
58
|
+
.sheet__form--inline button {
|
|
59
|
+
width: 100%;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.sheet__field {
|
|
63
|
+
display: flex;
|
|
64
|
+
flex-direction: column;
|
|
65
|
+
gap: var(--space-6);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.sheet__field-label {
|
|
69
|
+
font-size: var(--fs-12);
|
|
70
|
+
font-weight: var(--fw-medium);
|
|
71
|
+
color: var(--text-muted);
|
|
72
|
+
margin: 0;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.sheet__field-label--upper {
|
|
76
|
+
font-size: var(--fs-11);
|
|
77
|
+
letter-spacing: 0.06em;
|
|
78
|
+
text-transform: uppercase;
|
|
79
|
+
margin-bottom: var(--space-6);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
/* ================================================================
|
|
84
|
+
==== INPUTS
|
|
85
|
+
Input-wrap (med focus-within-state) ger sprint-65-ramad input.
|
|
86
|
+
Standalone-input ar fristaaende variant utan wrapper.
|
|
87
|
+
================================================================ */
|
|
88
|
+
.sheet__input-wrap {
|
|
89
|
+
position: relative;
|
|
90
|
+
display: flex;
|
|
91
|
+
align-items: center;
|
|
92
|
+
background: var(--surface-sunken);
|
|
93
|
+
border: 1px solid var(--border-default);
|
|
94
|
+
border-radius: var(--radius-12);
|
|
95
|
+
height: 48px;
|
|
96
|
+
transition: background var(--dur-fast) var(--ease-spring-snappy);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.sheet__input-wrap:focus-within {
|
|
100
|
+
outline: 2px solid var(--accent-9);
|
|
101
|
+
outline-offset: -1px;
|
|
102
|
+
background: var(--surface-default);
|
|
103
|
+
border-color: transparent;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.sheet__input {
|
|
107
|
+
flex: 1;
|
|
108
|
+
min-width: 0;
|
|
109
|
+
height: 100%;
|
|
110
|
+
padding: 0 var(--space-14);
|
|
111
|
+
background: transparent;
|
|
112
|
+
border: 0;
|
|
113
|
+
color: var(--text-default);
|
|
114
|
+
font-size: var(--fs-17);
|
|
115
|
+
font-family: inherit;
|
|
116
|
+
outline: none;
|
|
117
|
+
}
|
|
118
|
+
.sheet__input::placeholder {
|
|
119
|
+
color: var(--text-disabled);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.sheet__input--select {
|
|
123
|
+
appearance: none;
|
|
124
|
+
-webkit-appearance: none;
|
|
125
|
+
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
|
|
126
|
+
background-repeat: no-repeat;
|
|
127
|
+
background-position: right var(--space-12) center;
|
|
128
|
+
background-size: 14px;
|
|
129
|
+
padding-right: var(--space-32);
|
|
130
|
+
color: var(--text-muted);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.sheet__input--standalone {
|
|
134
|
+
display: block;
|
|
135
|
+
width: 100%;
|
|
136
|
+
padding: var(--space-12) var(--space-14);
|
|
137
|
+
background: var(--surface-sunken);
|
|
138
|
+
border: 1px solid var(--border-default);
|
|
139
|
+
border-radius: var(--radius-12);
|
|
140
|
+
color: var(--text-default);
|
|
141
|
+
font-size: var(--fs-17);
|
|
142
|
+
font-family: inherit;
|
|
143
|
+
outline: none;
|
|
144
|
+
margin-top: var(--space-6);
|
|
145
|
+
transition: background var(--dur-fast) var(--ease-spring-snappy);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.sheet__input--standalone:focus {
|
|
149
|
+
outline: 2px solid var(--accent-9);
|
|
150
|
+
outline-offset: -1px;
|
|
151
|
+
background: var(--surface-default);
|
|
152
|
+
border-color: transparent;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.sheet__suffix {
|
|
156
|
+
padding: 0 var(--space-14) 0 0;
|
|
157
|
+
font-size: var(--fs-14);
|
|
158
|
+
font-weight: var(--fw-medium);
|
|
159
|
+
color: var(--text-muted);
|
|
160
|
+
flex-shrink: 0;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
/* ================================================================
|
|
165
|
+
==== HINT-TEXT
|
|
166
|
+
.sheet__hint - default 12px text-muted med margin
|
|
167
|
+
.sheet__hint--compact - 11px utan margin (sprint 65 in-form-hint)
|
|
168
|
+
.is-error - rod variant for validation-fel
|
|
169
|
+
================================================================ */
|
|
170
|
+
.sheet__hint {
|
|
171
|
+
font-size: var(--fs-12);
|
|
172
|
+
color: var(--text-muted);
|
|
173
|
+
margin: var(--space-8) 0 var(--space-16);
|
|
174
|
+
}
|
|
175
|
+
.sheet__hint em {
|
|
176
|
+
font-style: italic;
|
|
177
|
+
color: var(--text-subtle);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.sheet__hint--compact {
|
|
181
|
+
font-size: var(--fs-11);
|
|
182
|
+
margin: 0;
|
|
183
|
+
line-height: var(--lh-snug);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.sheet__hint.is-error,
|
|
187
|
+
.sheet__hint--compact.is-error {
|
|
188
|
+
color: var(--accent-danger);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
/* ================================================================
|
|
193
|
+
==== ITEMS GRID (selectable items 2-kol)
|
|
194
|
+
Generic monster for kategori-val, alternativ-val osv. Apparna
|
|
195
|
+
binder data via egna domain-klasser pa item-elementet.
|
|
196
|
+
================================================================ */
|
|
197
|
+
.sheet__item-grid {
|
|
198
|
+
display: grid;
|
|
199
|
+
grid-template-columns: repeat(2, 1fr);
|
|
200
|
+
gap: var(--space-8);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.sheet__item {
|
|
204
|
+
display: block;
|
|
205
|
+
width: 100%;
|
|
206
|
+
padding: var(--space-12) var(--space-14);
|
|
207
|
+
background: var(--surface-default);
|
|
208
|
+
border: 1px solid var(--border-default);
|
|
209
|
+
border-radius: var(--radius-14);
|
|
210
|
+
color: var(--text-default);
|
|
211
|
+
font-size: var(--fs-14);
|
|
212
|
+
font-weight: var(--fw-medium);
|
|
213
|
+
font-family: inherit;
|
|
214
|
+
cursor: pointer;
|
|
215
|
+
text-align: center;
|
|
216
|
+
transition: background var(--dur-fast) var(--ease-spring-snappy);
|
|
217
|
+
-webkit-tap-highlight-color: transparent;
|
|
218
|
+
touch-action: manipulation;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
@media (hover: hover) and (pointer: fine) {
|
|
222
|
+
.sheet__item:hover {
|
|
223
|
+
background: var(--surface-hover);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.sheet__item:focus-visible {
|
|
228
|
+
outline: 2px solid var(--border-focus);
|
|
229
|
+
outline-offset: 2px;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.sheet__item:active {
|
|
233
|
+
transform: scale(0.985);
|
|
234
|
+
transition: transform 80ms var(--ease-spring-snappy);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.sheet__item--primary {
|
|
238
|
+
background: var(--accent-9);
|
|
239
|
+
color: var(--text-on-accent);
|
|
240
|
+
border-color: var(--accent-9);
|
|
241
|
+
}
|
|
242
|
+
@media (hover: hover) and (pointer: fine) {
|
|
243
|
+
.sheet__item--primary:hover {
|
|
244
|
+
background: var(--accent-10);
|
|
245
|
+
border-color: var(--accent-10);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.sheet__item--reset {
|
|
250
|
+
grid-column: 1 / -1;
|
|
251
|
+
margin-top: var(--space-6);
|
|
252
|
+
background: transparent;
|
|
253
|
+
color: var(--text-subtle);
|
|
254
|
+
border-style: dashed;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.sheet__item--back {
|
|
258
|
+
grid-column: 1 / -1;
|
|
259
|
+
margin-bottom: var(--space-4);
|
|
260
|
+
background: transparent;
|
|
261
|
+
color: var(--text-subtle);
|
|
262
|
+
border-style: dashed;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
/* ================================================================
|
|
267
|
+
==== MULTI-STEP ACTIONS-GRID
|
|
268
|
+
2-kol button-grid for steg-N actions (t.ex. Tillbaka + Spara).
|
|
269
|
+
================================================================ */
|
|
270
|
+
.sheet__actions {
|
|
271
|
+
display: grid;
|
|
272
|
+
grid-template-columns: 1fr 1fr;
|
|
273
|
+
gap: var(--space-8);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
/* ================================================================
|
|
278
|
+
==== CONFIRMATION
|
|
279
|
+
"Du valde X"-text fore step-2-actions.
|
|
280
|
+
================================================================ */
|
|
281
|
+
.sheet__confirm {
|
|
282
|
+
font-size: var(--fs-14);
|
|
283
|
+
color: var(--text-subtle);
|
|
284
|
+
margin: 0 0 var(--space-14);
|
|
285
|
+
}
|
|
286
|
+
.sheet__confirm strong {
|
|
287
|
+
color: var(--text-default);
|
|
288
|
+
font-weight: var(--fw-medium);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
/* ================================================================
|
|
293
|
+
==== TOGGLE (boolean field)
|
|
294
|
+
Row-layout for label + native checkbox/toggle.
|
|
295
|
+
================================================================ */
|
|
296
|
+
.sheet__toggle {
|
|
297
|
+
display: flex;
|
|
298
|
+
align-items: center;
|
|
299
|
+
justify-content: space-between;
|
|
300
|
+
gap: var(--space-10);
|
|
301
|
+
cursor: pointer;
|
|
302
|
+
padding: var(--space-6) 0;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.sheet__toggle-label {
|
|
306
|
+
font-size: var(--fs-14);
|
|
307
|
+
font-weight: var(--fw-medium);
|
|
308
|
+
color: var(--text-default);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.sheet__toggle-input {
|
|
312
|
+
width: 22px;
|
|
313
|
+
height: 22px;
|
|
314
|
+
accent-color: var(--accent-9);
|
|
315
|
+
cursor: pointer;
|
|
316
|
+
flex-shrink: 0;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
/* ================================================================
|
|
321
|
+
==== SUBFORM (sub-block med border-top divider)
|
|
322
|
+
Anvands for excluded-toggle-form etc i sheets med flera
|
|
323
|
+
logiska delar.
|
|
324
|
+
================================================================ */
|
|
325
|
+
.sheet__subform {
|
|
326
|
+
margin: var(--space-18) 0 0;
|
|
327
|
+
padding-top: var(--space-14);
|
|
328
|
+
border-top: 1px solid var(--border-default);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
/* ================================================================
|
|
333
|
+
==== ACTION-BUTTONS (fixed sizes for sheet-context)
|
|
334
|
+
.sheet__btn--save - primary 48px full-bredd accent-9
|
|
335
|
+
.sheet__btn--delete - sekundar destructive 44px transparent
|
|
336
|
+
Tightly coupled to sheet-form-sizing - inte generiska .btn.
|
|
337
|
+
================================================================ */
|
|
338
|
+
.sheet__btn--save {
|
|
339
|
+
display: block;
|
|
340
|
+
width: 100%;
|
|
341
|
+
height: 48px;
|
|
342
|
+
margin: var(--space-8) 0 0;
|
|
343
|
+
background: var(--accent-9);
|
|
344
|
+
color: var(--text-on-accent);
|
|
345
|
+
border: 0;
|
|
346
|
+
border-radius: var(--radius-14);
|
|
347
|
+
font-family: inherit;
|
|
348
|
+
font-size: var(--fs-15);
|
|
349
|
+
font-weight: var(--fw-medium);
|
|
350
|
+
cursor: pointer;
|
|
351
|
+
transition: background var(--dur-fast) var(--ease-spring-snappy);
|
|
352
|
+
-webkit-tap-highlight-color: transparent;
|
|
353
|
+
touch-action: manipulation;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
.sheet__btn--save:disabled {
|
|
357
|
+
opacity: 0.5;
|
|
358
|
+
cursor: not-allowed;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
@media (hover: hover) and (pointer: fine) {
|
|
362
|
+
.sheet__btn--save:not(:disabled):hover {
|
|
363
|
+
background: var(--accent-10);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.sheet__btn--save:focus-visible {
|
|
368
|
+
outline: 2px solid var(--border-focus);
|
|
369
|
+
outline-offset: 2px;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.sheet__btn--delete {
|
|
373
|
+
display: block;
|
|
374
|
+
width: 100%;
|
|
375
|
+
height: 44px;
|
|
376
|
+
margin: var(--space-8) 0 0;
|
|
377
|
+
background: transparent;
|
|
378
|
+
color: var(--accent-danger);
|
|
379
|
+
border: 0;
|
|
380
|
+
border-radius: var(--radius-14);
|
|
381
|
+
font-family: inherit;
|
|
382
|
+
font-size: var(--fs-14);
|
|
383
|
+
font-weight: var(--fw-medium);
|
|
384
|
+
cursor: pointer;
|
|
385
|
+
transition: background var(--dur-fast) var(--ease-spring-snappy);
|
|
386
|
+
-webkit-tap-highlight-color: transparent;
|
|
387
|
+
touch-action: manipulation;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
@media (hover: hover) and (pointer: fine) {
|
|
391
|
+
.sheet__btn--delete:hover {
|
|
392
|
+
background: var(--accent-danger-dim);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.sheet__btn--delete:focus-visible {
|
|
397
|
+
outline: 2px solid var(--border-focus);
|
|
398
|
+
outline-offset: 2px;
|
|
399
|
+
}
|
package/css/index.css
CHANGED
|
@@ -62,3 +62,6 @@
|
|
|
62
62
|
/* v3.1.0 - generic kategori-monster (token-binding via app-domain-CSS) */
|
|
63
63
|
@import './components/colored-row.css';
|
|
64
64
|
@import './components/colored-bar.css';
|
|
65
|
+
|
|
66
|
+
/* v3.5.1 - sheet-content (sprint-65 form-monster, generiska BEM-namn) */
|
|
67
|
+
@import './components/sheet-content.css';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@klodd/ds",
|
|
3
|
-
"version": "3.5.
|
|
4
|
-
"description": "Klodd Design System - shared tokens, typography, components and JS for Jubb, Ekonom, and future apps. v3.5.
|
|
3
|
+
"version": "3.5.2",
|
|
4
|
+
"description": "Klodd Design System - shared tokens, typography, components and JS for Jubb, Ekonom, and future apps. v3.5.2 (2026-05-08): rattade .panel--attention__pill (felaktig blandad modifier-element-BEM) till .panel__pill med context-styling via .panel--attention .panel__pill. Stricter BEM-konvention.",
|
|
5
5
|
"main": "css/index.css",
|
|
6
6
|
"bin": {
|
|
7
7
|
"klodd-ds": "./bin/klodd-ds.js"
|
|
@@ -223,16 +223,21 @@ Varje interaktiv komponent SKA ha:
|
|
|
223
223
|
- Linear, Vercel och liknande modern SaaS anvander samma stack
|
|
224
224
|
|
|
225
225
|
|
|
226
|
-
## 12.
|
|
226
|
+
## 12. Bara nya semantic token-namn
|
|
227
227
|
|
|
228
228
|
**Hur man foljer:**
|
|
229
|
-
-
|
|
230
|
-
|
|
231
|
-
-
|
|
232
|
-
|
|
233
|
-
-
|
|
229
|
+
- Anvand bara nya semantic-namn: `--text-default/-subtle/-muted/-disabled`,
|
|
230
|
+
`--surface-page/-default/-raised/-overlay/-hover/-active/-sunken`,
|
|
231
|
+
`--accent-soft/-9/-10/-text/-a10/-a20/-a40` osv.
|
|
232
|
+
- Gamla namn (--text-primary, --bg-base, --accent-dim, --fw-semibold,
|
|
233
|
+
--radius-sm/md/lg/xl/2xl/3xl/4xl) ar **borttagna** i v3.5.0
|
|
234
|
+
(2026-05-08). Ingen alias-bro langre.
|
|
234
235
|
|
|
235
236
|
**Varfor:**
|
|
236
|
-
-
|
|
237
|
-
|
|
238
|
-
-
|
|
237
|
+
- En standard, en mental modell. Inga "vilket namn ska jag anvanda?"-
|
|
238
|
+
fragor i koden.
|
|
239
|
+
- Komponenter som referensade gamla namn migrerades i 2026-05-07/08-
|
|
240
|
+
sprintarna innan aliasen raderades. Inga kvarstaende call-sites.
|
|
241
|
+
|
|
242
|
+
Migrations-historiken finns dokumenterad i ADR 0008 (CLOSED) och
|
|
243
|
+
ADR 0009 (locked).
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# 0009 - Inga flat-fil-aggregat av komponenter (`ds/components.css` förbjudet)
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
Locked.
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
Innan 2026-05-08 hade både Jubb och Ekonom en flat-fil
|
|
9
|
+
`app/static/css/ds/components.css` per repo. Filen aggregerade
|
|
10
|
+
paketets komponentstyling med app-specifik domain-CSS i en stor
|
|
11
|
+
samlingsfil.
|
|
12
|
+
|
|
13
|
+
Filen var ett resultat av att designsystemet började som en kopierad
|
|
14
|
+
samling klasser **innan** paketet flyttades till `@klodd/ds`. När
|
|
15
|
+
paketet bröts ut till en egen npm-modul med `components/<x>.css`-
|
|
16
|
+
filer per komponent fanns ingen tvingande mekanism att avveckla
|
|
17
|
+
flat-filen.
|
|
18
|
+
|
|
19
|
+
Filen växte över tid till en parallellprodukt mot paketets
|
|
20
|
+
`components/`-mapp:
|
|
21
|
+
|
|
22
|
+
- Dubbel-styling: samma selector definierades på två platser
|
|
23
|
+
- Drift: paketet uppdaterades men flat-filen släpade efter
|
|
24
|
+
- Underhållsbörda: ändring krävde uppdatering i två repos + paketet
|
|
25
|
+
- Otydlig ansvarsgräns: vad är paket-styling, vad är domain?
|
|
26
|
+
|
|
27
|
+
## Decision
|
|
28
|
+
|
|
29
|
+
`ds/components.css` (eller motsvarande aggregat-fil) i appar är
|
|
30
|
+
**förbjuden**. Appar konsumerar paketets `components/`-mapp direkt
|
|
31
|
+
via `@import url("ds/components/<x>.css")` i `main.css` (eller
|
|
32
|
+
motsvarande bundle-fil).
|
|
33
|
+
|
|
34
|
+
App-specifik domain-CSS (kategorisystem, score-pills, app-unika
|
|
35
|
+
element) lever i en tydligt namngiven domain-fil:
|
|
36
|
+
|
|
37
|
+
- Jubb: `app/static/css/jubb-theme.css`
|
|
38
|
+
- Ekonom: `app/static/css/ds/ekonom-domain.css`
|
|
39
|
+
|
|
40
|
+
## Consequences
|
|
41
|
+
|
|
42
|
+
**Bra:**
|
|
43
|
+
- Paketet är enda källan för komponent-styling
|
|
44
|
+
- Drift mellan paket och app är omöjlig
|
|
45
|
+
- Bumpa paketversion = automatiskt nya stilar i alla konsumenter
|
|
46
|
+
- Tydlig ansvarsgräns: paket = komponenter, domain-fil = app-spec
|
|
47
|
+
|
|
48
|
+
**Trade-off:**
|
|
49
|
+
- `main.css` får fler `@import`-rader (en per komponent). Inte ett
|
|
50
|
+
problem - browsern parallelliserar. Service Worker pre-cachar dem.
|
|
51
|
+
- Ny komponent kräver `@import` i alla konsumerande appars `main.css`.
|
|
52
|
+
Acceptabelt - paketet listar komponenter i README.
|
|
53
|
+
|
|
54
|
+
## Migration (genomförd 2026-05-08)
|
|
55
|
+
|
|
56
|
+
Båda repos genomgick **selector-för-selector-radering**, inte big-bang:
|
|
57
|
+
|
|
58
|
+
1. Klassificera varje sektion: paket-duplicat eller app-domain?
|
|
59
|
+
2. Paket-duplicat raderas direkt
|
|
60
|
+
3. App-domain flyttas till domain-fil
|
|
61
|
+
4. När filen är tom raderas den helt
|
|
62
|
+
5. `main.css` importerar paketet direkt
|
|
63
|
+
|
|
64
|
+
**Big-bang-försök rollbackades direkt** vid första testet - massiv
|
|
65
|
+
visuell regression (bottom-nav-blackouts, hub-card stylelöshet).
|
|
66
|
+
Selector-för-selector var rätt val för att hålla appen stabil under
|
|
67
|
+
migrationen.
|
|
68
|
+
|
|
69
|
+
Verifiering på prod via Chrome MCP:
|
|
70
|
+
- Jubb: 21 paket-imports, panel.css applierad, bottom-nav 20px
|
|
71
|
+
- Ekonom: 25 nested @imports (CSSOM-rekursion), components.css = 404,
|
|
72
|
+
panel.bg = rgb(32,19,32) Plum-2, hero rendererar
|
|
73
|
+
|
|
74
|
+
**Tester:** 429 pass (Jubb) + 636 pass (Ekonom), oförändrat.
|
|
75
|
+
|
|
76
|
+
## Framöver
|
|
77
|
+
|
|
78
|
+
Ny app som konsumerar paketet:
|
|
79
|
+
1. Skapa egen domain-fil: `app/static/css/<app>-domain.css`
|
|
80
|
+
2. Importera paketet direkt i `main.css` eller bundle-fil
|
|
81
|
+
3. Använd `npx @klodd/ds precache` för att generera SW PRECACHE_URLS
|
|
82
|
+
4. Bumpa SW-version vid varje paketuppdatering
|
|
83
|
+
|
|
84
|
+
**Aldrig** skapa en flat-fil-aggregat à la `ds/components.css`.
|
|
85
|
+
|
|
86
|
+
## References
|
|
87
|
+
|
|
88
|
+
- Ekonom commit: `8a0611e` (refactor(ds): ds/components.css raderad)
|
|
89
|
+
- Jubb commits: `cf334b5` (Block 1) + `6e0710d` (Block 2) + `d8a6c12`
|
|
90
|
+
(Block 3)
|
|
91
|
+
- Ekonom STATUS.md 2026-05-08
|
|
92
|
+
- Jubb STATUS.md 2026-05-08
|
|
93
|
+
- ADR 0001 (three-layer-token-architecture)
|
|
94
|
+
- ADR 0008 (npm-package-distribution)
|
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
# 0008 - Legacy token-migration och `ds/components.css`-radering - v4.0.0
|
|
2
2
|
|
|
3
3
|
## Status
|
|
4
|
+
**CLOSED 2026-05-08.** Bagge stegen genomforda. Se ADR 0009 (locked)
|
|
5
|
+
"Inga flat-fil-aggregat av komponenter" som ar den varande regeln
|
|
6
|
+
framover.
|
|
7
|
+
|
|
8
|
+
**Resultat:**
|
|
9
|
+
- LEGACY ALIASES-sektionen raderad ur `10-semantic.css` i paket v3.5.0
|
|
10
|
+
- `ds/components.css` raderad ur Jubb (commits cf334b5 + 6e0710d +
|
|
11
|
+
d8a6c12) och Ekonom (commit 8a0611e)
|
|
12
|
+
- Bagge appar kor 100% paket-driven design via `@klodd/ds`-komponenter
|
|
13
|
+
+ per-app domain-fil (`jubb-theme.css` resp. `ekonom-domain.css`)
|
|
14
|
+
- 429 pass (Jubb) + 636 pass (Ekonom), oforandrat
|
|
15
|
+
|
|
16
|
+
Originaltexten bevarad nedan for historik.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Original status (innan stangning)
|
|
4
21
|
Pending. Trigger: innan tredje app borjar anvanda `@klodd/ds`.
|
|
5
22
|
|
|
6
23
|
## Context
|