@danske/sapphire-css 50.2.1 → 52.2.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 (50) hide show
  1. package/build/themes/cjs/default-dark.js +4 -1
  2. package/build/themes/cjs/default.js +4 -1
  3. package/build/themes/cjs/index.d.ts +3 -0
  4. package/build/themes/cjs/realkredit.js +4 -1
  5. package/build/themes/esm/default-dark.js +4 -1
  6. package/build/themes/esm/default.js +4 -1
  7. package/build/themes/esm/index.d.ts +3 -0
  8. package/build/themes/esm/realkredit.js +4 -1
  9. package/components/alert/alert.module.css +3 -2
  10. package/components/avatar/avatar.module.css +1 -0
  11. package/components/button/button.module.css +1 -1
  12. package/components/calendar/calendar.module.css +46 -4
  13. package/components/calendar/calendar.module.css.d.ts +1 -0
  14. package/components/checkbox/checkbox.module.css +48 -3
  15. package/components/checkbox/checkbox.module.css.d.ts +5 -0
  16. package/components/danskeProgressBar/danskeProgressBar.module.css +178 -0
  17. package/components/danskeProgressBar/danskeProgressBar.module.css.d.ts +9 -0
  18. package/components/dateField/dateField.module.css +30 -1
  19. package/components/dateField/dateField.module.css.d.ts +1 -0
  20. package/components/dropzone/dropzone.module.css +12 -49
  21. package/components/field/field.module.css +180 -15
  22. package/components/field/field.module.css.d.ts +9 -2
  23. package/components/fieldGroup/fieldGroup.module.css +4 -0
  24. package/components/fieldGroup/fieldGroup.module.css.d.ts +1 -0
  25. package/components/label/label.module.css +5 -0
  26. package/components/label/label.module.css.d.ts +1 -0
  27. package/components/link/link.module.css +0 -1
  28. package/components/listbox/listbox.module.css +6 -0
  29. package/components/modalLayout/modalLayout.module.css +2 -1
  30. package/components/radio/radio.module.css +79 -18
  31. package/components/radio/radio.module.css.d.ts +5 -0
  32. package/components/searchField/searchField.module.css +31 -6
  33. package/components/searchField/searchField.module.css.d.ts +1 -0
  34. package/components/select/select.module.css +61 -16
  35. package/components/select/select.module.css.d.ts +2 -0
  36. package/components/slider/slider.module.css +2 -3
  37. package/components/switch/switch.module.css +42 -8
  38. package/components/switch/switch.module.css.d.ts +2 -0
  39. package/components/table/table.module.css +108 -10
  40. package/components/table/table.module.css.d.ts +5 -1
  41. package/components/textField/textField.module.css +43 -10
  42. package/components/textField/textField.module.css.d.ts +1 -0
  43. package/components/toast/toast.module.css +1 -0
  44. package/components/truncate-overflow/truncate-overflow.module.css +7 -0
  45. package/components/truncate-overflow/truncate-overflow.module.css.d.ts +5 -0
  46. package/package.json +19 -22
  47. package/themes/default-dark.js +4 -1
  48. package/themes/default.js +4 -1
  49. package/themes/index.d.ts +3 -0
  50. package/themes/realkredit.js +4 -1
@@ -23,6 +23,7 @@
23
23
  color: var(--sapphire-semantic-color-foreground-primary);
24
24
  font-size: var(--sapphire-semantic-size-font-control-lg);
25
25
  height: var(--sapphire-semantic-size-height-control-lg);
26
+ position: relative;
26
27
  background: var(
27
28
  --sapphire-semantic-color-background-action-secondary-default
28
29
  );
@@ -116,19 +117,17 @@
116
117
  * Css only solution to:
117
118
  * - hide the clear button when the input is empty.
118
119
  * - Apply a gentle transition on appearance/disappearance
120
+ * The button's space is kept reserved (only opacity/scale animate) so the
121
+ * input's flex space doesn't shift when the button appears/disappears.
119
122
  * IMPORTANT: there must be a placeholder provided for :placeholder-shown to
120
123
  * work. " " can be set as placeholder as a fallback, or
