@danske/sapphire-css 48.0.1 → 49.1.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.
@@ -146,6 +146,10 @@
146
146
  .sapphire-accordion__item-content-wrapper {
147
147
  display: grid;
148
148
  grid-template-rows: 0fr;
149
+ }
150
+
151
+ /* React sets height as css variable for transition, Angular does not */
152
+ .sapphire-accordion__item-content-wrapper--with-transition {
149
153
  transition: grid-template-rows var(--sapphire-semantic-time-motion-quick)
150
154
  var(--sapphire-semantic-transitions-dynamic);
151
155
  }
@@ -158,10 +162,8 @@
158
162
  opacity: 0;
159
163
  transition: opacity var(--sapphire-semantic-time-fade-default)
160
164
  var(--sapphire-semantic-transitions-fade),
161
- padding-bottom var(--sapphire-semantic-time-motion-quick)
165
+ height var(--sapphire-semantic-time-motion-quick)
162
166
  var(--sapphire-semantic-transitions-fade);
163
- padding-right: var(--sapphire-semantic-size-spacing-lg);
164
- padding-left: var(--sapphire-semantic-size-spacing-lg);
165
167
  }
166
168
 
167
169
  .sapphire-accordion__item--open > .sapphire-accordion__item-content-wrapper {
@@ -172,7 +174,6 @@
172
174
  > .sapphire-accordion__item-content-wrapper
173
175
  > .sapphire-accordion__item-content {
174
176
  opacity: 1;
175
- padding-bottom: var(--sapphire-semantic-size-spacing-lg);
176
177
  visibility: visible;
177
178
  }
178
179
 
@@ -180,3 +181,9 @@
180
181
  margin-left: calc(var(--sapphire-semantic-size-spacing-lg) * -1);
181
182
  width: calc(100% + (var(--sapphire-semantic-size-spacing-lg) * 2));
182
183
  }
184
+
185
+ .sapphire-accordion__item-content-inner {
186
+ padding-right: var(--sapphire-semantic-size-spacing-lg);
187
+ padding-left: var(--sapphire-semantic-size-spacing-lg);
188
+ padding-bottom: var(--sapphire-semantic-size-spacing-lg);
189
+ }
@@ -10,8 +10,10 @@ declare const styles: {
10
10
  readonly "sapphire-accordion__item--open": string;
11
11
  readonly "sapphire-accordion__item-heading": string;
12
12
  readonly "sapphire-accordion__item-arrow": string;
13
+ readonly "sapphire-accordion__item-content-wrapper--with-transition": string;
13
14
  readonly "sapphire-accordion__item-content": string;
14
15
  readonly "sapphire-accordion--negative-margin-self": string;
16
+ readonly "sapphire-accordion__item-content-inner": string;
15
17
  };
16
18
  export = styles;
17
19
 
@@ -12,10 +12,6 @@
12
12
  white-space: nowrap;
13
13
  }
14
14
 
15
- .sapphire-breadcrumbs__item * {
16
- max-width: var(--sapphire-global-size-generic-480);
17
- }
18
-
19
15
  .sapphire-breadcrumbs__item--static {
20
16
  /* typography */
21
17
  font-family: var(--sapphire-semantic-font-name-default);
@@ -28,10 +24,13 @@
28
24
  padding: 0 var(--sapphire-global-size-generic-50);
29
25
  height: var(--sapphire-semantic-size-height-control-md);
30
26
  min-width: var(--sapphire-global-size-generic-100);
31
- max-width: fit-content; /* When part of flex layout the button will otherwise expand to full width of container when container has flex-direction 'column' */
32
27
  flex-shrink: 0; /* When part of flex layout the button will otherwise be squashed */
33
28
 
34
29
  align-content: center;
30
+
31
+ max-width: calc(10 * var(--sapphire-semantic-size-height-control-md));
32
+ overflow: hidden;
33
+ text-overflow: ellipsis;
35
34
  }
36
35
 
37
36
  .sapphire-breadcrumbs .sapphire-breadcrumbs__item:last-child {
@@ -53,6 +52,7 @@
53
52
  padding: 0 var(--sapphire-semantic-size-spacing-md);
54
53
  font-size: var(--sapphire-semantic-size-font-control-sm);
55
54
  border-radius: var(--sapphire-semantic-size-height-control-sm);
55
+ max-width: calc(10 * var(--sapphire-semantic-size-height-control-sm));
56
56
  }
57
57
 
58
58
  .sapphire-breadcrumbs.sapphire-breadcrumbs--lg
@@ -70,6 +70,7 @@
70
70
  padding: 0 var(--sapphire-semantic-size-spacing-xl);
71
71
  font-size: var(--sapphire-semantic-size-font-control-lg);
72
72
  border-radius: var(--sapphire-semantic-size-height-control-lg);
73
+ max-width: calc(10 * var(--sapphire-semantic-size-height-control-lg));
73
74
  }
74
75
 
75
76
  /**
@@ -1,9 +1,11 @@
1
1
  .sapphire-bulk-actions-bar {
2
2
  display: flex;
3
+ min-height: var(--sapphire-global-size-generic-180);
4
+ box-sizing: border-box;
3
5
  align-items: center;
4
6
  justify-content: space-between;
5
- padding: var(--sapphire-semantic-size-spacing-sm)
6
- var(--sapphire-semantic-size-spacing-md);
7
+ padding: var(--sapphire-semantic-size-spacing-md)
8
+ var(--sapphire-semantic-size-spacing-xl);
7
9
  /* the bg color here is a hack until the design of this changes */
8
10
  background: var(--sapphire-semantic-color-background-neutral-subtle);
9
11
  position: sticky;
@@ -38,8 +38,9 @@
38
38
  padding: 0 var(--sapphire-semantic-size-spacing-md);
39
39
  height: var(--sapphire-semantic-size-height-control-md);
40
40
  min-width: var(--sapphire-global-size-generic-200);
41
- max-width: fit-content; /* When part of flex layout the button will otherwise expand to full width of container when container has flex-direction 'column' */
42
- flex-shrink: 0; /* When part of flex layout the button will otherwise be squashed */
41
+ width: fit-content;
42
+ max-width: 100%;
43
+ flex-shrink: 1;
43
44
 
