@klodd/ds 3.5.7 → 3.6.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/css/components/chip.css +21 -10
- package/css/components/collapsible.css +17 -6
- package/css/components/feedback.css +21 -2
- package/css/components/form.css +17 -3
- package/css/components/hero.css +15 -6
- package/css/components/hub-card.css +14 -5
- package/css/components/input.css +21 -6
- package/css/components/list-row.css +16 -6
- package/css/components/nav.css +16 -53
- package/css/components/progress.css +18 -6
- package/css/components/stat.css +13 -4
- package/css/components/swipe-stack.css +35 -16
- package/css/components/tab-bar.css +7 -0
- package/css/components/upload-spinner.css +18 -4
- package/package.json +1 -1
- package/references/02-components.md +120 -41
- package/references/03-quality-bar.md +78 -2
- package/references/04-locked-decisions/0009-collapsible-block-rename.md +48 -0
package/css/components/chip.css
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
/* ================================================================
|
|
2
2
|
components/chip.css
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
Pills- och chips-familjen: sex fristående blocks som delar
|
|
4
|
+
form-språket (rounded-full, kompakt padding, inline-flex).
|
|
5
|
+
|
|
6
|
+
Blocks:
|
|
7
|
+
.chip - generisk status-pill med dot-prefix (har modifiers)
|
|
8
|
+
.chip-list - sibling-wrapper för chips i rad (har __item/__delete/__add)
|
|
9
|
+
.brand-pill - projekt-namn-pill i topbar
|
|
10
|
+
.month-pill - navigations-pill för månadsbyte (Ekonom)
|
|
11
|
+
.score-pill - ratings-pill (NB: definieras även i badge.css - identiska regler)
|
|
12
|
+
.install-chip - PWA install-prompt som flyter ovan bottom-nav
|
|
13
|
+
|
|
14
|
+
HTML-relationer:
|
|
15
|
+
.chip-list innehåller .chip-list__item (egna BEM-element, ej .chip)
|
|
16
|
+
Övriga blocks är fristående och placeras där de behövs
|
|
17
|
+
|
|
18
|
+
Modifiers:
|
|
19
|
+
.chip --accent/-positive/-negative/-warning/-faint
|
|
20
|
+
.score-pill --strong/-medium/-low
|
|
21
|
+
|
|
22
|
+
.install-chip har egna BEM-element (__text/__install/__dismiss) plus
|
|
23
|
+
keyframe-animation install-chip-up (respekterar prefers-reduced-motion).
|
|
13
24
|
================================================================ */
|
|
14
25
|
.chip {
|
|
15
26
|
display: inline-flex;
|
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
/* ================================================================
|
|
2
2
|
components/collapsible.css
|
|
3
|
-
Panel som expanderar
|
|
3
|
+
Panel som expanderar på klick. Används för budget-sektioner,
|
|
4
4
|
kategori-grupper, FAQ-rader.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
- .collapsible__body expanderat innehall (hidden default)
|
|
9
|
-
- .collapsible__chev chevron som roterar 180deg
|
|
6
|
+
Block:
|
|
7
|
+
.collapsible-card - root-block (huvud-container)
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
BEM-element av blocket:
|
|
10
|
+
.collapsible__header - klickbar header (button-element)
|
|
11
|
+
.collapsible__header-text - text-wrapper i header
|
|
12
|
+
.collapsible__body - expanderat innehåll (hidden default)
|
|
13
|
+
.collapsible__chev - chevron som roterar 180deg
|
|
14
|
+
|
|
15
|
+
ANTECKNING (BEM-stam-mismatch, öppen punkt):
|
|
16
|
+
Blocket heter .collapsible-card men elementen heter .collapsible__X
|
|
17
|
+
(utan -card-suffix). Två lösningar finns: rename block till
|
|
18
|
+
.collapsible eller rename element till .collapsible-card__X.
|
|
19
|
+
Underlag finns i sprint-rapport 2026-05-09. Ingen rename i fas 1.
|
|
20
|
+
|
|
21
|
+
States:
|
|
22
|
+
[data-expanded] på .collapsible-card - JS togglar, roterar __chev 180deg
|
|
12
23
|
================================================================ */
|
|
13
24
|
.collapsible-card {
|
|
14
25
|
background: var(--surface-raised);
|
|
@@ -1,7 +1,26 @@
|
|
|
1
1
|
/* ================================================================
|
|
2
2
|
components/feedback.css
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Transient feedback och loading-states: fyra fristående blocks som
|
|
4
|
+
tematiskt hör ihop (status- eller loading-feedback) men används
|
|
5
|
+
oberoende i HTML.
|
|
6
|
+
|
|
7
|
+
Blocks:
|
|
8
|
+
.toast - transient meddelande (ankrat top-center via toast-region)
|
|
9
|
+
.empty-state - centrerad ikon + rubrik + text för tomma listor
|
|
10
|
+
.skeleton - loading-placeholder med pulse-animation
|
|
11
|
+
.spinner - roterande loader (inline-block)
|
|
12
|
+
|
|
13
|
+
Inga inbördes HTML-relationer - alla fyra placeras självständigt.
|
|
14
|
+
.toast och .empty-state har egna BEM-element (__title/__text/__icon).
|
|
15
|
+
.skeleton och .spinner har bara modifiers.
|
|
16
|
+
|
|
17
|
+
Modifiers:
|
|
18
|
+
.toast --success/-error/-warning
|
|
19
|
+
.skeleton --text/-circle/-card
|
|
20
|
+
.spinner --sm/-lg
|
|
21
|
+
|
|
22
|
+
Alla fyra respekterar prefers-reduced-motion (animation tas bort
|
|
23
|
+
eller saktas ned).
|
|
5
24
|
================================================================ */
|
|
6
25
|
|
|
7
26
|
|
package/css/components/form.css
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
/* ================================================================
|
|
2
2
|
components/form.css
|
|
3
|
-
Form-skelett
|
|
3
|
+
Form-skelett: wrapper-strukturen som gör formuläret komplett.
|
|
4
|
+
Skiljer sig från input.css (input-elementen själva).
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
Blocks:
|
|
7
|
+
.form-card - kort-style wrapper för forms (max-width 480px)
|
|
8
|
+
.form-section - sektion-grupp inom form (har __title)
|
|
9
|
+
.form-group - field-grupp: label + input (har __label)
|
|
10
|
+
.form-hint - help-text under field (atomisk)
|
|
11
|
+
.form-row - horisontell field-rad (grid-baserad, har --inline)
|
|
12
|
+
|
|
13
|
+
Alla fem är fristående blocks. .form-section och .form-group har
|
|
14
|
+
egna BEM-element (__title, __label). De kombineras fritt - ingen
|
|
15
|
+
tvingad hierarki i CSS:en.
|
|
16
|
+
|
|
17
|
+
HTML-relationer (vanligt mönster, ej tvingande):
|
|
18
|
+
.form-card > .form-section > .form-group > .form-row > <inputs>
|
|
19
|
+
|
|
20
|
+
Modifiers: .form-row har --inline (flex-wrap-variant).
|
|
7
21
|
================================================================ */
|
|
8
22
|
.form-card {
|
|
9
23
|
background: var(--surface-raised);
|
package/css/components/hero.css
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
/* ================================================================
|
|
2
2
|
components/hero.css
|
|
3
|
-
Stora display-rubriker med amount + meta.
|
|
3
|
+
Stora display-rubriker med amount + meta. Används på dashboard,
|
|
4
4
|
detaljvyer, primary-page-toppar.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
Blocks:
|
|
7
|
+
.hero - wrapper med padding och text-alignment (huvud-block)
|
|
8
|
+
.hero-amount - sibling-block: hero-roll-animations-target
|
|
9
9
|
|
|
10
|
-
.hero
|
|
11
|
-
-
|
|
10
|
+
.hero har BEM-element (__heading/__amount/__amount-row/__label/__meta/__actions).
|
|
11
|
+
.hero-amount är ett separat root-block av historiska skäl - hero-roll-
|
|
12
|
+
animationen adresserar just klassen .hero-amount[data-animate-roll],
|
|
13
|
+
inte .hero__amount. Definieras även i hero-roll.css (animation-styling).
|
|
14
|
+
|
|
15
|
+
Modifiers:
|
|
16
|
+
.hero__amount --card (40px sekundär), --fluid (clamp 40-80px)
|
|
17
|
+
.hero__label --muted
|
|
18
|
+
|
|
19
|
+
Se components/hero-roll.css för digit-roller-styling när
|
|
20
|
+
data-animate-roll triggar animationen.
|
|
12
21
|
================================================================ */
|
|
13
22
|
.hero {
|
|
14
23
|
padding: var(--space-20) var(--space-4) var(--space-24);
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
/* ================================================================
|
|
2
2
|
components/hub-card.css
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Settings-hub-navigation: kort-listor som länkar till sub-sidor.
|
|
4
|
+
Layout per kort: ikon + titel + subtitle + chevron. Hela kortet
|
|
5
|
+
är klickbart.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
Blocks:
|
|
8
|
+
.hub-card - klickbart kort (huvud-block med BEM-element)
|
|
9
|
+
.hub-list - sibling-wrapper: <ul> som samlar flera hub-cards
|
|
10
|
+
.hub-category - sibling-block: <h6>-rubrik över en hub-list-grupp
|
|
11
|
+
|
|
12
|
+
HTML-relationer:
|
|
13
|
+
.hub-list innehåller flera <li> med .hub-card
|
|
14
|
+
.hub-category placeras som sibling FÖRE .hub-list (inte inuti)
|
|
15
|
+
|
|
16
|
+
Bara .hub-card har egna BEM-element (__icon/__text/__title/__subtitle/__chev).
|
|
17
|
+
.hub-list och .hub-category är fristående blocks utan egna element.
|
|
9
18
|
================================================================ */
|
|
10
19
|
.hub-list {
|
|
11
20
|
display: flex;
|
package/css/components/input.css
CHANGED
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
/* ================================================================
|
|
2
2
|
components/input.css
|
|
3
|
-
|
|
4
|
-
States: :focus, :disabled, [aria-invalid="true"] (error).
|
|
5
|
-
Tillagg: .input-group (label + input + error), .input-icon (input
|
|
6
|
-
med leading ikon).
|
|
3
|
+
Form-fält med iOS-zoom-skydd (17px font-size).
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
Blocks:
|
|
6
|
+
.input - text-input-element (single-line)
|
|
7
|
+
.textarea - textarea-element (multi-line)
|
|
8
|
+
.select - select-element med custom chevron-bg
|
|
9
|
+
.input-group - sibling-wrapper: label + input + hint/error
|
|
10
|
+
.input-icon - sibling-wrapper: leading-ikon + input
|
|
11
|
+
|
|
12
|
+
.input/.textarea/.select delar bas-styling via comma-selector.
|
|
13
|
+
.input-group och .input-icon är fristående blocks, inte BEM-element
|
|
14
|
+
av .input. I HTML ligger ett .input-element som child inuti
|
|
15
|
+
wrapper-blocken (DOM-konvention, inte BEM-relation).
|
|
16
|
+
|
|
17
|
+
Modifiers: inga klassiska BEM-modifiers - tillstånd via [aria-invalid].
|
|
18
|
+
|
|
19
|
+
States på .input/.textarea/.select: :focus, :disabled, [aria-invalid="true"].
|
|
20
|
+
Text-inputs använder :focus istället för :focus-visible som dokumenterat
|
|
21
|
+
undantag (Radix UI/MUI/shadcn-konvention).
|
|
22
|
+
|
|
23
|
+
Regel: font-size 17px så iOS Safari inte auto-zoomar vid focus.
|
|
24
|
+
Aldrig under 16px på input-element.
|
|
10
25
|
================================================================ */
|
|
11
26
|
|
|
12
27
|
|
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
/* ================================================================
|
|
2
2
|
components/list-row.css
|
|
3
|
-
Generisk list-rad med ikon + body + amount.
|
|
3
|
+
Generisk list-rad med ikon + body + amount. Används för transaktioner,
|
|
4
4
|
subscriptions, audit-logs, jobblistor.
|
|
5
5
|
|
|
6
6
|
Tidigare hette komponenten .tx-row (transaction) - nu generaliserad
|
|
7
|
-
till .list-row
|
|
7
|
+
till .list-row så inte affärsdomänen sipprar in i namnet.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
Blocks:
|
|
10
|
+
.list - sibling-wrapper: <ul>-reset (list-style none, no padding)
|
|
11
|
+
.list-row - själva raden (huvud-block med BEM-element)
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
HTML-relationer:
|
|
14
|
+
.list innehåller flera <li> med .list-row (vanligt men ej tvingande)
|
|
15
|
+
.list-row kan också användas fristående utanför .list
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
.list-row har element __icon/__body/__desc/__date/__amount/__meta.
|
|
18
|
+
.list är atomisk (ingen __element).
|
|
19
|
+
|
|
20
|
+
Modifiers:
|
|
21
|
+
.list-row --excluded (greyed out), --pending (dashed border), --clickable
|
|
22
|
+
.list-row__amount --positive/-negative
|
|
23
|
+
|
|
24
|
+
App-specifika domain-overrides (kategori-färgade ikoner) lever i
|
|
15
25
|
app-repots egna CSS - inte i paketet.
|
|
16
26
|
================================================================ */
|
|
17
27
|
.list {
|
package/css/components/nav.css
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
/* ================================================================
|
|
2
2
|
components/nav.css
|
|
3
|
-
|
|
3
|
+
Tva navigations-blocks: fixed bottom-nav och in-flow topbar.
|
|
4
|
+
Tab-bar och .tab-bar__item lever i components/tab-bar.css.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
Blocks:
|
|
7
|
+
.bottom-nav - position:fixed pa mobil-botten (har __item)
|
|
8
|
+
.topbar - in-flow header under safe-area (har __back/__title/__action)
|
|
9
|
+
|
|
10
|
+
HTML-relationer:
|
|
11
|
+
.bottom-nav > .bottom-nav__item (BEM-element)
|
|
12
|
+
.topbar > .topbar__back/__title/__action (BEM-element)
|
|
13
|
+
|
|
14
|
+
Modifiers/States:
|
|
15
|
+
.bottom-nav__item--active - aktiv pod (Sprint F BEM-konvertering)
|
|
16
|
+
|
|
17
|
+
Sprint 1 (3.6.0): den gamla flat-form-varianten .tab + .tab-bar i
|
|
18
|
+
denna fil togs bort. Den hade min-height: 36px under WCAG-kravet
|
|
19
|
+
44px. Kanonisk tab-komponent: .tab-bar__item i tab-bar.css.
|
|
7
20
|
================================================================ */
|
|
8
21
|
|
|
9
22
|
|
|
@@ -150,53 +163,3 @@
|
|
|
150
163
|
outline: 2px solid var(--border-focus);
|
|
151
164
|
outline-offset: 2px;
|
|
152
165
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
/* ================================================================
|
|
156
|
-
==== TAB-BAR (inline tabs i panel)
|
|
157
|
-
Segmented control monster. Active-tab har highlighted bg.
|
|
158
|
-
================================================================ */
|
|
159
|
-
.tab-bar {
|
|
160
|
-
display: flex;
|
|
161
|
-
gap: var(--space-4);
|
|
162
|
-
padding: var(--space-4);
|
|
163
|
-
background: var(--surface-default);
|
|
164
|
-
border-radius: var(--radius-12);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
.tab {
|
|
168
|
-
flex: 1;
|
|
169
|
-
display: inline-flex;
|
|
170
|
-
align-items: center;
|
|
171
|
-
justify-content: center;
|
|
172
|
-
min-height: 36px;
|
|
173
|
-
padding: 0 var(--space-12);
|
|
174
|
-
font-family: inherit;
|
|
175
|
-
font-size: var(--fs-13);
|
|
176
|
-
font-weight: var(--fw-medium);
|
|
177
|
-
color: var(--text-subtle);
|
|
178
|
-
background: transparent;
|
|
179
|
-
border: 0;
|
|
180
|
-
border-radius: var(--radius-8);
|
|
181
|
-
cursor: pointer;
|
|
182
|
-
text-decoration: none;
|
|
183
|
-
transition:
|
|
184
|
-
background var(--dur-fast) var(--ease-spring-snappy),
|
|
185
|
-
color var(--dur-fast) var(--ease-spring-snappy);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
@media (hover: hover) and (pointer: fine) {
|
|
189
|
-
.tab:not(.active):hover {
|
|
190
|
-
color: var(--text-default);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
.tab.active {
|
|
195
|
-
background: var(--surface-raised);
|
|
196
|
-
color: var(--text-default);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
.tab:focus-visible {
|
|
200
|
-
outline: 2px solid var(--border-focus);
|
|
201
|
-
outline-offset: 2px;
|
|
202
|
-
}
|
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
/* ================================================================
|
|
2
2
|
components/progress.css
|
|
3
|
-
|
|
4
|
-
status, multi-step-flows.
|
|
3
|
+
Linjär progress-indikator. Används för budget-burndown, upload-
|
|
4
|
+
status, multi-step-flows.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
Blocks:
|
|
7
|
+
.progress - track (wrapper, surface-raised bg)
|
|
8
|
+
.progress-bar - fyllning (eget block, alltid DOM-child av .progress)
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
HTML-relationer:
|
|
11
|
+
.progress-bar placeras alltid som child inuti .progress i HTML.
|
|
12
|
+
CSS-mässigt fristående block - flat-namnet behålls av historiska
|
|
13
|
+
skäl (inte .progress__bar). Se references/03-quality-bar.md
|
|
14
|
+
regel 11 om fil med flera root-blocks.
|
|
15
|
+
|
|
16
|
+
Modifiers:
|
|
17
|
+
.progress-bar --success/-warning/-danger
|
|
18
|
+
|
|
19
|
+
Bredd via CSP-safe pattern (bar-styles.js applicerar style.width
|
|
20
|
+
från data-bar-width vid runtime):
|
|
10
21
|
<div class="progress">
|
|
11
22
|
<div class="progress-bar progress-bar--warning"
|
|
12
23
|
data-bar-width="73%"></div>
|
|
13
24
|
</div>
|
|
14
|
-
|
|
25
|
+
|
|
26
|
+
Respekterar prefers-reduced-motion (transition tas bort).
|
|
15
27
|
================================================================ */
|
|
16
28
|
.progress {
|
|
17
29
|
width: 100%;
|
package/css/components/stat.css
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
/* ================================================================
|
|
2
2
|
components/stat.css
|
|
3
|
-
|
|
4
|
-
.stat-grid lagger ut flera kort i grid (2 kol mobil, 4 desktop).
|
|
3
|
+
Små kort med stor siffra + label. Används för read-only metric-display.
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
Blocks:
|
|
6
|
+
.stat-grid - grid-container (2 kol mobil, 4 desktop)
|
|
7
|
+
.stat-card - kort med siffra + label (huvud-block med BEM-element)
|
|
8
|
+
|
|
9
|
+
HTML-relationer:
|
|
10
|
+
.stat-grid > .stat-card (multipel, layout-grid)
|
|
11
|
+
|
|
12
|
+
.stat-card har element __value/__label/__unit/__sub.
|
|
13
|
+
|
|
14
|
+
Modifiers:
|
|
15
|
+
.stat-grid --single (1-kol-grid)
|
|
16
|
+
.stat-card__value --positive/-negative/-accent/-warning
|
|
8
17
|
================================================================ */
|
|
9
18
|
.stat-grid {
|
|
10
19
|
display: grid;
|
|
@@ -1,23 +1,42 @@
|
|
|
1
1
|
/* ================================================================
|
|
2
2
|
components/swipe-stack.css
|
|
3
|
-
Tinder-stil swipe-card-stack med drag-physics.
|
|
3
|
+
Tinder-stil swipe-card-stack med drag-physics. Används för
|
|
4
4
|
triage-flow, decision-cards, tutorial-stacks.
|
|
5
5
|
|
|
6
|
-
Klassnamn
|
|
7
|
-
App-repots vyer applicerar dessa
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
6
|
+
Klassnamn är generiska (.swipe-*) - inte vy-specifika (.triage-*).
|
|
7
|
+
App-repots vyer applicerar dessa på sina specifika data-cards.
|
|
8
|
+
|
|
9
|
+
Blocks (10 fristående blocks i swipe-familjen):
|
|
10
|
+
|
|
11
|
+
Stack och kort:
|
|
12
|
+
.swipe-stack - container med relative position
|
|
13
|
+
.swipe-card - individuellt kort (absolute positionerat, har BEM-element)
|
|
14
|
+
|
|
15
|
+
Decision-overlays och actions:
|
|
16
|
+
.swipe-decision-overlay - overlay med "spara"/"avfärd"-indikator
|
|
17
|
+
.swipe-actions - knapp-rad under stacken
|
|
18
|
+
.swipe-action-btn - rund knapp i swipe-actions
|
|
19
|
+
|
|
20
|
+
Meta och feedback:
|
|
21
|
+
.swipe-meta - kort-meta-info (inline-flex)
|
|
22
|
+
.swipe-meta-sep - dot-separator mellan meta-items
|
|
23
|
+
.swipe-progress - text "X av Y"
|
|
24
|
+
.swipe-empty - tomt-state när stacken är klar
|
|
25
|
+
.swipe-hint - hint-text (t.ex. "Svep åt sidan")
|
|
26
|
+
|
|
27
|
+
HTML-relationer:
|
|
28
|
+
.swipe-stack > .swipe-card (multipel, absolute positionerade)
|
|
29
|
+
.swipe-card > .swipe-decision-overlay (overlay i kortet)
|
|
30
|
+
.swipe-actions > .swipe-action-btn (multipel)
|
|
31
|
+
Övriga är fristående.
|
|
32
|
+
|
|
33
|
+
Bara .swipe-card har egna BEM-element (__header/__title/__body/__footer).
|
|
34
|
+
Övriga blocks är atomiska eller har bara modifiers.
|
|
35
|
+
|
|
36
|
+
Modifiers:
|
|
37
|
+
.swipe-card --back/-gone
|
|
38
|
+
.swipe-decision-overlay --save/-dismiss/-visible
|
|
39
|
+
.swipe-action-btn --save/-dismiss
|
|
21
40
|
================================================================ */
|
|
22
41
|
.swipe-stack {
|
|
23
42
|
position: relative;
|
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
/* ================================================================
|
|
2
2
|
components/upload-spinner.css
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Viewport-overlay för långa async-operations (OCR, AI-anrop, andra
|
|
4
|
+
där appen är visuellt blockerad).
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
Blocks:
|
|
7
|
+
.upload-spinner-overlay - fixed-positionerat overlay (huvud-block)
|
|
8
|
+
.upload-spinner - själva spinner-cirkeln (atomisk)
|
|
9
|
+
|
|
10
|
+
HTML-relationer:
|
|
11
|
+
.upload-spinner-overlay > .upload-spinner + label + hint
|
|
12
|
+
(spinner ligger inuti overlay, men är ett separat CSS-block)
|
|
13
|
+
|
|
14
|
+
.upload-spinner-overlay har BEM-element __label/__hint plus
|
|
15
|
+
.is-visible state-class (JS togglar för display: flex).
|
|
16
|
+
.upload-spinner är atomisk - används bara som child av overlay.
|
|
17
|
+
|
|
18
|
+
States:
|
|
19
|
+
.upload-spinner-overlay.is-visible - visa overlay (display: flex)
|
|
20
|
+
|
|
21
|
+
Animation upload-spinner-rotate respekterar prefers-reduced-motion.
|
|
8
22
|
================================================================ */
|
|
9
23
|
.upload-spinner-overlay {
|
|
10
24
|
position: fixed;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@klodd/ds",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.0",
|
|
4
4
|
"description": "Klodd Design System - shared tokens, typography, components and JS for Jubb, Ekonom, and future apps. v3.5.3 (2026-05-09): tillagg .heading (17px medium tight) i base/typography.css for dialog-titlar och sheet-rubriker. Tackar luckan mellan .heading-2 (18px) och .heading-3 (15px) - matchar Ekonoms gamla .heading-class.",
|
|
5
5
|
"main": "css/index.css",
|
|
6
6
|
"bin": {
|
|
@@ -1,84 +1,116 @@
|
|
|
1
1
|
# Komponentkatalog
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
35 komponent-filer i `@klodd/ds@3.x`. Alla refererar bara semantic tokens -
|
|
4
4
|
inga primitives. BEM-konvention (block__element--modifier).
|
|
5
5
|
|
|
6
|
+
## Klassificeringsformat
|
|
7
|
+
|
|
8
|
+
För varje entry gäller:
|
|
9
|
+
|
|
10
|
+
- **Blocks:** root-blocks i filen. Flera blocks kan dela en fil när de är
|
|
11
|
+
semantiskt relaterade (se `references/03-quality-bar.md` regel 11).
|
|
12
|
+
Sibling-relation eller wrapper-roll noteras i parentes.
|
|
13
|
+
- **Element:** BEM-element (`block__element`). Listas bara om de finns.
|
|
14
|
+
- **Modifiers:** BEM-modifiers (`block--modifier`). Listas bara om de finns.
|
|
15
|
+
- **States:** state-classes (`.is-X`) eller attribut-states (`[data-X]`).
|
|
16
|
+
Listas bara om de finns.
|
|
17
|
+
|
|
6
18
|
## Grundkomponenter
|
|
7
19
|
|
|
8
20
|
### button (`button.css`)
|
|
9
|
-
- **
|
|
21
|
+
- **Blocks:** `.btn`
|
|
22
|
+
- **Modifiers:** `.btn--primary/-secondary/-ghost/-danger`, `.btn--sm/-lg/-icon/-circle`, `.btn--block/-add`, `.btn--loading`
|
|
10
23
|
- **Anvand:** alla aktioner med tap-target >=44px
|
|
11
24
|
- **INTE:** Cirkel-link i topbar (anvand `.btn--icon.btn--circle`)
|
|
12
25
|
- **Tokens:** `--surface-default/-hover/-active`, `--text-default/-on-accent`, `--border-default/-focus`, `--accent-9/-10`, `--bg-danger`, `--touch-min`
|
|
13
26
|
|
|
14
27
|
### input (`input.css`)
|
|
15
|
-
- **
|
|
28
|
+
- **Blocks:** `.input`, `.textarea`, `.select`, `.input-group` (sibling-wrapper for label + input + hint/error), `.input-icon` (sibling-wrapper for input med leading ikon)
|
|
29
|
+
- **Element:** `.input-group__label`, `.input-group__hint`, `.input-group__error`
|
|
30
|
+
- **States:** `:focus`, `:disabled`, `[aria-invalid="true"]` (text-inputs anvander `:focus` istallet for `:focus-visible` per dokumenterat undantag)
|
|
16
31
|
- **Anvand:** form-falt med 17px font-size (anti iOS auto-zoom)
|
|
17
32
|
- **INTE:** Inline-edit-pattern (anvand `.inline-edit__input`)
|
|
18
33
|
- **Tokens:** `--surface-sunken/-default`, `--accent-9`, `--accent-a3` (focus-ring), `--bg-danger` (error-state)
|
|
19
34
|
|
|
20
35
|
### badge (`badge.css`)
|
|
21
|
-
- **
|
|
36
|
+
- **Blocks:** `.badge`, `.score-pill` (sibling, definieras aven i `chip.css` med identiska regler)
|
|
37
|
+
- **Modifiers:** `.badge--neutral/-success/-warning/-danger/-accent`, `.score-pill--strong/-medium/-low`
|
|
22
38
|
- **Anvand:** Status-pills (statiska)
|
|
23
39
|
- **INTE:** Klickbara chips (anvand `.chip`)
|
|
24
40
|
- **Tokens:** `--positive/-dim/-border`, `--warning/-dim/-border`, `--bg-danger`, `--accent-text/-a2/-a6`
|
|
25
41
|
|
|
26
42
|
### card (`card.css`)
|
|
27
|
-
- **
|
|
43
|
+
- **Blocks:** `.card`
|
|
44
|
+
- **Element:** `.card__header`, `.card__body`, `.card__footer`, `.card__divider`
|
|
45
|
+
- **Modifiers:** `.card--interactive`, `.card--flush`
|
|
28
46
|
- **Anvand:** Standardcontainer for paneler. `--interactive` ger hover/press-feedback
|
|
29
47
|
- **INTE:** Settings-hub-kort (anvand `.hub-card`)
|
|
30
48
|
- **Tokens:** `--surface-raised/-overlay/-hover`, `--border-subtle/-default/-focus`
|
|
31
49
|
|
|
32
50
|
### nav (`nav.css`)
|
|
33
|
-
- **
|
|
51
|
+
- **Blocks:** `.bottom-nav`, `.topbar`, `.tab-bar`, `.tab` (child av tab-bar)
|
|
52
|
+
- **Element:** `.bottom-nav__item`, `.topbar__back`, `.topbar__title`, `.topbar__action`
|
|
53
|
+
- **Modifiers:** `.bottom-nav__item--active` (Sprint F BEM-konvertering)
|
|
54
|
+
- **States:** `.tab.active`
|
|
34
55
|
- **Anvand:** Mobile bottom-nav (fixed), in-flow topbar, segmented tabs
|
|
35
|
-
- **INTE:** Generisk navigations-meny (anvand `.dropdown`)
|
|
56
|
+
- **INTE:** Generisk navigations-meny (anvand `.dropdown`). For utokad tab-bar med 44px touch-target, anvand `.tab-bar__item` fran `tab-bar.css`
|
|
36
57
|
- **Tokens:** `--surface-default`, `--text-muted/-default`, `--accent-text` (active), `--border-subtle/-focus`, `--touch-min`, `--safe-bottom`
|
|
37
58
|
|
|
38
59
|
### feedback (`feedback.css`)
|
|
39
|
-
- **
|
|
60
|
+
- **Blocks:** `.toast`, `.empty-state`, `.skeleton`, `.spinner` (fyra fristaende blocks i samma fil - feedback-familjen)
|
|
61
|
+
- **Element:** `.empty-state__icon`, `.empty-state__title`, `.empty-state__text`
|
|
62
|
+
- **Modifiers:** `.toast--success/-error/-warning`, `.skeleton--text/-circle/-card`, `.spinner--sm/-lg`
|
|
40
63
|
- **Anvand:** Transient feedback + loading-states
|
|
41
64
|
- **INTE:** Inline error-meddelanden (anvand `.input-group__error`)
|
|
42
65
|
- **Tokens:** `--surface-overlay`, `--bg-success/-warning/-danger`, `--text-on-status`, `--shadow-float`. Respekterar `prefers-reduced-motion`.
|
|
43
66
|
|
|
44
67
|
### overlay (`overlay.css`)
|
|
45
|
-
- **
|
|
68
|
+
- **Blocks:** `.dialog`, `.sheet` (sibling - tva olika overlay-monster i samma fil)
|
|
69
|
+
- **Element:** `.dialog__backdrop`, `.dialog__header`, `.dialog__body`, `.dialog__footer`, `.sheet__handle`, `.sheet__body`, `.sheet__divider`
|
|
46
70
|
- **Anvand:** Native `<dialog>` (centrerad modal) eller `<dialog class="sheet">` (bottom-attached)
|
|
47
71
|
- **INTE:** Tooltip eller dropdown (egna komponenter)
|
|
48
72
|
- **Tokens:** `--surface-raised/-overlay`, `--border-subtle`, `--shadow-float`, `--z-overlay`, `--safe-bottom`
|
|
49
73
|
|
|
50
74
|
### icon (`icon.css`)
|
|
51
|
-
- **
|
|
75
|
+
- **Blocks:** `.icon`, `.icon-custom` (sibling - wrapper for handritade SVG som Lucide saknar)
|
|
76
|
+
- **Modifiers:** `.icon--xs/-sm/-md/-lg/-xl`
|
|
52
77
|
- **Anvand:** Lucide via CDN (cdn.jsdelivr.net) ELLER inline-SVG via `.icon-custom`
|
|
53
78
|
- **INTE:** Inline `style="width:Xpx"` pa ikoner (anvand size-modifier)
|
|
54
79
|
- **Tokens:** `currentColor` - parent-element styr fargen
|
|
55
80
|
|
|
56
81
|
### hero-roll (`hero-roll.css`)
|
|
57
|
-
- **
|
|
82
|
+
- **Blocks:** `.hero-amount` (definieras aven i `hero.css`)
|
|
83
|
+
- **Element:** `.hero-amount__digit-track`
|
|
84
|
+
- **States:** `[data-animate-roll]` pa `.hero-amount` (JS triggar animation)
|
|
58
85
|
- **Anvand:** Display-siffer-animation pa hero-vyer (kodlas-rullning)
|
|
59
86
|
- **INTE:** Vanliga numeriska varden (anvand `.hero__amount` utan data-animate-roll)
|
|
60
87
|
- **Tokens:** `--text-default`, `--lh-tight`, `--ls-tightest`, `--fs-80`. **Undantag:** `font-weight: 600` (display-undantaget fran 400/500-policyn).
|
|
61
88
|
|
|
62
89
|
### divider (`divider.css`)
|
|
63
|
-
- **
|
|
90
|
+
- **Blocks:** `.divider`
|
|
91
|
+
- **Modifiers:** `.divider--vertical`, `.divider--strong`
|
|
64
92
|
- **Anvand:** Horisontell eller vertikal separator
|
|
65
|
-
- **INTE:** Visuell separator inom card (anvand `.
|
|
93
|
+
- **INTE:** Visuell separator inom card (anvand `.card__divider`)
|
|
66
94
|
- **Tokens:** `--border-subtle/-default`
|
|
67
95
|
|
|
68
96
|
### progress (`progress.css`)
|
|
69
|
-
- **
|
|
97
|
+
- **Blocks:** `.progress` (track), `.progress-bar` (fyllning, alltid DOM-child av `.progress`)
|
|
98
|
+
- **Modifiers:** `.progress-bar--success/-warning/-danger`
|
|
70
99
|
- **Anvand:** Linjar progress med data-bar-width-pattern (CSP-safe via bar-styles.js)
|
|
71
100
|
- **INTE:** Progress med text-overlay (eget komposit-pattern)
|
|
72
101
|
- **Tokens:** `--surface-raised`, `--accent-9`, `--bg-success/-warning/-danger`. Respekterar `prefers-reduced-motion`.
|
|
73
102
|
|
|
74
103
|
### tooltip (`tooltip.css`)
|
|
75
|
-
- **
|
|
104
|
+
- **Blocks:** `.tooltip-wrapper` (compound block, parent i DOM), `.tooltip` (child i DOM, eget CSS-block)
|
|
76
105
|
- **Anvand:** Pure-CSS tooltip via `:hover/:focus-within` pa wrappern
|
|
77
106
|
- **INTE:** Long-content tooltips (anvand `.dialog`)
|
|
78
107
|
- **Tokens:** `--surface-overlay`, `--text-default`, `--border-default`, `--z-tooltip`
|
|
108
|
+
- **Special:** `.tooltip-wrapper` ar compound block, INTE flat-element av `.tooltip`. Wrappern ar utanfor `.tooltip` i DOM (parent, inte child).
|
|
79
109
|
|
|
80
110
|
### dropdown (`dropdown.css`)
|
|
81
|
-
- **
|
|
111
|
+
- **Blocks:** `.dropdown`, `.dropdown-menu`, `.dropdown-item`, `.dropdown-divider` (siblings i dropdown-familjen)
|
|
112
|
+
- **Modifiers:** `.dropdown-item--danger`
|
|
113
|
+
- **States:** `.dropdown.is-open`, `.dropdown.is-open-toggling`
|
|
82
114
|
- **Anvand:** Kontextuell meny (kebab/more-actions). JS togglar `.is-open`
|
|
83
115
|
- **INTE:** Permanent visible navigation (anvand `.nav` eller `.tab-bar`)
|
|
84
116
|
- **Tokens:** `--surface-overlay/-hover/-active`, `--text-default`, `--border-default/-subtle/-focus`, `--bg-danger` (item--danger), `--z-dropdown`
|
|
@@ -87,103 +119,140 @@ inga primitives. BEM-konvention (block__element--modifier).
|
|
|
87
119
|
## Layout-komponenter (v3.0.0+)
|
|
88
120
|
|
|
89
121
|
### banner (`banner.css`)
|
|
90
|
-
- **
|
|
122
|
+
- **Blocks:** `.banner`
|
|
123
|
+
- **Element:** `.banner__title`, `.banner__sub`, `.banner__content`
|
|
124
|
+
- **Modifiers:** `.banner--hero/-accent/-positive/-negative/-warning`
|
|
91
125
|
- **Anvand:** Bred informations-rad i flode (top-of-page eller mellan sektioner)
|
|
92
126
|
- **INTE:** Toast-notifikation (anvand `.toast`)
|
|
93
127
|
|
|
94
128
|
### panel (`panel.css`)
|
|
95
|
-
- **
|
|
129
|
+
- **Blocks:** `.panel`
|
|
130
|
+
- **Element:** `.panel__title`, `.panel__title-row`, `.panel__title-meta`, `.panel__title-link`, `.panel__header-row`, `.panel__step-row`, `.panel__step-badge`, `.panel__pill`
|
|
131
|
+
- **Modifiers:** `.panel--info`, `.panel--info-warning`, `.panel--danger`, `.panel--attention`
|
|
96
132
|
- **Anvand:** Sektion med ramad styling och titel
|
|
97
133
|
- **INTE:** Klickbart kort (anvand `.card--interactive`)
|
|
98
134
|
|
|
99
135
|
### hub-card (`hub-card.css`)
|
|
100
|
-
- **
|
|
136
|
+
- **Blocks:** `.hub-card`, `.hub-list` (sibling-wrapper for kort-lista), `.hub-category` (sibling-rubrik over hub-list)
|
|
137
|
+
- **Element:** `.hub-card__icon`, `.hub-card__text`, `.hub-card__title`, `.hub-card__subtitle`, `.hub-card__chev`
|
|
101
138
|
- **Anvand:** Settings-hub navigation (kort-listor som lankar till sub-sidor)
|
|
102
139
|
- **INTE:** Generic listrader (anvand `.list-row`)
|
|
103
140
|
|
|
104
141
|
### stat (`stat.css`)
|
|
105
|
-
- **
|
|
142
|
+
- **Blocks:** `.stat-grid` (grid-container), `.stat-card` (kort med BEM-element)
|
|
143
|
+
- **Element:** `.stat-card__value`, `.stat-card__label`, `.stat-card__unit`, `.stat-card__sub`
|
|
144
|
+
- **Modifiers:** `.stat-grid--single`, `.stat-card__value--positive/-negative/-accent/-warning`
|
|
106
145
|
- **Anvand:** Sma kort med stor siffra + label (read-only metric-display)
|
|
107
146
|
- **INTE:** Editerbart varde (anvand `.setting-row`)
|
|
108
147
|
|
|
109
148
|
### form (`form.css`)
|
|
110
|
-
- **
|
|
149
|
+
- **Blocks:** `.form-card`, `.form-section`, `.form-group`, `.form-hint`, `.form-row` (fem fristaende blocks i form-familjen)
|
|
150
|
+
- **Element:** `.form-section__title`, `.form-group__label`
|
|
151
|
+
- **Modifiers:** `.form-row--inline`
|
|
152
|
+
- **States:** `.form-group.is-fixed` (anvands inom `.form-row--inline`)
|
|
111
153
|
- **Anvand:** Wrapper-strukturen for formularet
|
|
112
154
|
- **INTE:** Inputs sjalva (egen `.input`)
|
|
113
155
|
|
|
114
156
|
### setting-row (`setting-row.css`)
|
|
115
|
-
- **
|
|
157
|
+
- **Blocks:** `.setting-list` (sibling-wrapper for setting-rows), `.setting-row` (huvud-block med BEM-element), `.setting-toggle` (iOS-stil toggle, sibling-block)
|
|
158
|
+
- **Element:** `.setting-row__text`, `.setting-row__label`, `.setting-row__sub`, `.setting-row__value`, `.setting-row__amount`, `.setting-row__chevron`, `.setting-row__avatar`, `.setting-row__pill`, `.setting-row__form`, `.setting-toggle__track`, `.setting-toggle__thumb`
|
|
159
|
+
- **Modifiers:** `.setting-row--static`, `.setting-row--danger`
|
|
116
160
|
- **Anvand:** Tap-to-edit-rad som triggar bottom-sheet
|
|
117
161
|
- **INTE:** Klickbart kort med rich content (anvand `.hub-card`)
|
|
118
162
|
|
|
119
163
|
### collapsible (`collapsible.css`)
|
|
120
|
-
- **
|
|
164
|
+
- **Blocks:** `.collapsible-card`
|
|
165
|
+
- **Element:** `.collapsible__header`, `.collapsible__header-text`, `.collapsible__chev`, `.collapsible__body`
|
|
166
|
+
- **States:** `[data-expanded]` pa `.collapsible-card`
|
|
121
167
|
- **Anvand:** Panel som expanderar pa klick. JS togglar `data-expanded`
|
|
122
168
|
- **INTE:** Modal-content (anvand `.dialog` eller `.sheet`)
|
|
169
|
+
- **Special:** BEM-stam-mismatch - block heter `.collapsible-card` men element heter `.collapsible__X` (utan `-card`-suffix). Oppen punkt for rename, se sprint-rapport 2026-05-09.
|
|
123
170
|
|
|
124
171
|
### hbar (`hbar.css`)
|
|
125
|
-
- **
|
|
172
|
+
- **Blocks:** `.hbar`
|
|
173
|
+
- **Element:** `.hbar__item`, `.hbar__track`, `.hbar__fill`, `.hbar__label`, `.hbar__value`
|
|
174
|
+
- **Modifiers:** `.hbar__fill--positive/-warning/-negative`
|
|
126
175
|
- **Anvand:** Generisk horisontell bar med label + value + track + fill
|
|
127
176
|
- **INTE:** Status-progress (anvand `.progress`)
|
|
128
177
|
|
|
129
178
|
### split-bar (`split-bar.css`)
|
|
130
|
-
- **
|
|
179
|
+
- **Blocks:** `.split-bar`
|
|
180
|
+
- **Element:** `.split-bar__segment`, `.split-bar__label`, `.split-bar__labels`
|
|
181
|
+
- **Modifiers:** `.split-bar__segment--primary/-secondary/-positive/-negative/-warning`
|
|
131
182
|
- **Anvand:** Flersegment-bar for cost-split, debt-vs-equity m.fl.
|
|
132
183
|
- **INTE:** Single-bar-progress (anvand `.hbar`)
|
|
133
184
|
|
|
134
185
|
### hero (`hero.css`)
|
|
135
|
-
- **
|
|
186
|
+
- **Blocks:** `.hero`, `.hero-amount` (sibling, animation-target - definieras aven i `hero-roll.css`)
|
|
187
|
+
- **Element:** `.hero__heading`, `.hero__amount`, `.hero__amount-row`, `.hero__label`, `.hero__meta`, `.hero__actions`
|
|
188
|
+
- **Modifiers:** `.hero__amount--card`, `.hero__amount--fluid`, `.hero__label--muted`
|
|
136
189
|
- **Anvand:** Stora display-rubriker (80px-skala default, 40px card)
|
|
137
190
|
- **INTE:** Vanlig `<h1>` (anvand `.heading-1`)
|
|
138
191
|
|
|
139
192
|
### chip (`chip.css`)
|
|
140
|
-
- **
|
|
193
|
+
- **Blocks:** `.chip`, `.chip-list` (sibling-wrapper for chips i rad), `.brand-pill`, `.month-pill`, `.score-pill` (definieras aven i `badge.css`), `.install-chip` (PWA install-prompt)
|
|
194
|
+
- **Element:** `.chip-list__item`, `.chip-list__text`, `.chip-list__form`, `.chip-list__delete`, `.chip-list__add`, `.install-chip__text`, `.install-chip__install`, `.install-chip__dismiss`
|
|
195
|
+
- **Modifiers:** `.chip--accent/-positive/-negative/-warning/-faint`, `.score-pill--strong/-medium/-low`
|
|
141
196
|
- **Anvand:** Kort-format pills med dot-prefix (status, kategori, count)
|
|
142
197
|
- **INTE:** Form-inputs (anvand `.input`)
|
|
143
198
|
|
|
144
199
|
### avatar (`avatar.css`)
|
|
145
|
-
- **
|
|
200
|
+
- **Blocks:** `.avatar`
|
|
201
|
+
- **Modifiers:** `.avatar--sm`, `.avatar--lg`
|
|
146
202
|
- **Anvand:** Cirkular initial-avatar med accent-gradient
|
|
147
203
|
- **INTE:** Foto-avatar (overlapp via custom regel)
|
|
148
204
|
|
|
149
205
|
### list-row (`list-row.css`)
|
|
150
|
-
- **
|
|
206
|
+
- **Blocks:** `.list` (sibling-wrapper, `<ul>`-reset), `.list-row` (huvud-block med BEM-element)
|
|
207
|
+
- **Element:** `.list-row__icon`, `.list-row__body`, `.list-row__desc`, `.list-row__meta`, `.list-row__date`, `.list-row__amount`
|
|
208
|
+
- **Modifiers:** `.list-row--excluded`, `.list-row--pending`, `.list-row--clickable`, `.list-row__amount--positive/-negative`
|
|
151
209
|
- **Anvand:** Generisk listrad med ikon + body + amount (transaktioner, audit-log, jobs)
|
|
152
210
|
- **INTE:** Settings-rad (anvand `.setting-row`)
|
|
153
211
|
|
|
154
212
|
### table (`table.css`)
|
|
155
|
-
- **
|
|
213
|
+
- **Blocks:** `.table`
|
|
214
|
+
- **Element:** `.table .num` (descendant-selector)
|
|
156
215
|
- **Anvand:** Tabell med tabular-nums-stod
|
|
157
216
|
- **INTE:** Layout-grid (anvand CSS Grid utility)
|
|
158
217
|
|
|
159
218
|
### auth (`auth.css`)
|
|
160
|
-
- **
|
|
219
|
+
- **Blocks:** `.auth-container`
|
|
220
|
+
- **Element:** `.auth-container__title`, `.auth-container__subtitle`
|
|
161
221
|
- **Anvand:** Centrerad layout for inloggning + onboarding
|
|
162
222
|
- **INTE:** Settings-vyer
|
|
163
223
|
|
|
164
224
|
### swipe-stack (`swipe-stack.css`)
|
|
165
|
-
- **
|
|
225
|
+
- **Blocks:** `.swipe-stack`, `.swipe-card`, `.swipe-decision-overlay`, `.swipe-actions`, `.swipe-action-btn`, `.swipe-meta`, `.swipe-meta-sep`, `.swipe-progress`, `.swipe-empty`, `.swipe-hint` (10 fristaende blocks i swipe-familjen)
|
|
226
|
+
- **Element:** `.swipe-card__header`, `.swipe-card__title`, `.swipe-card__body`, `.swipe-card__footer`
|
|
227
|
+
- **Modifiers:** `.swipe-card--back`, `.swipe-card--gone`, `.swipe-decision-overlay--save/-dismiss/-visible`, `.swipe-action-btn--save/-dismiss`
|
|
166
228
|
- **Anvand:** Tinder-stil swipe-stack med drag-physics
|
|
167
|
-
- **INTE:** Card-galleri (anvand `.card
|
|
229
|
+
- **INTE:** Card-galleri (anvand multipla `.card`)
|
|
168
230
|
|
|
169
231
|
### inline-edit (`inline-edit.css`)
|
|
170
|
-
- **
|
|
232
|
+
- **Blocks:** `.inline-edit`
|
|
233
|
+
- **Element:** `.inline-edit__text`, `.inline-edit__btn`, `.inline-edit__form`, `.inline-edit__input`
|
|
171
234
|
- **Anvand:** Inline-edit av profil-namn, etiketter (pencil-knapp togglar form)
|
|
172
235
|
- **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)
|
|
236
|
+
- **Special:** `.inline-edit__form[hidden]` har explicit `display: none` (paritet med globalt `[hidden]`-stod i base/pwa.css). `.inline-edit__input` anvander `:focus` istallet for `:focus-visible` per text-input-konvention.
|
|
174
237
|
|
|
175
238
|
### upload-spinner (`upload-spinner.css`)
|
|
176
|
-
- **
|
|
239
|
+
- **Blocks:** `.upload-spinner-overlay` (huvud-block), `.upload-spinner` (atomisk, anvands inuti overlay)
|
|
240
|
+
- **Element:** `.upload-spinner-overlay__label`, `.upload-spinner-overlay__hint`
|
|
241
|
+
- **States:** `.upload-spinner-overlay.is-visible`
|
|
177
242
|
- **Anvand:** Viewport-overlay for langa async-operationer (OCR, AI-anrop)
|
|
178
|
-
- **INTE:** Inline-spinner (anvand `.spinner`)
|
|
243
|
+
- **INTE:** Inline-spinner (anvand `.spinner` fran `feedback.css`)
|
|
179
244
|
|
|
180
245
|
### tab-bar (`tab-bar.css`)
|
|
181
|
-
- **
|
|
182
|
-
- **
|
|
246
|
+
- **Blocks:** `.tab-bar` (definieras aven i `nav.css` med 5 identiska properties + skillnad i margin)
|
|
247
|
+
- **Element:** `.tab-bar__item`
|
|
248
|
+
- **States:** `.tab-bar__item.is-active`
|
|
249
|
+
- **Anvand:** Inline tab-grupp for format-val (CSV/Avi etc.) - 44px touch-target
|
|
183
250
|
- **INTE:** Bottom-nav (anvand `.bottom-nav`)
|
|
251
|
+
- **Special:** Importordning i `index.css`: `nav.css` fore `tab-bar.css`. `.tab-bar`-block-styling fran tab-bar.css vinner via cascade.
|
|
184
252
|
|
|
185
253
|
### colored-row (`colored-row.css`) - v3.1.0
|
|
186
|
-
- **
|
|
254
|
+
- **Blocks:** `.colored-row`
|
|
255
|
+
- **Modifiers:** `.colored-row--sm`, `.colored-row--lg`
|
|
187
256
|
- **Anvand:** Kategoriserade rader, fargkodade listor, statusrader -
|
|
188
257
|
med vansterkant fran `--row-accent`-token (default: `--border-subtle`)
|
|
189
258
|
- **INTE:** Rader utan fargkodning (anvand `.list-row` eller plain `.tx-row`)
|
|
@@ -191,13 +260,22 @@ inga primitives. BEM-konvention (block__element--modifier).
|
|
|
191
260
|
- **Pattern:** Se "Kategori-monstret" nedan
|
|
192
261
|
|
|
193
262
|
### colored-bar (`colored-bar.css`) - v3.1.0
|
|
194
|
-
- **
|
|
263
|
+
- **Blocks:** `.colored-bar`
|
|
264
|
+
- **Modifiers:** `.colored-bar--sm`, `.colored-bar--md`, `.colored-bar--lg`, `.colored-bar--vertical`
|
|
195
265
|
- **Anvand:** Budget-staplar, kategori-staplar, progress med semantisk
|
|
196
266
|
farg fran `--bar-accent`-token (default: `--accent-9`)
|
|
197
267
|
- **INTE:** Generisk progress utan kategori (anvand `.progress`)
|
|
198
268
|
- **Tokens:** `--bar-accent` (sattes av app-bindning), `--accent-9` (default)
|
|
199
269
|
- **Pattern:** Se "Kategori-monstret" nedan
|
|
200
270
|
|
|
271
|
+
### sheet-content (`sheet-content.css`) - v3.5.1
|
|
272
|
+
- **Blocks:** `.sheet` (kompletterar `.sheet` fran `overlay.css` med innehall-typografi och form-monster)
|
|
273
|
+
- **Element:** `.sheet__title`, `.sheet__description`, `.sheet__form`, `.sheet__field`, `.sheet__field-label`, `.sheet__hint`, `.sheet__items`, `.sheet__item`, `.sheet__actions`, `.sheet__toggle`, `.sheet__subform`, `.sheet__save`, `.sheet__delete`, `.sheet__handle`, `.sheet__body`, `.sheet__divider` (kompletterande element)
|
|
274
|
+
- **Modifiers:** `.sheet__form--inline`, `.sheet__field-label--upper`, `.sheet__hint--compact`
|
|
275
|
+
- **States:** `.sheet__hint.is-error`, `.sheet__hint--compact.is-error`
|
|
276
|
+
- **Anvand:** Sprint-65 sheet-form-monster (Title + description + Form + Field + Items + Actions + Toggle + Subform)
|
|
277
|
+
- **INTE:** Sheet-overlay sjalv (definieras i `overlay.css`)
|
|
278
|
+
|
|
201
279
|
|
|
202
280
|
## Kategori-monstret
|
|
203
281
|
|
|
@@ -258,3 +336,4 @@ Jubb, Ekonom, framtida appar foljer samma monster med sina egna tokens.
|
|
|
258
336
|
- **`var(--gray-9)` i komponent-CSS.** Komponenter laser bara semantic.
|
|
259
337
|
- **Egen .button-style.** Anvand `.btn` med modifier istallet.
|
|
260
338
|
- **`font-weight: 700`.** Anvand `--fw-medium` (500). Display-siffror ar dokumenterat undantag.
|
|
339
|
+
- **Anta att alla komponent-filer har ett root-block.** 17 av 35 komponent-filer har flera root-blocks - se regel 11 i `references/03-quality-bar.md`.
|
|
@@ -210,7 +210,83 @@ Varje interaktiv komponent SKA ha:
|
|
|
210
210
|
annan 0.7, snart finns alla varianter och visuellt sprak ar splittrat
|
|
211
211
|
|
|
212
212
|
|
|
213
|
-
## 11.
|
|
213
|
+
## 11. En fil kan innehalla flera root-blocks
|
|
214
|
+
|
|
215
|
+
I 17 av 35 komponent-filer i paketet definieras flera root-blocks i
|
|
216
|
+
samma fil (`form.css`, `nav.css`, `chip.css`, `swipe-stack.css`,
|
|
217
|
+
`feedback.css`, `hub-card.css` m.fl.). Det ar en medveten konvention,
|
|
218
|
+
inte ett undantag eller teknisk skuld.
|
|
219
|
+
|
|
220
|
+
**Nar det ar korrekt att samla flera blocks i en fil:**
|
|
221
|
+
- **Semantiskt relaterade:** blocks som tillhor samma tema (form-skelett,
|
|
222
|
+
feedback-states, navigation-monster, swipe-card-familjen)
|
|
223
|
+
- **Anvands i kombination:** wrapper + child-block som alltid renderas
|
|
224
|
+
tillsammans (`.hub-list` + `.hub-card`, `.list` + `.list-row`,
|
|
225
|
+
`.progress` + `.progress-bar`)
|
|
226
|
+
- **Sibling-relation:** blocks som placeras parallellt i HTML men aldrig
|
|
227
|
+
ar BEM-element av varandra (`.hub-category` + `.hub-list`,
|
|
228
|
+
`.input-group` + `.input-icon` som siblings till `.input`)
|
|
229
|
+
|
|
230
|
+
**Nar det INTE ar korrekt:**
|
|
231
|
+
- Tva orelaterade komponenter staplade i samma fil av bekvamlighet
|
|
232
|
+
- Ett block som logiskt kunde varit BEM-element av ett annat - i sa
|
|
233
|
+
fall ska det vara `.X__Y`, inte `.X-Y` som separat block
|
|
234
|
+
|
|
235
|
+
**Hur de ska dokumenteras:**
|
|
236
|
+
|
|
237
|
+
JSDoc-header i CSS-filen ska ha en `Blocks:`-sektion som listar varje
|
|
238
|
+
root-block med en kort beskrivning + relation:
|
|
239
|
+
|
|
240
|
+
```css
|
|
241
|
+
/* ================================================================
|
|
242
|
+
components/example.css
|
|
243
|
+
[Kort beskrivning av filens syfte]
|
|
244
|
+
|
|
245
|
+
Blocks:
|
|
246
|
+
.block-a - [vad den gor]
|
|
247
|
+
.block-b - sibling-wrapper for [...]
|
|
248
|
+
.block-c - atomisk, anvands inuti .block-a
|
|
249
|
+
|
|
250
|
+
HTML-relationer (om ej uppenbara):
|
|
251
|
+
.block-c placeras alltid som child av .block-a i HTML
|
|
252
|
+
================================================================ */
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
I `references/02-components.md` listas root-blocks under
|
|
256
|
+
`**Blocks:**`-raden, BEM-element under `**Element:**`, modifiers under
|
|
257
|
+
`**Modifiers:**`, state-classes under `**States:**`. Sibling- och
|
|
258
|
+
wrapper-relationer noteras i parentes.
|
|
259
|
+
|
|
260
|
+
**Konkret exempel:** `hub-card.css` har tre fristaende blocks:
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
.hub-card - klickbart kort (huvud-block med BEM-element)
|
|
264
|
+
.hub-list - <ul>-wrapper for flera hub-cards (sibling)
|
|
265
|
+
.hub-category - <h6>-rubrik over hub-list (sibling, placeras FORE)
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
I HTML ligger `.hub-category` som syskon till `.hub-list`, inte inuti
|
|
269
|
+
det. Bara `.hub-card` har egna BEM-element (`__icon/__text/__title`).
|
|
270
|
+
|
|
271
|
+
**Varfor:**
|
|
272
|
+
- Semantisk gruppering > arbitrar fil-uppdelning. Att splittra
|
|
273
|
+
`.form-card/.form-section/.form-group` i tre filer ger inget varde -
|
|
274
|
+
de hor ihop som "form-skelett".
|
|
275
|
+
- Auditer ska kunna lasa filens kommentar och forsta strukturen utan
|
|
276
|
+
att behova rekonstruera den fran selektor-mosaik.
|
|
277
|
+
- BEM-falska-positiv minimeras. En extern reviewer som ser `.hub-list`
|
|
278
|
+
ska kunna avgora om det ar ett brott (compound block i fel fil) eller
|
|
279
|
+
konvention (sibling i samma fil).
|
|
280
|
+
|
|
281
|
+
**Trade-off:**
|
|
282
|
+
- Kraver disciplinerad JSDoc + 02-components.md-underhall vid varje ny
|
|
283
|
+
komponent. Utan det blir flera-blocks-i-samma-fil ett mysterium.
|
|
284
|
+
- Risk for junk-drawer-filer dar olika blocks staplas av lathet.
|
|
285
|
+
Mitigation: granska om varje nytt block hor ihop tematiskt eller
|
|
286
|
+
borde fa egen fil.
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
## 12. Inter font + Linear-stack
|
|
214
290
|
|
|
215
291
|
**Hur man foljer:**
|
|
216
292
|
- Anvand `var(--font-sans)` overallt - ALDRIG specifika font-family-
|
|
@@ -230,7 +306,7 @@ Varje interaktiv komponent SKA ha:
|
|
|
230
306
|
- Linear, Vercel och liknande modern SaaS anvander samma stack
|
|
231
307
|
|
|
232
308
|
|
|
233
|
-
##
|
|
309
|
+
## 13. Bara nya semantic token-namn
|
|
234
310
|
|
|
235
311
|
**Hur man foljer:**
|
|
236
312
|
- Anvand bara nya semantic-namn: `--text-default/-subtle/-muted/-disabled`,
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# 0009 - collapsible block-rename: .collapsible-card → .collapsible
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
Locked. Beslutat 2026-05-09.
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
collapsible.css definierade root-blocket som `.collapsible-card` men
|
|
8
|
+
BEM-elementen som `.collapsible__header`, `.collapsible__body`,
|
|
9
|
+
`.collapsible__chev`, `.collapsible__header-text`. BEM-stammen var
|
|
10
|
+
inkonsekvent: elementen antydde att parent-blocket borde heta
|
|
11
|
+
`.collapsible`, inte `.collapsible-card`.
|
|
12
|
+
|
|
13
|
+
Fyndet identifierades i paritetsaudit 2026-05-09 (undersökning 4).
|
|
14
|
+
Underlaget visade:
|
|
15
|
+
|
|
16
|
+
- 3 produktion-templates i Ekonom (avstamning.html)
|
|
17
|
+
- 3 showcase-templates i Ekonom (design.html)
|
|
18
|
+
- 3 showcase-templates i Jubb (design.html)
|
|
19
|
+
- 0 produktion-templates i Jubb
|
|
20
|
+
- 0 lokala CSS-overrides i någon app
|
|
21
|
+
- JS-koppling via [data-collapsible]-attribut, inte via klasnamn
|
|
22
|
+
(en querySelector på .collapsible__body i Ekonom app.js rad 202)
|
|
23
|
+
|
|
24
|
+
## Considered options
|
|
25
|
+
|
|
26
|
+
### Alternativ A: rename block .collapsible-card → .collapsible
|
|
27
|
+
Elementen (.collapsible__header etc.) oförändrade.
|
|
28
|
+
~12 ändringar: 1 CSS-fil + 2 template-filer per app.
|
|
29
|
+
JS opåverkat (data-attribut-koppling).
|
|
30
|
+
|
|
31
|
+
### Alternativ B: rename element .collapsible__X → .collapsible-card__X
|
|
32
|
+
Blocket (.collapsible-card) oförändrat.
|
|
33
|
+
~15 ändringar + 1 JS-ändring (app.js rad 202).
|
|
34
|
+
|
|
35
|
+
## Decision
|
|
36
|
+
**Alternativ A.** Elementen är rätt — `.collapsible__` speglar det
|
|
37
|
+
semantiska begreppet. Blocket är det som avviker. "-card"-suffixet är
|
|
38
|
+
en implementationsdetalj från ursprunglig skapelse, inte en semantisk
|
|
39
|
+
egenskap. JS-kopplingen via data-attribut gör att rename är renare än
|
|
40
|
+
Alternativ B.
|
|
41
|
+
|
|
42
|
+
## Consequences
|
|
43
|
+
- + BEM-stammen är konsekvent: .collapsible → .collapsible__header etc.
|
|
44
|
+
- + JS opåverkat
|
|
45
|
+
- + Färre ändringar än Alternativ B
|
|
46
|
+
- − Template-ändringar krävs i Ekonom produktion (3 rader) och
|
|
47
|
+
showcase i båda appar (6 rader)
|
|
48
|
+
- − npm minor version-bump krävs (publik klass-rename är breaking change)
|