121
124
  * sapphire-search-field__input--empty class can be used instead.
122
125
  */
123
126
  opacity: 0;
124
- width: 0; /* To not cover the input when invisible. */
125
127
  transform: scale(0.85);
128
+ cursor: text; /* cursor: text is used to avoid the button's hover effect when the input is empty */
126
129
  transition: transform var(--sapphire-semantic-time-fade-quick),
127
- opacity var(--sapphire-semantic-time-fade-quick),
128
- width var(--sapphire-semantic-time-fade-quick)
129
- /* Zero duration will kill the transition */
130
- var(--sapphire-semantic-time-fade-quick)
131
- /* Delaying to prevent width transition*/;
130
+ opacity var(--sapphire-semantic-time-fade-quick);
132
131
  }
133
132
 
134
133
  /*
@@ -166,3 +165,29 @@
166
165
  .sapphire-search-field--md .sapphire-search-field__icon {
167
166
  margin-left: var(--sapphire-semantic-size-spacing-sm);
168
167
  }
168
+
169
+ /**
170
+ * Small Size
171
+ */
172
+ .sapphire-search-field--sm {
173
+ font-size: var(--sapphire-semantic-size-font-control-md);
174
+ height: var(--sapphire-semantic-size-height-control-sm);
175
+ border-radius: var(--sapphire-semantic-size-height-control-sm);
176
+ }
177
+
178
+ .sapphire-search-field--sm .sapphire-search-field__input {
179
+ padding-left: var(--sapphire-semantic-size-height-control-sm);
180
+ }
181
+
182
+ .sapphire-search-field--sm .sapphire-search-field__button {
183
+ height: var(--sapphire-semantic-size-height-control-sm);
184
+ width: var(--sapphire-semantic-size-height-control-sm);
185
+ }
186
+
187
+ .sapphire-search-field--sm .sapphire-search-field__input:last-child {
188
+ padding-right: var(--sapphire-semantic-size-spacing-xs);
189
+ }
190
+
191
+ .sapphire-search-field--sm .sapphire-search-field__icon {
192
+ margin-left: var(--sapphire-semantic-size-spacing-xs);
193
+ }
@@ -10,6 +10,7 @@ declare const styles: {
10
10
  readonly "sapphire-search-field__input--empty": string;
11
11
  readonly "sapphire-search-field__icon": string;
12
12
  readonly "sapphire-search-field--md": string;
13
+ readonly "sapphire-search-field--sm": string;
13
14
  };
14
15
  export = styles;
15
16
 
@@ -24,17 +24,16 @@
24
24
  height: var(--sapphire-semantic-size-height-control-lg);
25
25
  box-sizing: border-box;
26
26
  cursor: pointer;
27
- padding: 0 var(--sapphire-semantic-size-spacing-control-horizontal-md) 0
28
- var(--sapphire-semantic-size-spacing-control-horizontal-lg);
27
+ padding: 0 var(--sapphire-semantic-size-spacing-control-horizontal-md);
29
28
  border: none;
30
29
  background: var(--sapphire-semantic-color-background-field);
31
30
  width: 100%;
32
- outline: 0;
31
+ outline: solid var(--sapphire-semantic-size-border-sm)
32
+ var(--sapphire-semantic-color-border-field-default);
33
+ outline-offset: calc(0px - var(--sapphire-semantic-size-border-sm));
33
34
  text-align: left;
34
35
  color: inherit;
35
36
  font-family: inherit;
36
- box-shadow: inset 0px 0px 0px var(--sapphire-semantic-size-border-sm)
37
- var(--sapphire-semantic-color-border-field-default);
38
37
  border-radius: var(--sapphire-semantic-size-radius-md);
39
38
  gap: var(--sapphire-semantic-size-spacing-sm);
40
39
  }
@@ -46,6 +45,14 @@
46
45
  gap: var(--sapphire-semantic-size-spacing-xs);
47
46
  }
48
47
 
