@klodd/ds 1.0.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/README.md +120 -0
- package/css/00-primitives.css +337 -0
- package/css/10-semantic.css +432 -0
- package/css/apps/ekonom.css +17 -0
- package/css/apps/jubb.css +15 -0
- package/css/base/pwa.css +53 -0
- package/css/base/typography.css +122 -0
- package/css/components/badge.css +98 -0
- package/css/components/button.css +200 -0
- package/css/components/card.css +86 -0
- package/css/components/feedback.css +187 -0
- package/css/components/hero-roll.css +129 -0
- package/css/components/icon.css +60 -0
- package/css/components/input.css +144 -0
- package/css/components/nav.css +192 -0
- package/css/components/overlay.css +128 -0
- package/css/index.css +28 -0
- package/package.json +23 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/* ================================================================
|
|
2
|
+
components/icon.css
|
|
3
|
+
.icon - generisk ikon-wrapper med fem size-modifiers.
|
|
4
|
+
Anvands for bade Lucide-ikoner (via <i data-lucide="X" class="icon icon--md">)
|
|
5
|
+
och custom inline-SVG (<svg class="icon icon--md">).
|
|
6
|
+
|
|
7
|
+
color: currentColor sa parent-elementet styr fargen via color-property.
|
|
8
|
+
|
|
9
|
+
Custom SVG-monster (.icon-custom svg) ger standardiserade
|
|
10
|
+
stroke-attribut for handritade ikoner som Lucide saknar.
|
|
11
|
+
================================================================ */
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/* ================================================================
|
|
15
|
+
==== BAS
|
|
16
|
+
================================================================ */
|
|
17
|
+
.icon {
|
|
18
|
+
display: inline-flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
justify-content: center;
|
|
21
|
+
flex-shrink: 0;
|
|
22
|
+
color: currentColor;
|
|
23
|
+
vertical-align: middle;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* Lucide ersatter <i data-lucide="X"> med <svg>. Tvinga svg att fylla
|
|
27
|
+
wrappern sa size-modifiers fungerar konsekvent. */
|
|
28
|
+
.icon > svg {
|
|
29
|
+
width: 100%;
|
|
30
|
+
height: 100%;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
/* ================================================================
|
|
35
|
+
==== STORLEKAR
|
|
36
|
+
--md ar default storlek (20px). Anvand --xs/--sm/--lg/--xl explicit.
|
|
37
|
+
================================================================ */
|
|
38
|
+
.icon--xs { width: var(--space-12); height: var(--space-12); }
|
|
39
|
+
.icon--sm { width: var(--space-16); height: var(--space-16); }
|
|
40
|
+
.icon--md { width: var(--space-20); height: var(--space-20); }
|
|
41
|
+
.icon--lg { width: var(--space-24); height: var(--space-24); }
|
|
42
|
+
.icon--xl { width: var(--space-32); height: var(--space-32); }
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
/* ================================================================
|
|
46
|
+
==== CUSTOM SVG-MONSTER
|
|
47
|
+
App-specifika ikoner som Lucide saknar. Anvand som wrapper:
|
|
48
|
+
<span class="icon icon--md icon-custom">
|
|
49
|
+
<svg viewBox="0 0 24 24">...</svg>
|
|
50
|
+
</span>
|
|
51
|
+
stroke-width 1.5 matchar Lucide-default. linecap/linejoin round
|
|
52
|
+
ger samma mjuka look.
|
|
53
|
+
================================================================ */
|
|
54
|
+
.icon-custom svg {
|
|
55
|
+
fill: none;
|
|
56
|
+
stroke: currentColor;
|
|
57
|
+
stroke-width: 1.5;
|
|
58
|
+
stroke-linecap: round;
|
|
59
|
+
stroke-linejoin: round;
|
|
60
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/* ================================================================
|
|
2
|
+
components/input.css
|
|
3
|
+
.input + .textarea + .select med konsekvent styling.
|
|
4
|
+
States: :focus, :disabled, [aria-invalid="true"] (error).
|
|
5
|
+
Tillagg: .input-group (label + input + error), .input-icon (input
|
|
6
|
+
med leading ikon).
|
|
7
|
+
|
|
8
|
+
Regel: font-size 17px sa iOS Safari inte auto-zoomar in vid focus.
|
|
9
|
+
Aldrig under 16px pa input-element.
|
|
10
|
+
================================================================ */
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/* ================================================================
|
|
14
|
+
==== BAS
|
|
15
|
+
================================================================ */
|
|
16
|
+
.input,
|
|
17
|
+
.textarea,
|
|
18
|
+
.select {
|
|
19
|
+
display: block;
|
|
20
|
+
width: 100%;
|
|
21
|
+
min-height: var(--touch-min);
|
|
22
|
+
padding: 0 var(--space-14);
|
|
23
|
+
font-family: inherit;
|
|
24
|
+
font-size: var(--fs-17);
|
|
25
|
+
line-height: 1.4;
|
|
26
|
+
color: var(--text-default);
|
|
27
|
+
background: var(--surface-sunken);
|
|
28
|
+
border: 1px solid var(--border-default);
|
|
29
|
+
border-radius: var(--radius-10);
|
|
30
|
+
outline: none;
|
|
31
|
+
transition:
|
|
32
|
+
border-color var(--dur-base) var(--ease-spring-snappy),
|
|
33
|
+
box-shadow var(--dur-base) var(--ease-spring-snappy),
|
|
34
|
+
background var(--dur-base) var(--ease-spring-snappy);
|
|
35
|
+
-webkit-appearance: none;
|
|
36
|
+
appearance: none;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.textarea {
|
|
40
|
+
min-height: 96px;
|
|
41
|
+
padding: var(--space-12) var(--space-14);
|
|
42
|
+
line-height: var(--lh-base);
|
|
43
|
+
resize: vertical;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.select {
|
|
47
|
+
padding-right: var(--space-32);
|
|
48
|
+
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2390919E' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
|
|
49
|
+
background-repeat: no-repeat;
|
|
50
|
+
background-position: right var(--space-12) center;
|
|
51
|
+
background-size: 14px;
|
|
52
|
+
cursor: pointer;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.input::placeholder,
|
|
56
|
+
.textarea::placeholder {
|
|
57
|
+
color: var(--text-muted);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
/* ================================================================
|
|
62
|
+
==== STATES
|
|
63
|
+
================================================================ */
|
|
64
|
+
.input:focus,
|
|
65
|
+
.textarea:focus,
|
|
66
|
+
.select:focus {
|
|
67
|
+
border-color: var(--accent-9);
|
|
68
|
+
box-shadow: 0 0 0 3px var(--accent-a20);
|
|
69
|
+
background: var(--surface-default);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.input:disabled,
|
|
73
|
+
.textarea:disabled,
|
|
74
|
+
.select:disabled {
|
|
75
|
+
opacity: 0.5;
|
|
76
|
+
cursor: not-allowed;
|
|
77
|
+
background: var(--surface-default);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.input[aria-invalid="true"],
|
|
81
|
+
.textarea[aria-invalid="true"],
|
|
82
|
+
.select[aria-invalid="true"] {
|
|
83
|
+
border-color: var(--bg-danger);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.input[aria-invalid="true"]:focus,
|
|
87
|
+
.textarea[aria-invalid="true"]:focus,
|
|
88
|
+
.select[aria-invalid="true"]:focus {
|
|
89
|
+
box-shadow: 0 0 0 3px color-mix(in oklch, var(--bg-danger) 20%, transparent);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
/* ================================================================
|
|
94
|
+
==== INPUT-GROUP (label + input + error)
|
|
95
|
+
Wrapper for ett komplett input-falt med metadata.
|
|
96
|
+
================================================================ */
|
|
97
|
+
.input-group {
|
|
98
|
+
display: flex;
|
|
99
|
+
flex-direction: column;
|
|
100
|
+
gap: var(--space-6);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.input-group__label {
|
|
104
|
+
font-size: var(--fs-12);
|
|
105
|
+
font-weight: var(--fw-medium);
|
|
106
|
+
color: var(--text-subtle);
|
|
107
|
+
letter-spacing: 0.02em;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.input-group__hint {
|
|
111
|
+
font-size: var(--fs-11);
|
|
112
|
+
color: var(--text-muted);
|
|
113
|
+
line-height: var(--lh-base);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.input-group__error {
|
|
117
|
+
font-size: var(--fs-11);
|
|
118
|
+
color: var(--bg-danger);
|
|
119
|
+
line-height: var(--lh-base);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
/* ================================================================
|
|
124
|
+
==== INPUT-ICON (leading icon)
|
|
125
|
+
Wrapper med ikon till vanster om input. Anvands for sok-falt eller
|
|
126
|
+
amount-input med suffix.
|
|
127
|
+
================================================================ */
|
|
128
|
+
.input-icon {
|
|
129
|
+
position: relative;
|
|
130
|
+
display: flex;
|
|
131
|
+
align-items: center;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.input-icon > .icon,
|
|
135
|
+
.input-icon > svg {
|
|
136
|
+
position: absolute;
|
|
137
|
+
left: var(--space-12);
|
|
138
|
+
pointer-events: none;
|
|
139
|
+
color: var(--text-muted);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.input-icon > .input {
|
|
143
|
+
padding-left: var(--space-40);
|
|
144
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/* ================================================================
|
|
2
|
+
components/nav.css
|
|
3
|
+
Bottom-nav, topbar och tab-bar - tre standardnavigations-monster.
|
|
4
|
+
|
|
5
|
+
Bottom-nav ar position:fixed och ALLTID synlig pa mobil. Topbar
|
|
6
|
+
ar in-flow under safe-area. Tab-bar ar inline (inom en panel).
|
|
7
|
+
================================================================ */
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
/* ================================================================
|
|
11
|
+
==== BOTTOM-NAV (fixed, mobil-primar)
|
|
12
|
+
Edge-to-edge pa botten med safe-area-padding for hemskarms-knapp.
|
|
13
|
+
N kolumner via grid (--bottom-nav-cols custom property om appen
|
|
14
|
+
vill annat an default 4).
|
|
15
|
+
================================================================ */
|
|
16
|
+
.bottom-nav {
|
|
17
|
+
position: fixed;
|
|
18
|
+
bottom: 0;
|
|
19
|
+
left: 0;
|
|
20
|
+
right: 0;
|
|
21
|
+
z-index: var(--z-nav);
|
|
22
|
+
display: grid;
|
|
23
|
+
grid-template-columns: repeat(var(--bottom-nav-cols, 4), 1fr);
|
|
24
|
+
padding: 0;
|
|
25
|
+
padding-bottom: var(--safe-bottom);
|
|
26
|
+
margin: 0;
|
|
27
|
+
max-width: none;
|
|
28
|
+
background: var(--surface-default);
|
|
29
|
+
border: 0;
|
|
30
|
+
border-top: 1px solid var(--border-subtle);
|
|
31
|
+
border-radius: 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.bottom-nav-item {
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-direction: column;
|
|
37
|
+
align-items: center;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
gap: var(--space-4);
|
|
40
|
+
min-height: var(--touch-min);
|
|
41
|
+
padding: var(--space-8) var(--space-6);
|
|
42
|
+
font-size: var(--fs-10);
|
|
43
|
+
font-weight: var(--fw-medium);
|
|
44
|
+
color: var(--text-muted);
|
|
45
|
+
text-decoration: none;
|
|
46
|
+
-webkit-tap-highlight-color: transparent;
|
|
47
|
+
touch-action: manipulation;
|
|
48
|
+
transition:
|
|
49
|
+
color var(--dur-base) var(--ease-spring-snappy),
|
|
50
|
+
background var(--dur-base) var(--ease-spring-snappy);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@media (hover: hover) and (pointer: fine) {
|
|
54
|
+
.bottom-nav-item:hover {
|
|
55
|
+
color: var(--text-default);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.bottom-nav-item.active {
|
|
60
|
+
color: var(--accent-text);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.bottom-nav-item .icon,
|
|
64
|
+
.bottom-nav-item svg {
|
|
65
|
+
width: var(--space-20);
|
|
66
|
+
height: var(--space-20);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
/* ================================================================
|
|
71
|
+
==== TOPBAR (in-flow header)
|
|
72
|
+
Tre slots: back-knapp / titel / action. Display flex, full bredd.
|
|
73
|
+
================================================================ */
|
|
74
|
+
.topbar {
|
|
75
|
+
display: flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
gap: var(--space-12);
|
|
78
|
+
min-height: var(--touch-min);
|
|
79
|
+
padding: 0 var(--space-4);
|
|
80
|
+
margin-bottom: var(--space-16);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.topbar-back {
|
|
84
|
+
display: inline-flex;
|
|
85
|
+
align-items: center;
|
|
86
|
+
justify-content: center;
|
|
87
|
+
width: 36px;
|
|
88
|
+
height: 36px;
|
|
89
|
+
padding: 0;
|
|
90
|
+
border: 1px solid var(--border-subtle);
|
|
91
|
+
border-radius: var(--radius-full);
|
|
92
|
+
background: var(--surface-default);
|
|
93
|
+
color: var(--text-default);
|
|
94
|
+
cursor: pointer;
|
|
95
|
+
flex-shrink: 0;
|
|
96
|
+
transition: background var(--dur-base) var(--ease-spring-snappy);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@media (hover: hover) and (pointer: fine) {
|
|
100
|
+
.topbar-back:hover {
|
|
101
|
+
background: var(--surface-hover);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.topbar-back:focus-visible {
|
|
106
|
+
outline: 2px solid var(--border-focus);
|
|
107
|
+
outline-offset: 2px;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.topbar-title {
|
|
111
|
+
flex: 1;
|
|
112
|
+
min-width: 0;
|
|
113
|
+
font-size: var(--fs-17);
|
|
114
|
+
font-weight: var(--fw-medium);
|
|
115
|
+
line-height: var(--lh-tight);
|
|
116
|
+
color: var(--text-default);
|
|
117
|
+
margin: 0;
|
|
118
|
+
overflow: hidden;
|
|
119
|
+
text-overflow: ellipsis;
|
|
120
|
+
white-space: nowrap;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.topbar-action {
|
|
124
|
+
display: inline-flex;
|
|
125
|
+
align-items: center;
|
|
126
|
+
justify-content: center;
|
|
127
|
+
min-width: 36px;
|
|
128
|
+
min-height: 36px;
|
|
129
|
+
padding: 0 var(--space-10);
|
|
130
|
+
background: transparent;
|
|
131
|
+
border: 0;
|
|
132
|
+
color: var(--text-subtle);
|
|
133
|
+
cursor: pointer;
|
|
134
|
+
flex-shrink: 0;
|
|
135
|
+
transition: color var(--dur-base) var(--ease-spring-snappy);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@media (hover: hover) and (pointer: fine) {
|
|
139
|
+
.topbar-action:hover {
|
|
140
|
+
color: var(--text-default);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
/* ================================================================
|
|
146
|
+
==== TAB-BAR (inline tabs i panel)
|
|
147
|
+
Segmented control monster. Active-tab har highlighted bg.
|
|
148
|
+
================================================================ */
|
|
149
|
+
.tab-bar {
|
|
150
|
+
display: flex;
|
|
151
|
+
gap: var(--space-4);
|
|
152
|
+
padding: var(--space-4);
|
|
153
|
+
background: var(--surface-default);
|
|
154
|
+
border-radius: var(--radius-12);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.tab {
|
|
158
|
+
flex: 1;
|
|
159
|
+
display: inline-flex;
|
|
160
|
+
align-items: center;
|
|
161
|
+
justify-content: center;
|
|
162
|
+
min-height: 36px;
|
|
163
|
+
padding: 0 var(--space-12);
|
|
164
|
+
font-family: inherit;
|
|
165
|
+
font-size: var(--fs-13);
|
|
166
|
+
font-weight: var(--fw-medium);
|
|
167
|
+
color: var(--text-subtle);
|
|
168
|
+
background: transparent;
|
|
169
|
+
border: 0;
|
|
170
|
+
border-radius: var(--radius-8);
|
|
171
|
+
cursor: pointer;
|
|
172
|
+
text-decoration: none;
|
|
173
|
+
transition:
|
|
174
|
+
background var(--dur-fast) var(--ease-spring-snappy),
|
|
175
|
+
color var(--dur-fast) var(--ease-spring-snappy);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@media (hover: hover) and (pointer: fine) {
|
|
179
|
+
.tab:not(.active):hover {
|
|
180
|
+
color: var(--text-default);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.tab.active {
|
|
185
|
+
background: var(--surface-raised);
|
|
186
|
+
color: var(--text-default);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.tab:focus-visible {
|
|
190
|
+
outline: 2px solid var(--border-focus);
|
|
191
|
+
outline-offset: 1px;
|
|
192
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/* ================================================================
|
|
2
|
+
components/overlay.css
|
|
3
|
+
Dialog/modal och bottom-sheet - tva overlay-monster.
|
|
4
|
+
|
|
5
|
+
Dialog: centrerad modal for forms och bekraftelser.
|
|
6
|
+
Sheet: bottom-attached for mobile-first sheet-monster.
|
|
7
|
+
|
|
8
|
+
Bagge anvander backdrop med blur for visuell hierarki.
|
|
9
|
+
================================================================ */
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
/* ================================================================
|
|
13
|
+
==== DIALOG-BACKDROP
|
|
14
|
+
Halvtransparent overlay med blur. Anvands av bade .dialog och
|
|
15
|
+
.sheet. native ::backdrop pseudo-element (om <dialog>) eller en
|
|
16
|
+
konkret <div class="dialog-backdrop"> for portal-baserade modaler.
|
|
17
|
+
================================================================ */
|
|
18
|
+
.dialog-backdrop,
|
|
19
|
+
dialog.dialog::backdrop,
|
|
20
|
+
dialog.sheet::backdrop {
|
|
21
|
+
background: color-mix(in oklch, var(--surface-page) 60%, transparent);
|
|
22
|
+
-webkit-backdrop-filter: blur(4px);
|
|
23
|
+
backdrop-filter: blur(4px);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
/* ================================================================
|
|
28
|
+
==== DIALOG (centrerad modal)
|
|
29
|
+
Native <dialog>-element rekommenderas for fokus-trap + ESC-stang.
|
|
30
|
+
Klassen .dialog kan ocksa anvandas pa <div role="dialog"> nar
|
|
31
|
+
native inte passar (ex. icke-modal panel).
|
|
32
|
+
================================================================ */
|
|
33
|
+
.dialog {
|
|
34
|
+
position: fixed;
|
|
35
|
+
top: 50%;
|
|
36
|
+
left: 50%;
|
|
37
|
+
transform: translate(-50%, -50%);
|
|
38
|
+
z-index: var(--z-overlay);
|
|
39
|
+
width: calc(100vw - 2 * var(--space-20));
|
|
40
|
+
max-width: 480px;
|
|
41
|
+
max-height: calc(100dvh - 2 * var(--space-40));
|
|
42
|
+
margin: 0;
|
|
43
|
+
padding: 0;
|
|
44
|
+
background: var(--surface-raised);
|
|
45
|
+
color: var(--text-default);
|
|
46
|
+
border: 1px solid var(--border-subtle);
|
|
47
|
+
border-radius: var(--radius-14);
|
|
48
|
+
box-shadow: var(--shadow-float);
|
|
49
|
+
overflow: hidden;
|
|
50
|
+
/* Native <dialog>: aterstall default-sytling. */
|
|
51
|
+
inset: auto;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.dialog-header {
|
|
55
|
+
display: flex;
|
|
56
|
+
align-items: center;
|
|
57
|
+
justify-content: space-between;
|
|
58
|
+
gap: var(--space-12);
|
|
59
|
+
padding: var(--space-16) var(--space-20);
|
|
60
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.dialog-body {
|
|
64
|
+
padding: var(--space-20);
|
|
65
|
+
overflow-y: auto;
|
|
66
|
+
max-height: 60vh;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.dialog-footer {
|
|
70
|
+
display: flex;
|
|
71
|
+
justify-content: flex-end;
|
|
72
|
+
gap: var(--space-8);
|
|
73
|
+
padding: var(--space-12) var(--space-20);
|
|
74
|
+
border-top: 1px solid var(--border-subtle);
|
|
75
|
+
background: var(--surface-default);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
/* ================================================================
|
|
80
|
+
==== SHEET (bottom-attached)
|
|
81
|
+
<dialog class="sheet"> ar standardpattern. Native focus-trap, ESC,
|
|
82
|
+
::backdrop. JS anvander .showModal() / .close().
|
|
83
|
+
|
|
84
|
+
max-height 90svh sa sheet alltid laemnar lite plats overst sa
|
|
85
|
+
anvandaren ser kontexten bakom.
|
|
86
|
+
================================================================ */
|
|
87
|
+
.sheet {
|
|
88
|
+
position: fixed;
|
|
89
|
+
bottom: 0;
|
|
90
|
+
left: 0;
|
|
91
|
+
right: 0;
|
|
92
|
+
top: auto;
|
|
93
|
+
z-index: var(--z-overlay);
|
|
94
|
+
width: 100%;
|
|
95
|
+
max-width: 600px;
|
|
96
|
+
max-height: 90svh;
|
|
97
|
+
margin: 0 auto;
|
|
98
|
+
padding: var(--space-8) var(--space-20) calc(var(--space-28) + var(--safe-bottom));
|
|
99
|
+
background: var(--surface-raised);
|
|
100
|
+
color: var(--text-default);
|
|
101
|
+
border: 1px solid var(--border-subtle);
|
|
102
|
+
border-bottom: 0;
|
|
103
|
+
border-radius: var(--radius-24) var(--radius-24) 0 0;
|
|
104
|
+
box-shadow: var(--shadow-float);
|
|
105
|
+
overflow-y: auto;
|
|
106
|
+
overscroll-behavior: contain;
|
|
107
|
+
-webkit-overflow-scrolling: touch;
|
|
108
|
+
inset: auto 0 0 0;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.sheet-handle {
|
|
112
|
+
width: 32px;
|
|
113
|
+
height: 4px;
|
|
114
|
+
margin: 0 auto var(--space-16);
|
|
115
|
+
background: var(--text-disabled);
|
|
116
|
+
border-radius: var(--radius-full);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.sheet-body {
|
|
120
|
+
padding-top: var(--space-4);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* Sheet-section divider for grupper inom samma sheet. */
|
|
124
|
+
.sheet-divider {
|
|
125
|
+
height: 1px;
|
|
126
|
+
background: var(--border-subtle);
|
|
127
|
+
margin: var(--space-16) calc(-1 * var(--space-20));
|
|
128
|
+
}
|
package/css/index.css
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/* ================================================================
|
|
2
|
+
@klodd/ds - convenience-import
|
|
3
|
+
Importerar hela designsystemet i kanonisk ordning. App-specifika
|
|
4
|
+
tema-filer (apps/jubb.css, apps/ekonom.css) importeras separat
|
|
5
|
+
eftersom bara en ar aktiv per pageload.
|
|
6
|
+
|
|
7
|
+
Anvandning:
|
|
8
|
+
<link rel="stylesheet" href="@klodd/ds/css/index.css">
|
|
9
|
+
<link rel="stylesheet" href="@klodd/ds/css/apps/jubb.css">
|
|
10
|
+
|
|
11
|
+
Eller via CSS:
|
|
12
|
+
@import '@klodd/ds/css/index.css';
|
|
13
|
+
@import '@klodd/ds/css/apps/jubb.css';
|
|
14
|
+
================================================================ */
|
|
15
|
+
|
|
16
|
+
@import './00-primitives.css';
|
|
17
|
+
@import './10-semantic.css';
|
|
18
|
+
@import './base/pwa.css';
|
|
19
|
+
@import './base/typography.css';
|
|
20
|
+
@import './components/button.css';
|
|
21
|
+
@import './components/input.css';
|
|
22
|
+
@import './components/badge.css';
|
|
23
|
+
@import './components/card.css';
|
|
24
|
+
@import './components/nav.css';
|
|
25
|
+
@import './components/feedback.css';
|
|
26
|
+
@import './components/overlay.css';
|
|
27
|
+
@import './components/icon.css';
|
|
28
|
+
@import './components/hero-roll.css';
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@klodd/ds",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Klodd Design System - shared tokens, typography, and components for Jubb, Ekonom, and future apps",
|
|
5
|
+
"main": "css/index.css",
|
|
6
|
+
"files": [
|
|
7
|
+
"css/"
|
|
8
|
+
],
|
|
9
|
+
"keywords": [
|
|
10
|
+
"design-system",
|
|
11
|
+
"css",
|
|
12
|
+
"tokens",
|
|
13
|
+
"dark-mode",
|
|
14
|
+
"radix-colors"
|
|
15
|
+
],
|
|
16
|
+
"author": "Carl-Eric Persson",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/drawn124578/klodd-ds.git"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/drawn124578/klodd-ds#readme"
|
|
23
|
+
}
|