44
45
  /* shape */
45
46
  border-radius: var(--sapphire-semantic-size-height-control-md);
@@ -56,9 +57,8 @@
56
57
  }
57
58
 
58
59
  .sapphire-button__content {
59
- display: inline-flex;
60
60
  align-items: center;
61
- justify-content: center;
61
+ text-align: center;
62
62
  vertical-align: middle;
63
63
  white-space: nowrap;
64
64
  user-select: none;
@@ -68,6 +68,20 @@
68
68
  margin: 0;
69
69
  width: 100%;
70
70
  padding: 0 var(--sapphire-semantic-size-spacing-xs);
71
+ max-width: calc(10 * var(--sapphire-semantic-size-height-control-md));
72
+ overflow: hidden;
73
+ text-overflow: ellipsis;
74
+ }
75
+
76
+ .sapphire-button--stretch,
77
+ .sapphire-button--stretch-left-align {
78
+ max-width: 100%;
79
+ min-width: fit-content;
80
+ flex-grow: 1;
81
+ }
82
+
83
+ .sapphire-button--stretch-left-align .sapphire-button__content {
84
+ text-align: start;
71
85
  }
72
86
 
73
87
  a.sapphire-button {
@@ -491,6 +505,9 @@ a.sapphire-button {
491
505
  padding: 0;
492
506
  border-radius: var(--sapphire-semantic-size-radius-xs);
493
507
  }
508
+ .sapphire-button--lg .sapphire-button__content {
509
+ max-width: calc(10 * var(--sapphire-semantic-size-height-control-lg));
510
+ }
494
511
 
495
512
  /**
496
513
  * SMALL
@@ -510,4 +527,5 @@ a.sapphire-button {
510
527
 
511
528
  .sapphire-button--sm .sapphire-button__content {
512
529
  padding: 0 var(--sapphire-semantic-size-spacing-2xs);
530
+ max-width: calc(10 * var(--sapphire-semantic-size-height-control-sm));
513
531
  }
@@ -1,6 +1,8 @@
1
1
  declare const styles: {
2
2
  readonly "sapphire-button": string;
3
3
  readonly "sapphire-button__content": string;
4
+ readonly "sapphire-button--stretch": string;
5
+ readonly "sapphire-button--stretch-left-align": string;
4
6
  readonly "is-disabled": string;
5
7
  readonly "is-focus": string;
6
8
  readonly "js-focus": string;
@@ -51,6 +51,11 @@
51
51
  flex-wrap: nowrap;
52
52
  }
53
53
 
54
+ .sapphire-button-group--stretch.sapphire-button-group--stretch-auto-vertical
55
+ > * {
56
+ width: auto !important;
57
+ }
58
+
54
59
  .sapphire-button-group--stretch.sapphire-button-group--stretch-auto-vertical.sapphire-button-group:has(
55
60
  > *:nth-child(3)
56
61
  ) {
@@ -1,7 +1,7 @@
1
1
  .sapphire-field-group {
2
2
  display: flex;
3
3
  flex-wrap: wrap;
4
- column-gap: var(--sapphire-semantic-size-spacing-lg);
4
+ column-gap: var(--sapphire-semantic-size-spacing-xl);
5
5
  row-gap: var(--sapphire-semantic-size-spacing-sm);
6
6
  }
7
7
 
@@ -14,5 +14,5 @@
14
14
  }
15
15
 
16
16
  .sapphire-field-group--md {
17
- row-gap: var(--sapphire-semantic-size-spacing-2xs);
17
+ row-gap: var(--sapphire-semantic-size-spacing-xs);
18
18
  }
@@ -165,14 +165,14 @@ instead of being applied on the list item itself */
165
165
  .sapphire-list__item--interactive.is-hover:not(.is-active):not(:has(.is-hover)),
166
166
  .sapphire-list__item--interactive:not(.js-hover):not(
167
167
  [aria-disabled='true']
168
- ):not(:disabled):not(:active):not(:has(:hover)):hover {
168
+ ):not(:disabled):not(:active):not(:has(:focus-within)):hover {
169
169
  background: var(--sapphire-semantic-color-background-action-tertiary-hover);
170
170
  }
171
171
 
172
172
  .sapphire-list__item--selected.is-hover:not(.is-active):not(:has(.is-hover)),
173
173
  .sapphire-list__item--selected:not(.js-hover):not([aria-disabled='true']):not(
174
174
  :disabled
175
- ):not(:active):not(:has(:hover)):hover {
175
+ ):not(:active):not(:has(:focus-within)):hover {
176
176
  background: var(
177
177
  --sapphire-semantic-color-background-action-select-secondary-hover
178
178
  );
@@ -197,12 +197,14 @@ instead of being applied on the list item itself */
197
197
 
198
198
  /* Active */
199
199
 
200
+ /* The 2 instances of button[aria-expanded='true'] below is a hack to accomodate the scenario where
201
+ the contentRight button, when it triggers a menu, does not get the active state. */
200
202
  .sapphire-list__item--interactive:not(.is-disabled).is-active:not(
201
203
  :has(.is-active)
202
204
  ),
203
205
  .sapphire-list__item--interactive:not([aria-disabled='true']):not(
204
206
  :disabled
205
- ):not(:has(:active)):active {
207
+ ):not(:has(:focus-within, button[aria-expanded='true'])):active {
206
208
  background-color: var(
207
209
  --sapphire-semantic-color-background-action-secondary-hover
208
210
  );
@@ -212,7 +214,7 @@ instead of being applied on the list item itself */
212
214
  :has(.is-active)
213
215
  ),
214
216
  .sapphire-list__item--selected:not([aria-disabled='true']):not(:disabled):not(
215
- :has(:active)
217
+ :has(:focus-within, button[aria-expanded='true'])
216
218
  ):active {
217
219
  background-color: var(
218
220
  --sapphire-semantic-color-background-action-select-secondary-active
@@ -199,7 +199,9 @@ Hence a separate class for checkmark icon to be used in the alignment styles */
199
199
  );
200
200
  }
201
201
 
202
- .sapphire-listbox__separator {
202
+ .sapphire-listbox__separator,
203
+ .sapphire-listbox__separator.sapphire-listbox__separator {
204
+ width: auto;
203
205
  height: var(--sapphire-semantic-size-border-sm);
204
206
  background: var(--sapphire-semantic-color-border-secondary);
205
207
  margin: var(--sapphire-listbox-items-gap)
@@ -12,6 +12,10 @@
12
12
  background: var(--sapphire-semantic-color-background-popover);
13
13
  }
14
14
 
15
+ .sapphire-panel--left {
16
+ transform: translateX(-100%);
17
+ }
18
+
15
19
  .sapphire-panel--visible {
16
20
  transform: translateX(0%);
17
21
  }
@@ -1,5 +1,6 @@
1
1
  declare const styles: {
2
2
  readonly "sapphire-panel": string;
3
+ readonly "sapphire-panel--left": string;
3
4
  readonly "sapphire-panel--visible": string;
4
5
  readonly "sapphire-panel--sm": string;
5
6
  };
@@ -0,0 +1,67 @@
1
+ .sapphire-password-field__button {
2
+ box-sizing: border-box;
3
+ display: flex;
4
+ align-items: center;
5
+ justify-content: center;
6
+ vertical-align: middle;
7
+ white-space: nowrap;
8
+ /* In Safari buttons get a 2px border
9
+ * https://github.com/necolas/normalize.css/blob/master/normalize.css#L160-L169
10
+ */
11
+ margin: 0;
12
+ padding: 0;
13
+ /* height: var(--sapphire-dateField-icon-size);
14
+ width: var(--sapphire-dateField-icon-size); */
15
+ background: transparent;
16
+ color: var(--sapphire-semantic-color-foreground-secondary);
17
+ cursor: pointer;
18
+
19
+ /* shape */
20
+ border-radius: var(--sapphire-semantic-size-radius-xs);
21
+ border-style: solid;
22
+ border-width: 0;
23
+ border-color: transparent;
24
+
25
+ /* transition for color */
26
+ transition-property: color;
27
+ transition-duration: var(--sapphire-semantic-time-fade-quick);
28
+ transition-timing-function: var(--sapphire-semantic-transitions-fade);
29
+ }
30
+
31
+ /**
32
+ * Hover
33
+ */
34
+ .sapphire-password-field__button:not(:disabled):not(.is-disabled):not(
35
+ :active
36
+ ):not(.is-active):not(.js-hover):hover,
37
+ .sapphire-password-field__button:not(:disabled):not(.is-disabled):not(
38
+ :active
39
+ ):not(.is-active).is-hover {
40
+ color: var(--sapphire-semantic-color-foreground-primary);
41
+ }
42
+
43
+ /**
44
+ * Active
45
+ */
46
+ .sapphire-password-field__button:not(:disabled):not(.is-disabled).is-active,
47
+ .sapphire-password-field__button:not(:disabled):not(.is-disabled):active,
48
+ .sapphire-password-field__button:not(:disabled):not(
49
+ .is-disabled
50
+ ):focus-visible:active {
51
+ color: var(--sapphire-semantic-color-foreground-primary);
52
+ }
53
+ /**
54
+ * Focus
55
+ */
56
+ .sapphire-password-field__button.is-focus,
57
+ .sapphire-password-field__button:not(.js-focus):focus-visible {
58
+ outline: var(--sapphire-semantic-size-focus-ring) solid
59
+ var(--sapphire-semantic-color-focus-ring);
60
+ }
61
+ /**
62
+ * Disabled
63
+ */
64
+ .sapphire-password-field__button:disabled,
65
+ .sapphire-password-field__button.is-disabled {
66
+ cursor: not-allowed;
67
+ }
@@ -0,0 +1,11 @@
1
+ declare const styles: {
2
+ readonly "sapphire-password-field__button": string;
3
+ readonly "is-disabled": string;
4
+ readonly "is-active": string;
5
+ readonly "js-hover": string;
6
+ readonly "is-hover": string;
7
+ readonly "is-focus": string;
8
+ readonly "js-focus": string;
9
+ };
10
+ export = styles;
11
+
@@ -0,0 +1,14 @@
1
+ .sapphire-separator {
2
+ height: 1px;
3
+ background-color: var(--sapphire-semantic-color-border-secondary);
4
+ border: none;
5
+ width: 100%;
6
+ }
7
+
8
+ .sapphire-separator[aria-orientation='vertical'] {
9
+ width: 1px;
10
+ height: auto;
11
+ min-height: 100%;
12
+ flex-direction: column;
13
+ align-self: stretch;
14
+ }
@@ -0,0 +1,5 @@
1
+ declare const styles: {
2
+ readonly "sapphire-separator": string;
3
+ };
4
+ export = styles;
5
+
@@ -0,0 +1,204 @@
1
+ @keyframes slide-in {
2
+ 0% {
3
+ transform: translate(-7%);
4
+ opacity: 0;
5
+ }
6
+
7
+ 100% {
8
+ transform: translate(0%);
9
+ opacity: 1;
10
+ }
11
+ }
12
+
13
+ @keyframes slide-out {
14
+ 0% {
15
+ transform: translate(0%);
16
+ opacity: 1;
17
+ }
18
+
19
+ 100% {
20
+ transform: translate(-7%);
21
+ opacity: 0;
22
+ display: none;
23
+ }
24
+ }
25
+
26
+ .sapphire-sidebar {
27
+ box-sizing: border-box;
28
+ /* the secondary sidebar is relative to this */
29
+ position: relative;
30
+ font-family: var(--sapphire-semantic-font-name-default);
31
+
32
+ --sapphire-sidebar-spacing-horizontal: var(
33
+ --sapphire-semantic-size-spacing-md
34
+ );
35
+
36
+ /* The below is meant to address a font rendering quirk in OSX where the text
37
+ * looks bolder than intended due to subpixel rendering. This quirk generally
38
+ * occurs for bold fonts on dark backgrounds but depending on the font, it
39
+ * can happen in other contexts as well.
40
+ *
41
+ * These do not do anything except in webkit browsers & firefox on OSX.
42
+ *
43
+ * For more details see:
44
+ * - https://azuredevops/Main/WCCJ/_git/sapphire/pullRequest/212710?path=%2Fpackages%2Fcss%2Fcomponents%2Fbutton%2Fbutton.module.css&discussionId=1507702&_a=files
45
+ * - https://usabilitypost.com/2012/11/05/stop-fixing-font-smoothing/
46
+ */
47
+ -webkit-font-smoothing: antialiased;
48
+ -moz-osx-font-smoothing: grayscale;
49
+
50
+ display: flex;
51
+ flex-direction: column;
52
+
53
+ /**
54
+ * Normally the background and foreground belong to the `surface`
55
+ * but the sidebar is a little bit special. Part of what a sidebar is, is
56
+ * that it has the surface background color. Similar to popovers.
57
+ */
58
+ background: var(--sapphire-semantic-color-background-surface);
59
+ padding-left: var(--sapphire-sidebar-spacing-horizontal);
60
+ padding-right: var(--sapphire-sidebar-spacing-horizontal);
61
+
62
+ min-width: var(--sapphire-global-size-generic-600);
63
+ max-width: fit-content;
64
+ height: 100%;
65
+ }
66
+
67
+ /**
68
+ * Applied on secondary sidebar for transition
69
+ */
70
+ .sapphire-sidebar--slide-in {
71
+ animation: slide-in var(--sapphire-semantic-time-fade-default)
72
+ var(--sapphire-semantic-transitions-dynamic);
73
+ }
74
+
75
+ .sapphire-sidebar--slide-out {
76
+ animation: slide-out var(--sapphire-semantic-time-fade-default)
77
+ var(--sapphire-semantic-transitions-dynamic) forwards;
78
+ }
79
+
80
+ .sapphire-sidebar__secondary-container {
81
+ position: absolute;
82
+ top: 0;
83
+ left: 100%;
84
+ height: 100%;
85
+ border-right: var(--sapphire-semantic-size-border-sm) solid
86
+ var(--sapphire-semantic-color-border-secondary);
87
+ }
88
+
89
+ /* Header */
90
+ .sapphire-sidebar__header {
91
+ display: flex;
92
+ justify-content: space-between;
93
+ align-items: center;
94
+ gap: var(--sapphire-semantic-size-spacing-sm);
95
+
96
+ padding-top: var(--sapphire-semantic-size-spacing-xl);
97
+ padding-bottom: var(--sapphire-semantic-size-spacing-xl);
98
+ padding-left: var(--sapphire-semantic-size-spacing-lg);
99
+
100
+ /**
101
+ * Need a min height to avoid moving the heading in case it contains a
102
+ * regular icon button, like it will always do in the secondary heading
103
+ */
104
+ box-sizing: content-box;
105
+ min-height: var(--sapphire-semantic-size-height-control-md);
106
+ }
107
+
108
+ /* Body (main content) */
109
+ .sapphire-sidebar__body {
110
+ flex-grow: 1;
111
+ overflow: auto;
112
+ margin-left: calc(-1 * var(--sapphire-sidebar-spacing-horizontal));
113
+ margin-right: calc(-1 * var(--sapphire-sidebar-spacing-horizontal));
114
+ padding-left: var(--sapphire-sidebar-spacing-horizontal);
115
+ padding-right: var(--sapphire-sidebar-spacing-horizontal);
116
+ }
117
+
118
+ /* Modifier for when list has scrolled. Needs JS control. */
119
+ .sapphire-sidebar__body--scrolled {
120
+ border-top: var(--sapphire-semantic-size-border-sm) solid
121
+ var(--sapphire-semantic-color-border-secondary);
122
+ }
123
+
124
+ /* Nav list (usually a <ul> or <ol>) */
125
+ .sapphire-sidebar__nav-list {
126
+ --sapphire-sidebar-item-gap: var(--sapphire-semantic-size-spacing-3xs);
127
+ --sapphire-sidebar-spacing-separator-horizontal: var(
128
+ --sapphire-semantic-size-spacing-3xs
129
+ );
130
+
131
+ margin: 0;
132
+ list-style: none;
133
+ display: flex;
134
+ flex-direction: column;
135
+ gap: var(--sapphire-sidebar-item-gap);
136
+ padding-left: 0;
137
+ padding-right: 0;
138
+ padding-top: var(--sapphire-semantic-size-spacing-xs);
139
+ padding-bottom: var(--sapphire-semantic-size-spacing-xl);
140
+ }
141
+
142
+ .sapphire-sidebar__nav-item {
143
+ display: flex;
144
+ }
145
+
146
+ /**
147
+ * Custom increase of clickable area of the button
148
+ */
149
+ .sapphire-sidebar__nav-item > [role='button'] {
150
+ position: relative;
151
+ }
152
+
153
+ .sapphire-sidebar__nav-item > [role='button']::before {
154
+ content: '';
155
+ position: absolute;
156
+ top: calc(-1 * (var(--sapphire-sidebar-item-gap) / 2));
157
+ bottom: calc(-1 * (var(--sapphire-sidebar-item-gap) / 2));
158
+ left: 0;
159
+ right: 0;
160
+ background: transparent;
161
+ }
162
+
163
+ /* Sections */
164
+ .sapphire-sidebar__separator {
165
+ height: var(--sapphire-semantic-size-border-sm);
166
+ background: var(--sapphire-semantic-color-border-secondary);
167
+ margin: var(--sapphire-semantic-size-spacing-3xs)
168
+ calc(
169
+ var(--sapphire-semantic-size-spacing-lg) -
170
+ var(--sapphire-sidebar-spacing-separator-horizontal)
171
+ );
172
+ }
173
+
174
+ .sapphire-sidebar__nav-list > .sapphire-sidebar__separator:first-child {
175
+ display: none;
176
+ }
177
+
178
+ .sapphire-sidebar__section {
179
+ padding: 0;
180
+ margin: 0;
181
+ list-style: none;
182
+ display: flex;
183
+ flex-direction: column;
184
+ gap: var(--sapphire-sidebar-item-gap);
185
+ }
186
+
187
+ .sapphire-sidebar__section-header {
188
+ font-size: var(--sapphire-semantic-size-font-body-xs);
189
+ color: var(--sapphire-semantic-color-foreground-primary);
190
+ font-weight: var(--sapphire-semantic-font-weight-default-medium);
191
+ padding: calc(
192
+ var(--sapphire-semantic-size-spacing-md) -
193
+ var(--sapphire-sidebar-item-gap)
194
+ )
195
+ calc(
196
+ var(--sapphire-semantic-size-spacing-sm) +
197
+ var(--sapphire-sidebar-spacing-separator-horizontal)
198
+ )
199
+ var(--sapphire-semantic-size-spacing-2xs)
200
+ calc(
201
+ var(--sapphire-semantic-size-spacing-sm) +
202
+ var(--sapphire-sidebar-spacing-separator-horizontal)
203
+ );
204
+ }
@@ -0,0 +1,18 @@
1
+ declare const styles: {
2
+ readonly "sapphire-sidebar": string;
3
+ readonly "sapphire-sidebar--slide-in": string;
4
+ readonly "slide-in": string;
5
+ readonly "sapphire-sidebar--slide-out": string;
6
+ readonly "slide-out": string;
7
+ readonly "sapphire-sidebar__secondary-container": string;
8
+ readonly "sapphire-sidebar__header": string;
9
+ readonly "sapphire-sidebar__body": string;
10
+ readonly "sapphire-sidebar__body--scrolled": string;
11
+ readonly "sapphire-sidebar__nav-list": string;
12
+ readonly "sapphire-sidebar__nav-item": string;
13
+ readonly "sapphire-sidebar__separator": string;
14
+ readonly "sapphire-sidebar__section": string;
15
+ readonly "sapphire-sidebar__section-header": string;
16
+ };
17
+ export = styles;
18
+
@@ -479,3 +479,34 @@ tbody .sapphire-table__row--highlighted > .sapphire-table__cell:first-child {
479
479
  right: 0;
480
480
  left: 0;
481
481
  }
482
+
483
+ /**
484
+ * Editable cell
485
+ */
486
+ .sapphire-table__cell-container--editable {
487
+ display: flex;
488
+ align-items: center;
489
+ justify-content: space-between;
490
+ gap: var(--sapphire-semantic-size-spacing-md);
491
+ }
492
+
493
+ .sapphire-table__edit-cell-popover {
494
+ display: flex;
495
+ align-items: start;
496
+ justify-content: space-between;
497
+ gap: var(--sapphire-semantic-size-spacing-sm);
498
+ }
499
+
500
+ .sapphire-table__edit-button {
501
+ /* Making sure the button does not change the row height */
502
+ margin-top: calc(-1 * var(--sapphire-semantic-size-spacing-2xs));
503
+ margin-bottom: calc(-1 * var(--sapphire-semantic-size-spacing-2xs));
504
+ visibility: hidden;
505
+ flex-shrink: 0;
506
+ }
507
+
508
+ .sapphire-table__row.is-hover .sapphire-table__edit-button,
509
+ .sapphire-table__row:hover .sapphire-table__edit-button,
510
+ .sapphire-table__row:focus-within .sapphire-table__edit-button {
511
+ visibility: visible;
512
+ }
@@ -43,6 +43,9 @@ declare const styles: {
43
43
  readonly "sapphire-table__footer": string;
44
44
  readonly "sapphire-table__footer--sticky": string;
45
45
  readonly "sapphire-table__footer--virtualized": string;
46
+ readonly "sapphire-table__cell-container--editable": string;
47
+ readonly "sapphire-table__edit-cell-popover": string;
48
+ readonly "sapphire-table__edit-button": string;
46
49
  };
47
50
  export = styles;
48
51
 
@@ -8,6 +8,7 @@
8
8
  .sapphire-tag {
9
9
  display: inline-flex;
10
10
  height: var(--sapphire-semantic-size-height-control-sm);
11
+ max-width: calc(var(--sapphire-semantic-size-height-control-sm) * 10);
11
12
  padding: 0 var(--sapphire-semantic-size-spacing-md);
12
13
  align-items: center;
13
14
  border-radius: var(--sapphire-semantic-size-height-control-sm);
@@ -59,6 +60,15 @@
59
60
  display: inline-flex;
60
61
  align-items: center;
61
62
  gap: var(--sapphire-semantic-size-spacing-xs);
63
+ min-width: 0;
64
+ flex: 1;
65
+ }
66
+
67
+ .sapphire-tag__label {
68
+ overflow: hidden;
69
+ text-overflow: ellipsis;
70
+ white-space: nowrap;
71
+ min-width: 0;
62
72
  }
63
73
 
64
74
  /* Actionable */
@@ -97,6 +107,7 @@
97
107
  display: flex;
98
108
  align-items: center;
99
109
  color: var(--sapphire-semantic-color-foreground-negative);
110
+ flex-shrink: 0;
100
111
  }
101
112
 
102
113
  /**
@@ -117,6 +128,7 @@
117
128
  margin: 0;
118
129
  padding: 0;
119
130
  background: transparent;
131
+ flex-shrink: 0;
120
132
 
121
133
  /* transition */
122
134
  transition-property: color;
@@ -4,6 +4,7 @@ declare const styles: {
4
4
  readonly "is-focus": string;
5
5
  readonly "js-focus": string;
6
6
  readonly "sapphire-tag__content": string;
7
+ readonly "sapphire-tag__label": string;
7
8
  readonly "sapphire-tag--actionable": string;
8
9
  readonly "is-disabled": string;
9
10
  readonly "is-active": string;
@@ -225,6 +225,16 @@
225
225
  outline-offset: calc(0px - var(--sapphire-semantic-size-focus-ring));
226
226
  }
227
227
 
228
+ /**
229
+ * Focus override in the case of password visibility toggle being focused.
230
+ (sapphire-password-field__button)
231
+ */
232
+ .sapphire-text-field:has(button:focus) {
233
+ outline: solid var(--sapphire-semantic-size-border-sm)
234
+ var(--sapphire-semantic-color-border-field-default);
235
+ outline-offset: calc(0px - var(--sapphire-semantic-size-border-sm));
236
+ }
237
+
228
238
  .sapphire-text-field.is-focus .sapphire-text-field__input:autofill,
229
239
  .sapphire-text-field:focus-within .sapphire-text-field__input:autofill {
230
240
  /*
@@ -1,106 +1,193 @@
1
- @keyframes fade-in {
1
+ @keyframes slide-in {
2
2
  from {
3
- opacity: 0;
4
3
  transform: translate3d(
5
4
  0,
6
- calc(var(--sapphire-toast-animation-direction, 1) * 100%),
5
+ /* NOTE: 1rem is hardcoded since sapphire variables are not accessible
6
+ at html::view-transition-* pseudo-elements. Can be improved when scoped
7
+ view transitions are implemented: https://developer.chrome.com/blog/scoped-view-transitions-feedback
8
+ */
9
+ calc(var(--sapphire-toast-animation-direction, 1) * 100% + 1rem),
7
10
  0
8
11
  )
9
- translateX(var(--sapphire-toast-horizontal-transform)) scale(0.9);
12
+ scale(0.9);
10
13
  }
14
+ }
11
15
 