48
+ .sapphire-select--sm .sapphire-select__button {
49
+ border-radius: var(--sapphire-semantic-size-radius-sm);
50
+ height: var(--sapphire-semantic-size-height-control-sm);
51
+ padding: 0 var(--sapphire-semantic-size-spacing-control-horizontal-sm) 0
52
+ var(--sapphire-semantic-size-spacing-control-horizontal-md);
53
+ gap: var(--sapphire-semantic-size-spacing-2xs);
54
+ }
55
+
49
56
  .sapphire-select__value {
50
57
  flex: 1 0 0;
51
58
  min-width: 0;
@@ -61,6 +68,10 @@
61
68
  font-size: var(--sapphire-semantic-size-font-control-md);
62
69
  }
63
70
 
71
+ .sapphire-select--sm .sapphire-select__value {
72
+ font-size: var(--sapphire-semantic-size-font-control-md);
73
+ }
74
+
64
75
  .sapphire-select__placeholder {
65
76
  overflow: hidden;
66
77
  text-overflow: ellipsis;
@@ -81,6 +92,11 @@
81
92
  height: var(--sapphire-semantic-size-icon-sm);
82
93
  }
83
94
 
95
+ .sapphire-select--sm .sapphire-select__icon-container {
96
+ width: var(--sapphire-semantic-size-icon-sm);
97
+ height: var(--sapphire-semantic-size-icon-sm);
98
+ }
99
+
84
100
  /**
85
101
  * Prefix
86
102
  */
@@ -91,15 +107,18 @@
91
107
  color: var(--sapphire-semantic-color-foreground-secondary);
92
108
  }
93
109
 
