@oslokommune/punkt-css 16.26.2 → 17.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.
Files changed (75) hide show
  1. package/CHANGELOG.md +111 -0
  2. package/dist/css/components/accordion.css +27 -5
  3. package/dist/css/components/accordion.min.css +1 -1
  4. package/dist/css/components/alert.css +37 -9
  5. package/dist/css/components/alert.min.css +1 -1
  6. package/dist/css/components/calendar.css +4 -0
  7. package/dist/css/components/calendar.min.css +1 -1
  8. package/dist/css/components/combobox.css +82 -0
  9. package/dist/css/components/combobox.min.css +1 -1
  10. package/dist/css/components/datepicker.css +82 -3
  11. package/dist/css/components/datepicker.min.css +1 -1
  12. package/dist/css/components/footer.css +232 -108
  13. package/dist/css/components/footer.min.css +1 -1
  14. package/dist/css/components/header-global.css +287 -0
  15. package/dist/css/components/header-global.min.css +1 -0
  16. package/dist/css/components/header-menu.css +364 -123
  17. package/dist/css/components/header-menu.min.css +1 -1
  18. package/dist/css/components/header-service-mobile.css +71 -22
  19. package/dist/css/components/header-service-mobile.min.css +1 -1
  20. package/dist/css/components/header-service.css +68 -14
  21. package/dist/css/components/header-service.min.css +1 -1
  22. package/dist/css/components/header-shared.css +49 -0
  23. package/dist/css/components/header-shared.min.css +0 -0
  24. package/dist/css/components/inputwrapper.css +59 -5
  25. package/dist/css/components/inputwrapper.min.css +1 -1
  26. package/dist/css/components/modal.css +0 -5
  27. package/dist/css/components/modal.min.css +1 -1
  28. package/dist/css/components/searchinput.css +71 -2
  29. package/dist/css/components/searchinput.min.css +1 -1
  30. package/dist/css/components/textarea.css +41 -0
  31. package/dist/css/components/textarea.min.css +1 -0
  32. package/dist/css/components/textinput.css +126 -6
  33. package/dist/css/components/textinput.min.css +1 -1
  34. package/dist/css/components/timepicker.css +133 -38
  35. package/dist/css/components/timepicker.min.css +1 -1
  36. package/dist/css/elements/button.css +20 -4
  37. package/dist/css/elements/button.min.css +1 -1
  38. package/dist/css/elements/checkbox-radio.css +3 -3
  39. package/dist/css/elements/checkbox-radio.min.css +1 -1
  40. package/dist/css/elements/input.css +121 -6
  41. package/dist/css/elements/input.min.css +1 -1
  42. package/dist/css/elements/select.css +137 -9
  43. package/dist/css/elements/select.min.css +1 -1
  44. package/dist/css/pkt-base.css +434 -1
  45. package/dist/css/pkt-base.min.css +1 -1
  46. package/dist/css/pkt-components.css +1595 -348
  47. package/dist/css/pkt-components.min.css +1 -1
  48. package/dist/css/pkt-docs.css +2077 -364
  49. package/dist/css/pkt-docs.min.css +1 -1
  50. package/dist/css/pkt-elements.css +160 -16
  51. package/dist/css/pkt-elements.min.css +1 -1
  52. package/dist/css/pkt.css +2077 -364
  53. package/dist/css/pkt.min.css +1 -1
  54. package/dist/scss/abstracts/variables/_index.scss +1 -1
  55. package/dist/scss/abstracts/variables/_spacing.scss +1 -0
  56. package/dist/scss/components/_accordion.scss +7 -11
  57. package/dist/scss/components/_alert.scss +34 -11
  58. package/dist/scss/components/_calendar.scss +3 -0
  59. package/dist/scss/components/_combobox.scss +74 -0
  60. package/dist/scss/components/_datepicker.scss +75 -8
  61. package/dist/scss/components/_footer.scss +149 -123
  62. package/dist/scss/components/_header-global.scss +192 -0
  63. package/dist/scss/components/_header-menu.scss +30 -31
  64. package/dist/scss/components/_header-service-mobile.scss +4 -28
  65. package/dist/scss/components/_header-service.scss +4 -21
  66. package/dist/scss/components/_header-shared.scss +190 -0
  67. package/dist/scss/components/_index.scss +2 -0
  68. package/dist/scss/components/_inputwrapper.scss +66 -10
  69. package/dist/scss/components/_modal.scss +1 -5
  70. package/dist/scss/components/_searchinput.scss +58 -2
  71. package/dist/scss/components/_textarea.scss +48 -0
  72. package/dist/scss/components/_timepicker.scss +95 -34
  73. package/dist/scss/elements/_button.scss +12 -3
  74. package/dist/scss/elements/_input.scss +141 -7
  75. package/package.json +3 -3