16
+ @keyframes slide-out {
12
17
  to {
13
- opacity: 1;
14
- transform: translate3d(0, 0, 0)
15
- translateX(var(--sapphire-toast-horizontal-transform)) scale(1);
18
+ opacity: 0;
19
+ transform: translate3d(
20
+ 0,
21
+ calc(var(--sapphire-toast-animation-direction, 1) * 100% + 1rem),
22
+ 0
23
+ )
24
+ scale(0.9);
16
25
  }
17
26
  }
18
27
 
19
- @keyframes fade-out {
20
- from {
21
- opacity: 1;
28
+ ::view-transition-group(.sapphire-toast-view-transition--reverse) {
29
+ --sapphire-toast-animation-direction: -1;
30
+ }
31
+
32
+ @media (prefers-reduced-motion: no-preference) {
33
+ ::view-transition-group(.sapphire-toast-view-transition) {
34
+ /* NOTE: the values are hardcoded since sapphire variables are not accessible
35
+ at html::view-transition-* pseudo-elements. Can be improved when scoped
36
+ view transitions are implemented: https://developer.chrome.com/blog/scoped-view-transitions-feedback
37
+ */
38
+ animation-duration: 200ms;
39
+ animation-timing-function: cubic-bezier(0, 0, 0, 1);
22
40
  }
23
41
 
24
- to {
25
- opacity: 0;
42
+ /*
43
+ * animation customization
44
+ * the default view transition animation works fine
45
+ * for all state changes except for two cases that we need to customize:
46
+ * 1. a new toast should be added with a slide-in animation
47
+ * 2. the first toast should be removed with a slide-out animation
48
+ */
49
+ ::view-transition-new(.sapphire-toast-view-transition):only-child {
50
+ animation-name: slide-in;
51
+ }
52
+ ::view-transition-old(.sapphire-toast-view-transition):only-child {
53
+ animation-name: slide-out;
54
+ }
55
+ }
56
+
57
+ @media (prefers-reduced-motion: reduce) {
58
+ /* Avoid view transition for individual toast when user prefers reduced motion */
59
+ .sapphire-toast {
60
+ view-transition-name: none !important;
26
61
  }
27
62
  }
28
63
 
29
64
  .sapphire-toast-container {
30
65
  pointer-events: none;
31
66
  position: fixed;
67
+ display: flex;
68
+ flex-direction: column;
69
+ align-items: center;
70
+ width: 100%;
71
+ max-height: calc(100vh - 2 * var(--sapphire-semantic-size-spacing-md));
32
72
  }
33
73
 
34
74
  /* Placement */
35
75
  .sapphire-toast-container--bottom {
36
- --sapphire-toast-horizontal-transform: -50%;
37
- bottom: 0;
38
- left: 50%;
39
- margin-bottom: var(--sapphire-semantic-size-spacing-md);
76
+ bottom: var(--sapphire-semantic-size-spacing-md);
77
+ left: 0;
40
78
  }
41
79
 
42
80
  .sapphire-toast-container--bottom-left {
43
- --sapphire-toast-horizontal-transform: 0%;
44
- bottom: 0;
45
- left: 0;
46
- margin-bottom: var(--sapphire-semantic-size-spacing-md);
47
- margin-left: var(--sapphire-semantic-size-spacing-md);
81
+ bottom: var(--sapphire-semantic-size-spacing-md);
82
+ left: var(--sapphire-semantic-size-spacing-md);
83
+ align-items: flex-start;
48
84
  }
49
85
 
50
86
  .sapphire-toast-container--bottom-right {
51
- --sapphire-toast-horizontal-transform: 0%;
52
- bottom: 0;
53
- right: 0;
54
- margin-bottom: var(--sapphire-semantic-size-spacing-md);
55
- margin-right: var(--sapphire-semantic-size-spacing-md);
87
+ bottom: var(--sapphire-semantic-size-spacing-md);
88
+ right: var(--sapphire-semantic-size-spacing-md);
89
+ align-items: flex-end;
56
90
  }
57
91
 
58
92
  .sapphire-toast-container--top {
59
- --sapphire-toast-animation-direction: -1;
60
- --sapphire-toast-horizontal-transform: -50%;
61
- top: 0;
62
- left: 50%;
63
- margin-top: var(--sapphire-semantic-size-spacing-md);
93
+ top: var(--sapphire-semantic-size-spacing-md);
94
+ left: 0;
64
95
  }
65
96
 
66
97
  .sapphire-toast-container--top-left {
67
- --sapphire-toast-animation-direction: -1;
68
- --sapphire-toast-horizontal-transform: 0%;
69
- top: 0;
70
- left: 0;
71
- margin-top: var(--sapphire-semantic-size-spacing-md);
72
- margin-left: var(--sapphire-semantic-size-spacing-md);
98
+ top: var(--sapphire-semantic-size-spacing-md);
99
+ left: var(--sapphire-semantic-size-spacing-md);
100
+ align-items: flex-start;
73
101
  }
74
102
 
75
103
  .sapphire-toast-container--top-right {
76
- --sapphire-toast-animation-direction: -1;
77
- --sapphire-toast-horizontal-transform: 0%;
104
+ top: var(--sapphire-semantic-size-spacing-md);
105
+ right: var(--sapphire-semantic-size-spacing-md);
106
+ align-items: flex-end;
107
+ }
108
+
109
+ .sapphire-toast-container--top:has(.sapphire-toast-list--expanded),
110
+ .sapphire-toast-container--top-left:has(.sapphire-toast-list--expanded),
111
+ .sapphire-toast-container--top-right:has(.sapphire-toast-list--expanded) {
78
112
  top: 0;
79
- right: 0;
80
- margin-top: var(--sapphire-semantic-size-spacing-md);
81
- margin-right: var(--sapphire-semantic-size-spacing-md);
113
+ }
114
+
115
+ .sapphire-toast-container--bottom:has(.sapphire-toast-list--expanded),
116
+ .sapphire-toast-container--bottom-left:has(.sapphire-toast-list--expanded),
117
+ .sapphire-toast-container--bottom-right:has(.sapphire-toast-list--expanded) {
118
+ bottom: 0;
119
+ }
120
+
121
+ .sapphire-toast-list {
122
+ flex-grow: 1;
123
+ pointer-events: all;
124
+ position: relative;
125
+ display: flex;
126
+ flex-direction: column-reverse;
127
+ align-items: center;
128
+ gap: var(--sapphire-semantic-size-spacing-sm);
129
+
130
+ padding: 0;
131
+ margin: 0;
132
+ transition: perspective-origin var(--sapphire-semantic-time-motion-default)
133
+ var(--sapphire-semantic-transitions-dynamic);
134
+ }
135
+
136
+ .sapphire-toast-list--expanded {
137
+ overflow-y: auto;
138
+ overflow-x: visible;
139
+ padding: var(--sapphire-semantic-size-spacing-md)
140
+ calc(var(--sapphire-semantic-size-focus-ring) * 2);
141
+ margin: 0 calc(var(--sapphire-semantic-size-focus-ring) * -2);
142
+ }
143
+
144
+ .sapphire-toast-list--collapsed {
145
+ perspective: calc(
146
+ var(--sapphire-semantic-size-spacing-sm) * 2 +
147
+ var(--sapphire-global-size-generic-140)
148
+ );
149
+ --sapphire-origin-y: 200%;
150
+ perspective-origin: center calc(-1 * var(--sapphire-origin-y));
151
+ }
152
+
153
+ .sapphire-toast-list--collapsed.js-hover.is-hover:has(> :nth-child(2)),
154
+ .sapphire-toast-list--collapsed:not(.js-hover):hover:has(> :nth-child(2)) {
155
+ --sapphire-origin-y: 280%;
156
+ }
157
+
158
+ .sapphire-toast-container--top .sapphire-toast-list,
159
+ .sapphire-toast-container--top-left .sapphire-toast-list,
160
+ .sapphire-toast-container--top-right .sapphire-toast-list {
161
+ perspective-origin: center calc(100% + var(--sapphire-origin-y));
162
+ flex-direction: column;
163
+ }
164
+
165
+ .sapphire-toast-list:has(> :nth-child(2)) .sapphire-toast,
166
+ .sapphire-toast-list:has(> :nth-child(2)) .sapphire-toast {
167
+ cursor: pointer;
168
+ }
169
+
170
+ /* when the view transition is active, we want to delay the transition of the toast list
171
+ to make sure hover effects are not triggered */
172
+ :root:active-view-transition .sapphire-toast-list {
173
+ transition-delay: 2s;
82
174
  }
83
175
 
84
176
  /************************************************************/
85
177
 
86
178
  .sapphire-toast {
87
179
  pointer-events: initial;
88
- position: absolute;
180
+ position: relative;
89
181
  inset: inherit;
90
- /* absolute position & center */
91
- transform: translateX(var(--sapphire-toast-horizontal-transform));
92
182
 
93
- /* let the text grow until max-width */
94
- width: max-content;
183
+ width: min(
184
+ var(--sapphire-global-size-generic-850),
185
+ calc(100vw - 2 * var(--sapphire-semantic-size-spacing-md))
186
+ );
187
+ flex-shrink: 0;
95
188
 
96
189
  overflow: hidden;
97
- max-width: var(--sapphire-global-size-generic-1400);
98
- min-width: var(--sapphire-global-size-generic-750);
99
190
  border-radius: var(--sapphire-semantic-size-radius-lg);
100
- animation-duration: var(--sapphire-semantic-time-motion-default);
101
-
102
- animation-timing-function: var(--sapphire-semantic-transitions-fade);
103
-
104
191
  /* if implemented as focusable, we don't want the outline because this is not
105
192
  * an an interactive element in itself */
106
193
  outline: none;
@@ -120,22 +207,54 @@
120
207
  -moz-osx-font-smoothing: grayscale;
121
208
  }
122
209
 
123
- .sapphire-toast--entering {
124
- animation-name: fade-in;
210
+ /* focus */
211
+ .sapphire-toast:not(.js-focus):focus-visible,
212
+ .sapphire-toast.is-focus {
213
+ outline: var(--sapphire-semantic-size-focus-ring) solid
214
+ var(--sapphire-semantic-color-focus-ring);
215
+ outline-offset: var(--sapphire-semantic-size-focus-ring);
125
216
  }
126
217
 
127
- /* This represents the toast which appears immediately after the current one
128
- * disappears */
129
- .sapphire-toast--queued {
130
- opacity: 0;
131
- animation-name: fade-in;
132
- animation-delay: var(--sapphire-semantic-time-motion-default);
133
- animation-fill-mode: forwards;
218
+ .sapphire-toast.sapphire-toast--stacked {
219
+ /* Position absolute is needed for the correct container sizing */
220
+ /* stylelint-disable csstools/value-no-unknown-custom-properties */
221
+ position: absolute;
222
+ /* when stacked, toasts after the third one should not be visible.
223
+ They are still expected to be rendered so that the view transition
224
+ works as expected without needing any special style */
225
+ --sapphire-toast-position-index: min(var(--sapphire-toast-index, 0), 2);
226
+
227
+ translate: 0 0
228
+ calc(
229
+ var(--sapphire-toast-position-index) *
230
+ var(--sapphire-semantic-size-spacing-xs) * -1
231
+ );
232
+ max-height: var(--sapphire-global-size-generic-140);
134
233
  }
135
234
 
136
- .sapphire-toast--exiting {
137
- animation-name: fade-out;
138
- animation-fill-mode: forwards;
235
+ .sapphire-toast-container--bottom .sapphire-toast.sapphire-toast--stacked,
236
+ .sapphire-toast-container--bottom-left .sapphire-toast.sapphire-toast--stacked,
237
+ .sapphire-toast-container--bottom-right
238
+ .sapphire-toast.sapphire-toast--stacked {
239
+ top: 0;
240
+ }
241
+
242
+ .sapphire-toast-container--top .sapphire-toast.sapphire-toast--stacked,
243
+ .sapphire-toast-container--top-left .sapphire-toast.sapphire-toast--stacked,
244
+ .sapphire-toast-container--top-right .sapphire-toast.sapphire-toast--stacked {
245
+ bottom: 0;
246
+ }
247
+
248
+ .sapphire-toast--stacked .sapphire-toast__text-content {
249
+ visibility: hidden;
250
+ }
251
+
252
+ .sapphire-toast--stacked::after {
253
+ content: '';
254
+ position: absolute;
255
+ inset: 0;
256
+ background: var(--sapphire-semantic-color-background-surface);
257
+ opacity: calc(var(--sapphire-toast-index) * 0.2);
139
258
  }
140
259
 
141
260
  .sapphire-toast__content {
@@ -160,6 +279,7 @@
160
279
  flex: 1;
161
280
  justify-content: center;
162
281
  padding: var(--sapphire-semantic-size-spacing-2xs);
282
+ overflow: hidden;
163
283
  }
164
284
 
165
285
  .sapphire-toast__text-content > :nth-child(1 of :not(:only-child)) {
@@ -1,4 +1,9 @@
1
1
  declare const styles: {
2
+ readonly "sapphire-toast-view-transition--reverse": string;
3
+ readonly "sapphire-toast-view-transition": string;
4
+ readonly "slide-in": string;
5
+ readonly "slide-out": string;
6
+ readonly "sapphire-toast": string;
2
7
  readonly "sapphire-toast-container": string;
3
8
  readonly "sapphire-toast-container--bottom": string;
4
9
  readonly "sapphire-toast-container--bottom-left": string;
@@ -6,14 +11,16 @@ declare const styles: {
6
11
  readonly "sapphire-toast-container--top": string;
7
12
  readonly "sapphire-toast-container--top-left": string;
8
13
  readonly "sapphire-toast-container--top-right": string;
9
- readonly "sapphire-toast": string;
10
- readonly "sapphire-toast--entering": string;
11
- readonly "fade-in": string;
12
- readonly "sapphire-toast--queued": string;
13
- readonly "sapphire-toast--exiting": string;
14
- readonly "fade-out": string;
15
- readonly "sapphire-toast__content": string;
14
+ readonly "sapphire-toast-list--expanded": string;
15
+ readonly "sapphire-toast-list": string;
16
+ readonly "sapphire-toast-list--collapsed": string;
17
+ readonly "js-hover": string;
18
+ readonly "is-hover": string;
19
+ readonly "js-focus": string;
20
+ readonly "is-focus": string;
21
+ readonly "sapphire-toast--stacked": string;
16
22
  readonly "sapphire-toast__text-content": string;
23
+ readonly "sapphire-toast__content": string;
17
24
  readonly "sapphire-toast__content--success": string;
18
25
  readonly "sapphire-toast__content--error": string;
19
26
  readonly "sapphire-toast__title--with-icon": string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danske/sapphire-css",
3
- "version": "48.0.1",
3
+ "version": "49.1.0",
4
4
  "description": "CSS implementation of the Sapphire Design System from Danske Bank A/S",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "sideEffects": false,
@@ -36,8 +36,8 @@
36
36
  "build:storybook": "cross-env NODE_OPTIONS=--openssl-legacy-provider build-storybook --docs -o dist",
37
37
  "build:types": "tcm -p /**/*.module.css",
38
38
  "build:themes": "yarn build:themes:esm && yarn build:themes:cjs",
39
- "build:themes:esm": "tsc --module ES2020 --outDir build/themes/esm && tsc --module ES2020 --outDir themes",
40
- "build:themes:cjs": "tsc --module CommonJS --outDir build/themes/cjs && tsc --module CommonJS",
39
+ "build:themes:esm": "tsc -p tsconfig.themes.json --module ES2020 --outDir build/themes/esm && tsc -p tsconfig.themes.json --module ES2020 --outDir themes",
40
+ "build:themes:cjs": "tsc -p tsconfig.themes.json --module CommonJS --outDir build/themes/cjs && tsc -p tsconfig.themes.json --module CommonJS",
41
41
  "prepare": "yarn run build"
42
42
  },
43
43
  "devDependencies": {
@@ -67,7 +67,7 @@
67
67
  "typescript": "~4.6.4"
68
68
  },
69
69
  "dependencies": {
70
- "@danske/sapphire-design-tokens": "^42.2.1"
70
+ "@danske/sapphire-design-tokens": "^42.3.0"
71
71
  },
72
- "gitHead": "62297801a42339d31b5099ad337f29fc5ebd7391"
72
+ "gitHead": "88e11202ab17bb9830ba1f261d631ab24edf57d2"
73
73
  }