94
- .sapphire-select:not(.sapphire-select--md)
95
- .sapphire-select__button:has(.sapphire-select__prefix) {
96
- padding-left: var(--sapphire-semantic-size-spacing-control-horizontal-md);
110
+ .sapphire-select--sm .sapphire-select__button:has(.sapphire-select__prefix) {
111
+ padding-left: var(--sapphire-semantic-size-spacing-control-horizontal-sm);
97
112
  }
98
113
 
99
114
  .sapphire-select--md .sapphire-select__prefix {
100
115
  font-size: var(--sapphire-semantic-size-font-control-md);
101
116
  }
102
117
 
118
+ .sapphire-select--sm .sapphire-select__prefix {
119
+ font-size: var(--sapphire-semantic-size-font-control-md);
120
+ }
121
+
103
122
  /*
104
123
  * Search input. If visually-hidden styles are not inline,
105
124
  * data-hidden="true" can be added when the input is visually hidden,
@@ -123,12 +142,41 @@
123
142
  z-index: 1;
124
143
  }
125
144
 
145
+ /*
146
+ * iOS keyboard trigger.
147
+ *
148
+ * An invisible <label htmlFor> overlay (a sibling of __button) that covers the
149
+ * trigger while the searchable select is closed. On touch devices, tapping it
150
+ * forwards a trusted focus to the search input, which is the only way to make
151
+ * iOS Safari open the software keyboard — the trigger button itself cannot,
152
+ * because React Aria's usePress defers onPress to the click event and Sapphire's
153
+ * useButton (usePreventTouchEnd) calls preventDefault() on the trigger touchend.
154
+ *
155
+ * pointer-events is disabled by default so mouse/keyboard users interact with the
156
+ * trigger button exactly as before (hover, press, toggle). It is only enabled on
157
+ * touch devices, where the keyboard problem exists.
158
+ */
159
+ .sapphire-select__ios-keyboard-trigger {
160
+ position: absolute;
161
+ inset: 0;
162
+ z-index: 1;
163
+ cursor: pointer;
164
+ pointer-events: none;
165
+ }
166
+
167
+ @media (hover: none) and (pointer: coarse) {
168
+ .sapphire-select__ios-keyboard-trigger {
169
+ pointer-events: auto;
170
+ }
171
+ }
172
+
126
173
  /**
127
174
  * Error
128
175
  */
129
176
  .sapphire-select--error:not(.is-disabled) .sapphire-select__button {
130
- box-shadow: inset 0px 0px 0px 1px
177
+ outline: solid var(--sapphire-semantic-size-border-sm)
131
178
  var(--sapphire-semantic-color-border-negative-default);
179
+ outline-offset: calc(0px - var(--sapphire-semantic-size-border-sm));
132
180
  }
133
181
 
134
182
  /**
@@ -142,8 +190,9 @@
142
190
  .is-disabled
143
191
  ):not(.js-hover):hover
144
192
  .sapphire-select__button {
145
- box-shadow: inset 0px 0px 0px var(--sapphire-semantic-size-border-sm)
193
+ outline: solid var(--sapphire-semantic-size-border-sm)
146
194
  var(--sapphire-semantic-color-border-field-hover);
195
+ outline-offset: calc(0px - var(--sapphire-semantic-size-border-sm));
147
196
  }
148
197
 
149
198
  .sapphire-select:not(.is-disabled).is-hover .sapphire-select__icon-container,
@@ -156,13 +205,9 @@
156
205
  * Focus
157
206
  */
158
207
  .sapphire-select:not(.is-disabled).is-focus .sapphire-select__button {
159
- box-shadow: inset 0px 0px 0px var(--sapphire-semantic-size-focus-ring)
208
+ outline: solid var(--sapphire-semantic-size-focus-ring)
160
209
  var(--sapphire-semantic-color-focus-ring);
161
- }
162
-
163
- .sapphire-select--error:not(.is-disabled).is-focus .sapphire-select__button {
164
- box-shadow: inset 0px 0px 0px var(--sapphire-semantic-size-focus-ring)
165
- var(--sapphire-semantic-color-border-negative-default);
210
+ outline-offset: calc(0px - var(--sapphire-semantic-size-focus-ring));
166
211
  }
167
212
 
168
213
  .sapphire-select.is-disabled .sapphire-select__button {
@@ -2,12 +2,14 @@ declare const styles: {
2
2
  readonly "sapphire-select": string;
3
3
  readonly "sapphire-select__button": string;
4
4
  readonly "sapphire-select--md": string;
5
+ readonly "sapphire-select--sm": string;
5
6
  readonly "sapphire-select__value": string;
6
7
  readonly "sapphire-select__placeholder": string;
7
8
  readonly "sapphire-select__icon-container": string;
8
9
  readonly "sapphire-select__prefix": string;
9
10
  readonly "sapphire-select__search-input": string;
10
11
  readonly "sapphire-select__native-select": string;
12
+ readonly "sapphire-select__ios-keyboard-trigger": string;
11
13
  readonly "sapphire-select--error": string;
12
14
  readonly "is-disabled": string;
13
15
  readonly "is-focus": string;
@@ -4,12 +4,11 @@
4
4
  flex-direction: column;
5
5
  gap: var(--sapphire-semantic-size-spacing-xs);
6
6
  justify-content: center;
7
- width: fit-content;
8
7
  }
9
8
 
10
9
  .sapphire-slider__track {
11
10
  position: relative;
12
- width: var(--sapphire-semantic-size-width-field);
11
+ width: 100%;
13
12
  height: var(--sapphire-semantic-size-height-control-2xs);
14
13
  touch-action: none;
15
14
  }
@@ -22,7 +21,7 @@
22
21
  backdrop-filter: var(--sapphire-semantic-backdrop-filter-blur);
23
22
  height: var(--sapphire-global-size-generic-10);
24
23
  border-radius: var(--sapphire-semantic-size-radius-sm);
25
- width: var(--sapphire-semantic-size-width-field);
24
+ width: 100%;
26
25
  top: 50%;
27
26
  transform: translateY(-50%);
28
27
  }
@@ -66,6 +66,12 @@
66
66
  line-height: var(--sapphire-semantic-size-height-control-2xs);
67
67
  }
68
68
 
69
+ .sapphire-switch--sm .sapphire-switch-label {
70
+ gap: var(--sapphire-semantic-size-spacing-2xs);
71
+ font-size: var(--sapphire-semantic-size-font-control-md);
72
+ line-height: var(--sapphire-semantic-size-height-control-2xs);
73
+ }
74
+
69
75
  /* focus */
70
76
  .sapphire-switch:not(.js-focus)
71
77
  .sapphire-switch-input:focus-visible
@@ -85,8 +91,9 @@
85
91
  width: var(--sapphire-global-size-generic-110);