@@ -15,9 +15,9 @@ pkt-input-wrapper {
15
15
  pkt-helptext:not(:has(.pkt-inputwrapper__has-helptext)),
16
16
  .pkt-inputwrapper__helptext-container:not(.pkt-inputwrapper__has-helptext) {
17
17
  &:not(
18
- :has([slot='helptext']:not(:empty)),
19
- :has(.pkt-inputwrapper__helptext-expandable .pkt-inputwrapper__helptext:not(:empty))
20
- ) {
18
+ :has([slot='helptext']:not(:empty)),
19
+ :has(.pkt-inputwrapper__helptext-expandable .pkt-inputwrapper__helptext:not(:empty))
20
+ ) {
21
21
  display: none;
22
22
  }
23
23
  }
@@ -26,7 +26,7 @@ pkt-input-wrapper {
26
26
  &__label {
27
27
  display: flex;
28
28
  flex-direction: row;
29
- align-items: flex-end;
29
+ align-items: center;
30
30
  gap: map.get(variables.$spacing, 'size-8');
31
31
  color: var(--pkt-color-text-body-default);
32
32
 
@@ -43,7 +43,7 @@ pkt-input-wrapper {
43
43
  &__helptext-container {
44
44
  display: flex;
45
45
  flex-direction: column;
46
- gap: map.get(variables.$spacing, 'size-4');
46
+ gap: map.get(variables.$spacing, 'size-8');
47
47
  }
48
48
  &__helptext {
49
49
  width: min(100%, 31rem);
@@ -71,6 +71,11 @@ pkt-input-wrapper {
71
71
  }
72
72
 
73
73
  &-expandable {
74
+ display: flex;
75
+ flex-direction: column;
76
+ align-items: flex-start;
77
+ gap: map.get(variables.$spacing, 'size-4');
78
+
74
79
  &-heading {
75
80
  margin: 0;
76
81
  @include typography.get-text('pkt-txt-18-medium');
@@ -80,7 +85,6 @@ pkt-input-wrapper {
80
85
  display: block;
81
86
  border-left: 2px solid var(--pkt-color-text-body-dark);
82
87
  padding: map.get(variables.$spacing, 'size-8') map.get(variables.$spacing, 'size-16');
83
- margin-bottom: map.get(variables.$spacing, 'size-4');
84
88
  }
85
89
 
86
90
  &-closed {
@@ -135,17 +139,32 @@ pkt-input-wrapper {
135
139
  margin-right: 8px;
136
140
  }
137
141
 
138
- // Alert
139
142
  .pkt-alert {
140
143
  width: min(100%, 31rem);
141
144
  margin: 0 0 0.5rem 0;
145
+ }
146
+
147
+ // Alert — stretch to match field width (fieldset uses align-items: flex-start)
148
+ &__alert-wrapper {
149
+ align-self: stretch;
150
+ max-width: min(100%, 31rem);
142
151
 
143
- &--error {
144
- margin: 0.5rem 0 0.5rem 0;
152
+ .pkt-alert {
153
+ width: 100%;
154
+ margin: 0;
145
155
  }
146
156
  }
147
157
 
148
- // Tag
158
+ &:has(.pkt-input--fullwidth) &__alert-wrapper {
159
+ max-width: none;
160
+ }
161
+
162
+ &__fieldset > .pkt-alert {
163
+ align-self: stretch;
164
+ width: auto;
165
+ max-width: min(100%, 31rem);
166
+ }
167
+
149
168
  .pkt-tag {
150
169
  margin-left: 8px;
151
170
  }
@@ -212,6 +231,43 @@ pkt-input-wrapper {
212
231
  outline: none;
213
232
  }
214
233
  }
234
+
235
+ // medium = base styles above; only compact sizes get modifier classes
236
+ &--small,
237
+ &--xsmall {
238
+ .pkt-inputwrapper__helptext-container {
239
+ gap: map.get(variables.$spacing, 'size-4');
240
+ }
241
+
242
+ .pkt-inputwrapper__helptext,
243
+ .pkt-inputwrapper__helptext > .pkt-btn,
244
+ .pkt-inputwrapper__helptext-expandable .pkt-btn {
245
+ @include typography.get-text('pkt-txt-12-light');
246
+ }
247
+
248
+ .pkt-inputwrapper__helptext-expandable-heading {
249
+ @include typography.get-text('pkt-txt-16-medium');
250
+ }
251
+
252
+ .pkt-inputwrapper__fieldset {
253
+ gap: map.get(variables.$spacing, 'size-4');
254
+ }
255
+ }
256
+
257
+ &--small {
258
+ .pkt-inputwrapper__label,
259
+ .pkt-inputwrapper__legend {
260
+ @include typography.get-text('pkt-txt-16-medium');
261
+ }
262
+ }
263
+
264
+ // xsmall: wrapper chrome only — field scale lives on .pkt-input--xsmall / .pkt-combobox__input--xsmall
265
+ &--xsmall {
266
+ .pkt-inputwrapper__label,
267
+ .pkt-inputwrapper__legend {
268
+ @include typography.get-text('pkt-txt-14-medium');
269
+ }
270
+ }
215
271
  }
216
272
 
217
273
  [data-mode='dark'] .pkt-inputwrapper {
@@ -236,11 +236,7 @@ $pkt-modal-padding-sides: map.get(variables.$spacing, 'size-40');
236
236
  }
237
237
  }
238
238
 
239
- // Prevent scroll when modal is open
240
- body.pkt-modal--open {
241
- overflow: hidden;
242
- scrollbar-gutter: stable;
243
- }
239
+ // Scroll lock removed from here. Is now shared with other components through shared-utils
244
240
 
245
241
  // SIZES
246
242
  .pkt-modal--small {
@@ -1,4 +1,3 @@
1
- /* Common styles for all inputs */
2
1
  @use 'sass:map';
3
2
  @use '../abstracts/variables';
4
3
  @use '../abstracts/functions';
@@ -9,9 +8,49 @@
9
8
 
10
9
  @include typography.get-text('pkt-txt-18-light');
11
10
 
11
+ &--small {
12
+ @include typography.get-text('pkt-txt-16-light');
13
+
14
+ .pkt-inputwrapper__label {
15
+ @include typography.get-text('pkt-txt-16-medium');
16
+ }
17
+
18
+ .pkt-searchinput__suggestion {
19
+ padding: 0.75rem;
20
+ @include typography.get-text('pkt-txt-16-light');
21
+ }
22
+
23
+ .pkt-searchinput__suggestion-title {
24
+ @include typography.get-text('pkt-txt-16-medium');
25
+ }
26
+ }
27
+
28
+ &--xsmall {
29
+ @include typography.get-text('pkt-txt-14-light');
30
+
31
+ .pkt-inputwrapper__label {
32
+ @include typography.get-text('pkt-txt-14-medium');
33
+ }
34
+
35
+ .pkt-searchinput__suggestion {
36
+ padding: 0.5rem;
37
+ @include typography.get-text('pkt-txt-14-light');
38
+ }
39
+
40
+ .pkt-searchinput__suggestion-title {
41
+ @include typography.get-text('pkt-txt-14-medium');
42
+ }
43
+ }
44
+
12
45
  &__field {
13
46
  width: min(100%, 31rem);
14
47
  display: flex;
48
+ align-items: stretch;
49
+
50
+ .pkt-input {
51
+ flex: 1;
52
+ min-width: 0;
53
+ }
15
54
  }
16
55
 
17
56
  &--fullwidth &__field {
@@ -35,10 +74,15 @@
35
74
  gap: 0.5rem;
36
75
  }
37
76
 
38
- &--local .pkt-input {
77
+ &--local .pkt-input__container--medium .pkt-input {
39
78
  padding: 0.5rem 0 0.5rem 1rem;
40
79
  }
41
80
 
81
+ &--local .pkt-input__container--small .pkt-input,
82
+ &--local .pkt-input__container--xsmall .pkt-input {
83
+ padding-right: 0;
84
+ }
85
+
42
86
  &--local &__button {
43
87
  &:disabled {
44
88
  border-color: var(--pkt-color-input-border-disabled);
@@ -64,9 +108,21 @@
64
108
  &--global &__suggestions {
65
109
  width: min(calc(100% - 3rem), 28rem);
66
110
  }
111
+ &--global.pkt-searchinput--small &__suggestions {
112
+ width: min(calc(100% - 2.625rem), 28rem);
113
+ }
114
+ &--global.pkt-searchinput--xsmall &__suggestions {
115
+ width: min(calc(100% - 2.25rem), 28rem);
116
+ }
67
117
  &--local-with-button &__suggestions {
68
118
  width: min(calc(100% - 3.5rem), 27.5rem);
69
119
  }
120
+ &--local-with-button.pkt-searchinput--small &__suggestions {
121
+ width: min(calc(100% - 3.125rem), 27.5rem);
122
+ }
123
+ &--local-with-button.pkt-searchinput--xsmall &__suggestions {
124
+ width: min(calc(100% - 2.75rem), 27.5rem);
125
+ }
70
126
  &--fullwidth &__suggestions {
71
127
  width: 100%;
72
128
  }
@@ -0,0 +1,48 @@
1
+ /*
2
+ * Textarea component
3
+ *
4
+ * Base field styles (border, states, min-height) live in _input.scss on .pkt-input:is(textarea).
5
+ * Wrapper label/helptext scale lives in _inputwrapper.scss (--small / --xsmall).
6
+ * Counter stays in normal flow below the field for all sizes (see textarea.astro).
7
+ */
8
+ @use 'sass:map';
9
+ @use '../abstracts/variables';
10
+ @use '../abstracts/mixins/typography';
11
+
12
+ // Match textinput: cap at 31rem; field fills the wrapper.
13
+ // React: .pkt-inputwrapper is the outer box. Elements: pkt-textarea is the flex child and
14
+ // shrink-wraps unless capped here — inner .pkt-inputwrapper width: 100% then resolves correctly.
15
+ pkt-textarea:not([fullwidth]):has(textarea.pkt-input:not([cols])) {
16
+ width: min(31rem, 100%);
17
+ }
18
+
19
+ pkt-textarea[fullwidth] {
20
+ width: 100%;
21
+ }
22
+
23
+ .pkt-inputwrapper:has(textarea.pkt-input:not(.pkt-input--fullwidth):not([cols])) {
24
+ width: min(31rem, 100%);
25
+ }
26
+
27
+ .pkt-inputwrapper:has(textarea.pkt-input--fullwidth) {
28
+ width: 100%;
29
+ }
30
+
31
+ textarea.pkt-input {
32
+ &:not(.pkt-input--fullwidth):not([cols]) {
33
+ width: 100%;
34
+ }
35
+
36
+ &--small,
37
+ &--xsmall {
38
+ padding: map.get(variables.$spacing, 'size-8') map.get(variables.$spacing, 'size-16');
39
+ }
40
+
41
+ &--small {
42
+ @include typography.get-text('pkt-txt-16-light');
43
+ }
44
+
45
+ &--xsmall {
46
+ @include typography.get-text('pkt-txt-14-light');
47
+ }
48
+ }
@@ -1,13 +1,39 @@
1
1
  /* Component: pkt-timepicker */
2
2
 
3
- @use 'sass:map';
4
- @use '../abstracts/variables';
5
3
  @use '../abstracts/mixins/typography';
6
4
 
7
5
  pkt-timepicker {
8
6
  display: block;
9
7
  }
10
8
 
9
+ /// Size overrides for small / xsmall. Base .pkt-input__container styles use medium (48px).
10
+ @mixin timepicker-field-size($min-height, $text-style, $icon-size, $padding-inline: 0.5rem) {
11
+ .pkt-input__container {
12
+ min-height: $min-height;
13
+
14
+ .pkt-timepicker__input,
15
+ .pkt-timepicker__separator {
16
+ @include typography.get-text($text-style);
17
+ }
18
+
19
+ button.pkt-timepicker__button {
20
+ padding: 0 $padding-inline;
21
+
22
+ pkt-icon,
23
+ .pkt-icon,
24
+ svg {
25
+ width: $icon-size;
26
+ height: $icon-size;
27
+ }
28
+ }
29
+
30
+ .pkt-timepicker__icon {
31
+ padding: 0 $padding-inline 0 0;
32
+ height: $icon-size;
33
+ }
34
+ }
35
+ }
36
+
11
37
  .pkt-timepicker,
12
38
  pkt-timepicker {
13
39
  &__anchor {
@@ -15,35 +41,43 @@ pkt-timepicker {
15
41
  }
16
42
 
17
43
  .pkt-input__container {
44
+ min-height: 3rem;
45
+ align-items: center;
18
46
  border: 2px solid var(--pkt-color-input-border-normal);
19
47
  background-color: var(--pkt-color-input-background-normal);
20
48
  width: fit-content;
21
49
  padding: 0 0 0 1rem;
22
50
 
51
+ // Composite layout: one bordered row, segments without individual borders/heights.
52
+ .pkt-timepicker__input,
53
+ .pkt-timepicker__separator,
54
+ .pkt-input-icon,
55
+ .pkt-timepicker__button {
56
+ border: 0;
57
+ height: auto;
58
+ min-height: 0;
59
+ padding-top: 0;
60
+ padding-bottom: 0;
61
+ flex: 0 0 auto;
62
+ }
63
+
23
64
  .pkt-input,
24
65
  .pkt-input-icon,
25
66
  .pkt-input-separator {
26
67
  border: 0;
27
- min-height: auto;
28
68
  }
29
69
 
30
- &:hover {
31
- border-color: var(--pkt-color-input-border-active);
70
+ .pkt-timepicker__input,
71
+ .pkt-timepicker__separator {
72
+ @include typography.get-text('pkt-txt-18-light');
32
73
  }
33
74
 
34
- &:focus-within {
35
- border-color: var(--pkt-color-input-border-active);
36
- outline: 2px solid var(--pkt-color-input-border-active);
75
+ .pkt-timepicker__input {
76
+ padding-inline: 0;
37
77
  }
38
78
 
39
- &:has(input:disabled) {
40
- border-color: var(--pkt-color-input-border-disabled);
41
- background-color: var(--pkt-color-surface-default-gray);
42
-
43
- .pkt-timepicker__icon,
44
- .pkt-timepicker__button {
45
- --fg-color: var(--pkt-color-input-text-disabled);
46
- }
79
+ .pkt-timepicker__separator {
80
+ padding: 0;
47
81
  }
48
82
 
49
83
  button.pkt-timepicker__button {
@@ -51,7 +85,8 @@ pkt-timepicker {
51
85
  padding: 0 0.75rem;
52
86
 
53
87
  pkt-icon,
54
- .pkt-icon {
88
+ .pkt-icon,
89
+ svg {
55
90
  width: 1.5rem;
56
91
  height: 1.5rem;
57
92
  }
@@ -70,6 +105,49 @@ pkt-timepicker {
70
105
  margin-left: 0.25rem;
71
106
  }
72
107
  }
108
+
109
+ .pkt-timepicker__icon {
110
+ align-self: center;
111
+ pointer-events: none;
112
+ padding: 0 0.75rem 0 0;
113
+ height: 1.5rem;
114
+ width: -webkit-min-content;
115
+ width: -moz-min-content;
116
+ width: min-content;
117
+
118
+ > svg,
119
+ svg {
120
+ width: 100%;
121
+ height: 100%;
122
+ }
123
+ }
124
+
125
+ &:hover {
126
+ border-color: var(--pkt-color-input-border-active);
127
+ }
128
+
129
+ &:focus-within {
130
+ border-color: var(--pkt-color-input-border-active);
131
+ outline: 2px solid var(--pkt-color-input-border-active);
132
+ }
133
+
134
+ &:has(input:disabled) {
135
+ border-color: var(--pkt-color-input-border-disabled);
136
+ background-color: var(--pkt-color-surface-default-gray);
137
+
138
+ .pkt-timepicker__icon,
139
+ .pkt-timepicker__button {
140
+ --fg-color: var(--pkt-color-input-text-disabled);
141
+ }
142
+ }
143
+ }
144
+
145
+ &--small {
146
+ @include timepicker-field-size(2.625rem, 'pkt-txt-16-light', 1.25rem);
147
+ }
148
+
149
+ &--xsmall {
150
+ @include timepicker-field-size(2.25rem, 'pkt-txt-14-light', 1.125rem);
73
151
  }
74
152
 
75
153
  // Stepper variant: no left padding — the prev button takes that space
@@ -77,7 +155,6 @@ pkt-timepicker {
77
155
  padding-left: 0;
78
156
  }
79
157
 
80
- // Fullwidth modifier
81
158
  &--fullwidth {
82
159
  .pkt-timepicker__anchor,
83
160
  .pkt-input__container {
@@ -137,7 +214,6 @@ pkt-timepicker {
137
214
  &__input {
138
215
  width: 1.5rem;
139
216
  text-align: center;
140
- padding: 0.5rem 0;
141
217
 
142
218
  &::-webkit-inner-spin-button,
143
219
  &::-webkit-outer-spin-button {
@@ -150,24 +226,9 @@ pkt-timepicker {
150
226
  }
151
227
 
152
228
  &__separator {
153
- @include typography.get-text('pkt-txt-18');
154
-
155
- padding: 0.25rem 0 0.5rem;
156
229
  user-select: none;
157
230
  }
158
231
 
159
- &__icon {
160
- height: auto;
161
- padding: 0 0.75rem 0 0;
162
- pointer-events: none;
163
-
164
- pkt-icon,
165
- .pkt-icon {
166
- width: 1.5rem;
167
- height: 1.5rem;
168
- }
169
- }
170
-
171
232
  &-popup {
172
233
  position: absolute;
173
234
  top: 100%;
@@ -1,6 +1,6 @@
1
1
  /* Button element!
2
2
  *
3
- * Size: small, medium, large
3
+ * Size: xsmall, small, medium, large
4
4
  * Skin: primary, secondary, tertiary
5
5
  * State: normal, focus, hover, active, disabled
6
6
  * Variant: label-only, icon-left, icon-right, icon-only
@@ -23,14 +23,23 @@ $-sizes: (
23
23
  'height': 3rem,
24
24
  'line-height': 1.1,
25
25
  ),
26
- 'small': (
26
+ 'xsmall': (
27
27
  'text-class': 'pkt-txt-14-medium',
28
- 'padding': 0 0.5rem,
28
+ 'padding': 0 0.75rem,
29
+ 'padding-icon-only': 0 0.4375rem,
30
+ 'icon-size': 1.125rem,
31
+ 'height': 2.25rem,
32
+ 'line-height': 1.1,
33
+ ),
34
+ 'small': (
35
+ 'text-class': 'pkt-txt-16-medium',
36
+ 'padding': 0 1rem,
29
37
  'padding-icon-only': 0 0.5625rem,
30
38
  'icon-size': 1.25rem,
31
39
  'height': 2.625rem,
32
40
  'line-height': 1.1,
33
41
  ),
42
+
34
43
  'large': (
35
44
  'text-class': 'pkt-txt-24-medium',
36
45
  'padding': 0 1rem,