86
92
  box-shadow: inset 0 0 0 var(--sapphire-semantic-size-border-sm)
87
93
  var(--sapphire-semantic-color-border-field-default);
88
- transition: box-shadow var(--sapphire-semantic-time-motion-quick)
89
- var(--sapphire-semantic-transitions-fade);
94
+ transition-property: background, box-shadow;
95
+ transition-duration: var(--sapphire-semantic-time-motion-quick);
96
+ transition-timing-function: var(--sapphire-semantic-transitions-fade);
90
97
  height: var(--sapphire-semantic-size-height-control-xs);
91
98
  border-radius: calc(var(--sapphire-semantic-size-height-control-xs) / 2);
92
99
  /* Prevents the component from shrinking */
@@ -162,7 +169,7 @@
162
169
  padding: var(--sapphire-global-size-static-5);
163
170
 
164
171
  height: 100%;
165
- aspect-ratio: 1/1;
172
+ width: var(--sapphire-semantic-size-height-control-xs);
166
173
  border-radius: 50%;
167
174
  background-color: var(--sapphire-semantic-color-border-field-default);
168
175
  background-clip: content-box;
@@ -202,17 +209,41 @@
202
209
  }
203
210
 
204
211
  .sapphire-switch--md .sapphire-switch-track {
205
- width: var(--sapphire-global-size-generic-80);
212
+ width: 2.25rem /* 36px - do we want a token for this? */;
206
213
  height: var(--sapphire-semantic-size-height-control-2xs);
207
214
  border-radius: calc(var(--sapphire-semantic-size-height-control-2xs) / 2);
208
215
  }
209
216
 
217
+ .sapphire-switch--md .sapphire-switch-track::after {
218
+ width: var(--sapphire-semantic-size-height-control-2xs);
219
+ }
220
+
210
221
  .sapphire-switch--md
211
222
  .sapphire-switch-input:checked
212
223
  ~ .sapphire-switch-track::after {
213
224
  left: calc(100% - var(--sapphire-semantic-size-height-control-2xs));
214
225
  }
215
226
 
227
+ .sapphire-switch--sm .sapphire-switch-track {
228
+ width: 1.875rem; /* 30px - do we want a token for this? */
229
+ height: var(--sapphire-semantic-size-height-box-md);
230
+ border-radius: calc(var(--sapphire-semantic-size-height-box-md) / 2);
231
+ }
232
+
233
+ .sapphire-switch--sm .sapphire-switch-track::after {
234
+ width: var(--sapphire-semantic-size-height-box-md);
235
+ }
236
+
237
+ .sapphire-switch--sm
238
+ .sapphire-switch-input:checked
239
+ ~ .sapphire-switch-track::after {
240
+ left: calc(100% - var(--sapphire-semantic-size-height-box-md));
241
+ }
242
+
243
+ .sapphire-switch--sm {
244
+ gap: var(--sapphire-semantic-size-spacing-xs);
245
+ }
246
+
216
247
  /* Note */
217
248
  .sapphire-switch__note {
218
249
  display: block;
@@ -231,8 +262,11 @@
231
262
  .sapphire-switch__note--md {
232
263
  font-size: var(--sapphire-semantic-size-font-label-sm);
233
264
  line-height: var(--sapphire-semantic-size-line-height-sm);
234
- margin-left: calc(
235
- var(--sapphire-semantic-size-spacing-sm) +
236
- var(--sapphire-global-size-generic-80)
237
- );
265
+ margin-left: calc(var(--sapphire-semantic-size-spacing-sm) + 2.25rem);
266
+ }
267
+
268
+ .sapphire-switch__note--sm {
269
+ font-size: var(--sapphire-semantic-size-font-label-sm);
270
+ line-height: var(--sapphire-semantic-size-line-height-sm);
271
+ margin-left: calc(var(--sapphire-semantic-size-spacing-xs) + 1.875rem);
238
272
  }
@@ -4,6 +4,7 @@ declare const styles: {
4
4
  readonly "sapphire-switch-input": string;
5
5
  readonly "sapphire-switch-label": string;
6
6
  readonly "sapphire-switch--md": string;
7
+ readonly "sapphire-switch--sm": string;
7
8
  readonly "js-focus": string;
8
9
  readonly "sapphire-switch-track": string;
9
10
  readonly "is-focus": string;
@@ -12,6 +13,7 @@ declare const styles: {
12
13
  readonly "is-hover": string;
13
14
  readonly "sapphire-switch__note": string;
14
15
  readonly "sapphire-switch__note--md": string;
16
+ readonly "sapphire-switch__note--sm": string;
15
17
  };
16
18
  export = styles;
17
19
 
@@ -19,6 +19,11 @@
19
19
  background-color: var(--sapphire-semantic-color-background-surface);
20
20
  }
21
21
 
22
+ .sapphire-table--negative-margin-self {
23
+ margin-left: calc(var(--sapphire-semantic-size-spacing-sm) * -1);
24
+ width: calc(100% + (var(--sapphire-semantic-size-spacing-sm) * 2));
25
+ }
26
+
22
27
  .sapphire-table--overflow {
23
28
  /*
24
29
  * If the "sapphire-table" has a set height the table needs to overflow.
@@ -31,6 +36,7 @@
31
36
  border-spacing: 0;
32
37
  width: 100%;
33
38
  table-layout: auto;
39
+ --sapphire-table-side-padding: var(--sapphire-table-cell-spacing-h);
34
40
  }
35
41
 
36
42
  .sapphire-table__table--fixed-layout {
@@ -104,6 +110,14 @@
104
110
  width: 100%;
105
111
  }
106
112
 
113
+ .sapphire-table__headCell:first-child .sapphire-table__headCell_container {
114
+ padding-left: var(--sapphire-table-side-padding);
115
+ }
116
+
117
+ .sapphire-table__headCell:last-child .sapphire-table__headCell_container {
118
+ padding-right: var(--sapphire-table-side-padding);
119
+ }
120
+
107
121
  .sapphire-table__cell--alignRight .sapphire-table__headCell_container {
108
122
  justify-content: flex-end;
109
123
  }
@@ -173,6 +187,7 @@
173
187
 
174
188
  .sapphire-table__headCell.sapphire-table__headCell--sortable {
175
189
  cursor: pointer;
190
+ user-select: none;
176
191
  }
177
192
 
178
193
  .sapphire-table__headCell--sortable:not(sapphire-table__headCell--sorted):hover
@@ -216,6 +231,14 @@
216
231
  var(--sapphire-table-cell-spacing-h);
217
232
  }
218
233
 
234
+ .sapphire-table__cell:not(.sapphire-table__cell--tree):first-child {
235
+ padding-left: var(--sapphire-table-side-padding);
236
+ }
237
+
238
+ .sapphire-table__cell:not(.sapphire-table__cell--tree):last-child {
239
+ padding-right: var(--sapphire-table-side-padding);
240
+ }
241
+
219
242
  .sapphire-table__cell-contents {
220
243
  display: block;
221
244
  width: 100%;
@@ -223,6 +246,7 @@
223
246
  }
224
247
 
225
248
  /* Overflow behaviour */
249
+ /* @deprecated in favor of TruncateOverflow */
226
250
  .sapphire-table__cell--ellipsed,
227
251
  .sapphire-table__headCell_content--ellipsed,
228
252
  .sapphire-table__cell--ellipsed .sapphire-table__cell-contents {
@@ -261,12 +285,26 @@
261
285
  padding: var(--sapphire-table-cell-spacing-v)
262
286
  var(--sapphire-table-cell-spacing-h);
263
287
  box-sizing: content-box;
288
+ text-align: center;
264
289
  }
290
+
291
+ .sapphire-table__selectionCell:first-child {
292
+ padding-left: var(--sapphire-table-side-padding);
293
+ }
294
+
295
+ .sapphire-table__selectionCell:last-child {
296
+ padding-right: var(--sapphire-table-side-padding);
297
+ }
298
+
265
299
  .sapphire-table__head .sapphire-table__selectionCell {
266
300
  padding: var(--sapphire-semantic-size-spacing-2xs)
267
301
  var(--sapphire-table-cell-spacing-h);
268
302
  }
269
303
 
304
+ .sapphire-table__head .sapphire-table__selectionCell:first-child {
305
+ padding-left: var(--sapphire-table-side-padding);
306
+ }
307
+
270
308
  td.sapphire-table__selectionCell,
271
309
  th.sapphire-table__selectionCell {
272
310
  width: var(--sapphire-global-size-generic-50);
@@ -326,7 +364,14 @@ th.sapphire-table__selectionCell:first-child {
326
364
  );
327
365
  }
328
366
 
329
- .sapphire-table--interactive .sapphire-table__row--active {
367
+ /* Applied only when the "action" on rows is disabled. If only selection is disabled, only the checkbox should be disabled */
368
+ .sapphire-table__row.is-disabled .sapphire-table__cell,
369
+ .sapphire-table__row.is-disabled .sapphire-table__selectionCell {
370
+ opacity: var(--sapphire-semantic-opacity-disabled);
371
+ }
372
+
373
+ .sapphire-table--interactive .sapphire-table__row--active,
374
+ .sapphire-table__row--interactive.sapphire-table__row--active {
330
375
  --sapphire-table-row-bg-active: var(
331
376
  --sapphire-semantic-color-background-action-tertiary-active
332
377
  );
@@ -334,7 +379,8 @@ th.sapphire-table__selectionCell:first-child {
334
379
  }
335
380
 
336
381
  .sapphire-table--interactive
337
- .sapphire-table__row--selected.sapphire-table__row--active {
382
+ .sapphire-table__row--selected.sapphire-table__row--active,
383
+ .sapphire-table__row--interactive.sapphire-table__row--selected.sapphire-table__row--active {
338
384
  --sapphire-table-row-bg-active: var(
339
385
  /* using hover color for active here is intentional, and to avoid too many color changes when selecting rows */
340
386
  --sapphire-semantic-color-background-action-select-secondary-hover
@@ -363,16 +409,68 @@ th.sapphire-table__selectionCell:first-child {
363
409
  }
364
410
 
365
411
  .sapphire-table__row-expand-button {
366
- display: inline-flex; /* for transform to take effect */
367
- transition: transform var(--sapphire-semantic-transitions-dynamic)
368
- var(--sapphire-semantic-time-motion-quick);
412
+ display: inline-flex;
413
+ height: var(--sapphire-semantic-size-icon-md);
414
+ width: var(--sapphire-semantic-size-icon-md);
415
+ vertical-align: middle;
416
+ justify-content: center;
417
+ align-items: center;
418
+ margin-right: var(--sapphire-semantic-size-spacing-sm);
419
+ }
420
+ /* the following rule is not yet properly supported. When that's widely supported, we can remove the specific rules */
421
+ .sapphire-table__row[aria-level] {
422
+ --sapphire-table-row-level: attr(aria-level, number);
423
+ }
424
+ .sapphire-table__row[aria-level='1'] {
425
+ --sapphire-table-row-level: 1;
426
+ }
427
+ .sapphire-table__row[aria-level='2'] {
428
+ --sapphire-table-row-level: 2;
429
+ }
430
+ .sapphire-table__row[aria-level='3'] {
431
+ --sapphire-table-row-level: 3;
432
+ }
433
+ .sapphire-table__row[aria-level='4'] {
434
+ --sapphire-table-row-level: 4;
435
+ }
436
+ .sapphire-table__row[aria-level='5'] {
437
+ --sapphire-table-row-level: 5;
369
438
  }
370
439
 
371
- .sapphire-table td:has(.sapphire-table__row-expand-button) {
372
- width: 0; /* To prevent the cell from growing more than needed. only needed when td is used for cells */
440
+ .sapphire-table__headCell.sapphire-table__cell--tree {
441
+ --sapphire-table-row-level: 1;
442
+ }
443
+ .sapphire-table__headCell.sapphire-table__cell--tree
444
+ .sapphire-table__headCell_container {
445
+ padding-left: 0;
373
446
  }
374
447
 
375
- .sapphire-table__row--expanded .sapphire-table__row-expand-button {
448
+ /* tree column renders expand/collapse icon and is indented based on row level */
449
+ .sapphire-table__cell--tree {
450
+ /* the unit of indentation for nested rows. */
451
+ /* Important: this should match the width+margin-right of .sapphire-table__row-expand-button for expandable/non-expandable siblings to align. */
452
+ --sapphire-table-indent-unit: calc(
453
+ var(--sapphire-semantic-size-icon-md) +
454
+ var(--sapphire-semantic-size-spacing-sm)
455
+ );
456
+ --sapphire-table-cell-indent-count: calc(var(--sapphire-table-row-level) - 1);
457
+ padding-left: calc(
458
+ var(--sapphire-table-cell-spacing-h) +
459
+ calc(
460
+ var(--sapphire-table-cell-indent-count) *
461
+ var(--sapphire-table-indent-unit)
462
+ )
463
+ );
464
+ }
465
+ .sapphire-table__cell--tree:not(:has(.sapphire-table__row-expand-button)) {
466
+ --sapphire-table-cell-indent-count: var(--sapphire-table-row-level);
467
+ }
468
+
469
+ .sapphire-table__row-expand-button svg {
470
+ transition: transform var(--sapphire-semantic-transitions-dynamic)
471
+ var(--sapphire-semantic-time-motion-quick);
472
+ }
473
+ .sapphire-table__row-expand-button--expanded svg {
376
474
  transform: rotate(180deg);
377
475
  }
378
476
 
@@ -505,12 +603,12 @@ tbody .sapphire-table__row--highlighted > .sapphire-table__cell:first-child {
505
603
  /* Making sure the button does not change the row height */
506
604
  margin-top: calc(-1 * var(--sapphire-semantic-size-spacing-2xs));
507
605
  margin-bottom: calc(-1 * var(--sapphire-semantic-size-spacing-2xs));
508
- visibility: hidden;
606
+ opacity: 0;
509
607
  flex-shrink: 0;
510
608
  }
511
609
 
512
610
  .sapphire-table__row.is-hover .sapphire-table__edit-button,
513
611
  .sapphire-table__row:hover .sapphire-table__edit-button,
514
612
  .sapphire-table__row:focus-within .sapphire-table__edit-button {
515
- visibility: visible;
613
+ opacity: 1;
516
614
  }
@@ -1,5 +1,6 @@
1
1
  declare const styles: {
2
2
  readonly "sapphire-table": string;
3
+ readonly "sapphire-table--negative-margin-self": string;
3
4
  readonly "sapphire-table--overflow": string;
4
5
  readonly "sapphire-table__table": string;
5
6
  readonly "sapphire-table__table--fixed-layout": string;
@@ -25,6 +26,7 @@ declare const styles: {
25
26
  readonly "sapphire-table__headCell__text": string;
26
27
  readonly "sapphire-table__headCell__icon": string;
27
28
  readonly "sapphire-table__body": string;
29
+ readonly "sapphire-table__cell--tree": string;
28
30
  readonly "sapphire-table__cell-contents": string;
29
31
  readonly "sapphire-table__cell--ellipsed": string;
30
32
  readonly "sapphire-table__headCell_content--ellipsed": string;
@@ -32,13 +34,15 @@ declare const styles: {
32
34
  readonly "sapphire-table__table--spacing-lg": string;
33
35
  readonly "sapphire-table__table--spacing-xl": string;
34
36
  readonly "sapphire-table__tfoot": string;
37
+ readonly "is-disabled": string;
35
38
  readonly "sapphire-table--interactive": string;
36
39
  readonly "sapphire-table__row--active": string;
40
+ readonly "sapphire-table__row--interactive": string;
37
41
  readonly "sapphire-table__row--selected": string;
38
42
  readonly "sapphire-table__row--expanded": string;
39
43
  readonly "sapphire-table__row-expand-button": string;
44
+ readonly "sapphire-table__row-expand-button--expanded": string;
40
45
  readonly "sapphire-table--without-last-divider": string;
41
- readonly "sapphire-table__row--interactive": string;
42
46
  readonly "sapphire-table__row--highlighted": string;
43
47
  readonly "sapphire-table__footer": string;
44
48
  readonly "sapphire-table__footer--sticky": string;