@cloudscape-design/components-themeable 3.0.188 → 3.0.190
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/lib/internal/manifest.json +1 -1
- package/lib/internal/scss/flashbar/collapsible.motion.scss +23 -0
- package/lib/internal/scss/flashbar/collapsible.scss +224 -0
- package/lib/internal/scss/flashbar/motion.scss +1 -2
- package/lib/internal/scss/flashbar/styles.scss +12 -147
- package/lib/internal/template/flashbar/collapsible-flashbar.d.ts +4 -0
- package/lib/internal/template/flashbar/collapsible-flashbar.d.ts.map +1 -0
- package/lib/internal/template/flashbar/collapsible-flashbar.js +209 -0
- package/lib/internal/template/flashbar/collapsible-flashbar.js.map +1 -0
- package/lib/internal/template/flashbar/common.d.ts +19 -0
- package/lib/internal/template/flashbar/common.d.ts.map +1 -0
- package/lib/internal/template/flashbar/common.js +63 -0
- package/lib/internal/template/flashbar/common.js.map +1 -0
- package/lib/internal/template/flashbar/flash.d.ts.map +1 -1
- package/lib/internal/template/flashbar/flash.js +8 -3
- package/lib/internal/template/flashbar/flash.js.map +1 -1
- package/lib/internal/template/flashbar/index.d.ts +2 -2
- package/lib/internal/template/flashbar/index.d.ts.map +1 -1
- package/lib/internal/template/flashbar/index.js +14 -159
- package/lib/internal/template/flashbar/index.js.map +1 -1
- package/lib/internal/template/flashbar/interfaces.d.ts +14 -7
- package/lib/internal/template/flashbar/interfaces.d.ts.map +1 -1
- package/lib/internal/template/flashbar/interfaces.js.map +1 -1
- package/lib/internal/template/flashbar/internal/analytics.d.ts +5 -0
- package/lib/internal/template/flashbar/internal/analytics.d.ts.map +1 -0
- package/lib/internal/template/flashbar/internal/analytics.js +29 -0
- package/lib/internal/template/flashbar/internal/analytics.js.map +1 -0
- package/lib/internal/template/flashbar/non-collapsible-flashbar.d.ts +4 -0
- package/lib/internal/template/flashbar/non-collapsible-flashbar.d.ts.map +1 -0
- package/lib/internal/template/flashbar/non-collapsible-flashbar.js +70 -0
- package/lib/internal/template/flashbar/non-collapsible-flashbar.js.map +1 -0
- package/lib/internal/template/flashbar/styles.css.js +43 -33
- package/lib/internal/template/flashbar/styles.scoped.css +329 -225
- package/lib/internal/template/flashbar/styles.selectors.js +43 -33
- package/lib/internal/template/flashbar/utils.d.ts +17 -0
- package/lib/internal/template/flashbar/utils.d.ts.map +1 -0
- package/lib/internal/template/flashbar/utils.js +95 -0
- package/lib/internal/template/flashbar/utils.js.map +1 -0
- package/lib/internal/template/internal/animate.d.ts +11 -0
- package/lib/internal/template/internal/animate.d.ts.map +1 -0
- package/lib/internal/template/internal/animate.js +104 -0
- package/lib/internal/template/internal/animate.js.map +1 -0
- package/lib/internal/template/internal/base-component/styles.scoped.css +25 -0
- package/lib/internal/template/internal/environment.js +1 -1
- package/lib/internal/template/internal/generated/styles/tokens.d.ts +4 -1
- package/lib/internal/template/internal/generated/styles/tokens.js +4 -1
- package/lib/internal/template/internal/generated/theming/index.cjs +72 -1
- package/lib/internal/template/internal/generated/theming/index.js +72 -1
- package/package.json +1 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
@use '../internal/styles' as styles;
|
|
6
|
+
@use '../internal/styles/tokens' as tokens;
|
|
7
|
+
|
|
8
|
+
.stack {
|
|
9
|
+
> .animation-running > .item,
|
|
10
|
+
> .animation-running > .flash-list-item,
|
|
11
|
+
> .animation-running.toggle {
|
|
12
|
+
@include styles.with-motion {
|
|
13
|
+
transition-timing-function: tokens.$motion-easing-refresh-only-a;
|
|
14
|
+
transition-duration: tokens.$motion-duration-refresh-only-fast;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
> .collapsed.animation-ready > .expanded-only,
|
|
18
|
+
> .collapsed.animation-running > .expanded-only {
|
|
19
|
+
// When collapsing, hide the exiting items right away, otherwise our animation calculations will be off
|
|
20
|
+
// because of React Transition keeping the elements in the DOM for a bit longer.
|
|
21
|
+
display: none;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
@use '../internal/generated/custom-css-properties/index.scss' as custom-props;
|
|
6
|
+
@use '../internal/hooks/focus-visible' as focus-visible;
|
|
7
|
+
@use '../internal/styles/tokens' as awsui;
|
|
8
|
+
@use '../internal/styles' as styles;
|
|
9
|
+
@use '../internal/styles/typography' as typography;
|
|
10
|
+
@use './collapsible.motion';
|
|
11
|
+
|
|
12
|
+
.stack {
|
|
13
|
+
display: grid;
|
|
14
|
+
grid-template-columns: 1fr minmax(70px, auto) 1fr;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.stack > .expanded {
|
|
18
|
+
grid-column: 1 / 4;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@mixin stacked-flash-z-index {
|
|
22
|
+
// The first item should have the highest z index than the second item, and so forth...
|
|
23
|
+
z-index: calc(var(#{custom-props.$flashbarStackDepth}) - var(#{custom-props.$flashbarStackIndex}));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/*
|
|
27
|
+
The collapsed stack is a dynamic grid that creates the necessary number of
|
|
28
|
+
rows and columns based on the number of items passed to CSS via the
|
|
29
|
+
`flashbarStackDepth` custom property. Assuming there are three flashbar items,
|
|
30
|
+
the grid layout will be:
|
|
31
|
+
|
|
32
|
+
[item 1 start] [10px] [10px] [fractional unit] [10px] [10px] [item 1 end]
|
|
33
|
+
[10px] [item 2 start] [10px] [fractional unit] [10px] [item 2 end] [10px]
|
|
34
|
+
[10px] [10px] [item 3 start] [fractional unit] [item 3 end] [10px] [10px]
|
|
35
|
+
*/
|
|
36
|
+
.stack > .collapsed {
|
|
37
|
+
display: grid;
|
|
38
|
+
grid-column: 1 / 4;
|
|
39
|
+
grid-template-columns:
|
|
40
|
+
repeat(var(#{custom-props.$flashbarStackDepth}), 10px)
|
|
41
|
+
1fr
|
|
42
|
+
repeat(var(#{custom-props.$flashbarStackDepth}), 10px);
|
|
43
|
+
row-gap: 8px;
|
|
44
|
+
z-index: 0;
|
|
45
|
+
|
|
46
|
+
> .item {
|
|
47
|
+
// Each item will have a unique custom property `flashbarStackIndex`
|
|
48
|
+
// Add +1 is because the array is indexed at zero but grid positions are indexed at 1.
|
|
49
|
+
grid-column-start: calc(var(#{custom-props.$flashbarStackIndex}) + 1);
|
|
50
|
+
|
|
51
|
+
// Add +1 to include the fractional unit in the column count
|
|
52
|
+
// Add +1 because the array indexed at zero but grid positions at indexed at 1.
|
|
53
|
+
grid-column-end: calc(
|
|
54
|
+
var(#{custom-props.$flashbarStackDepth}) * 2 + 1 - var(#{custom-props.$flashbarStackIndex}) + 1
|
|
55
|
+
);
|
|
56
|
+
grid-row-start: 1;
|
|
57
|
+
grid-row-end: calc(var(#{custom-props.$flashbarStackIndex}) + 2);
|
|
58
|
+
|
|
59
|
+
@include stacked-flash-z-index;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
> .item:not(:first-of-type) {
|
|
63
|
+
align-self: end;
|
|
64
|
+
/* Give placeholder elements in the stacked state the height of a notification
|
|
65
|
+
with one single line of text.
|
|
66
|
+
This makes them look better during the collapse animation, in which they are already empty.
|
|
67
|
+
*/
|
|
68
|
+
min-height: calc(
|
|
69
|
+
#{awsui.$font-body-m-line-height} + (
|
|
70
|
+
#{awsui.$space-scaled-xs} + #{awsui.$border-field-width} + #{awsui.$space-scaled-xxs}
|
|
71
|
+
) * 2
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
> .item:not(:last-child) > .flash,
|
|
76
|
+
> .item.flash {
|
|
77
|
+
box-shadow: awsui.$shadow-flash-collapsed;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.stack > .expanded.animation-running > .flash-list-item {
|
|
82
|
+
position: relative;
|
|
83
|
+
@include stacked-flash-z-index;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@mixin toggle-button-layout($top-overlap-collapsed, $border-width) {
|
|
87
|
+
$margin-top-when-collapsed: -$top-overlap-collapsed;
|
|
88
|
+
$line-height: awsui.$font-body-m-line-height;
|
|
89
|
+
$padding-vertical: styles.$control-padding-vertical;
|
|
90
|
+
$margin-top-when-expanded: -12px;
|
|
91
|
+
|
|
92
|
+
padding-top: $padding-vertical;
|
|
93
|
+
padding-bottom: $padding-vertical;
|
|
94
|
+
|
|
95
|
+
&:not(.expanded) {
|
|
96
|
+
margin-top: #{$margin-top-when-collapsed};
|
|
97
|
+
margin-bottom: calc(
|
|
98
|
+
#{-$margin-top-when-collapsed} - (#{$line-height} + 2 * (#{$padding-vertical} + #{$border-width}))
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
&.expanded {
|
|
103
|
+
margin-top: #{$margin-top-when-expanded};
|
|
104
|
+
margin-bottom: calc(
|
|
105
|
+
#{-$margin-top-when-expanded} - (#{$line-height} + 2 * (#{$padding-vertical} + #{$border-width}))
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.stack > .toggle {
|
|
111
|
+
@include styles.text-wrapping;
|
|
112
|
+
|
|
113
|
+
background: awsui.$color-background-layout-toggle-default;
|
|
114
|
+
border-color: awsui.$color-background-layout-toggle-default;
|
|
115
|
+
border-radius: awsui.$border-radius-button;
|
|
116
|
+
border-style: solid;
|
|
117
|
+
box-shadow: awsui.$shadow-panel-toggle;
|
|
118
|
+
color: awsui.$color-text-layout-toggle;
|
|
119
|
+
cursor: pointer;
|
|
120
|
+
display: flex;
|
|
121
|
+
grid-column: 2;
|
|
122
|
+
grid-row: 2;
|
|
123
|
+
gap: awsui.$space-xs;
|
|
124
|
+
letter-spacing: awsui.$font-button-letter-spacing;
|
|
125
|
+
margin-left: auto;
|
|
126
|
+
margin-right: auto;
|
|
127
|
+
text-decoration: none;
|
|
128
|
+
z-index: 1;
|
|
129
|
+
|
|
130
|
+
> .status > .header,
|
|
131
|
+
> .status > .item-count,
|
|
132
|
+
> .button {
|
|
133
|
+
@include typography.default-text-style;
|
|
134
|
+
color: awsui.$color-text-layout-toggle;
|
|
135
|
+
cursor: pointer;
|
|
136
|
+
margin-top: 0;
|
|
137
|
+
margin-bottom: 0;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
> .status {
|
|
141
|
+
> .header {
|
|
142
|
+
font-weight: awsui.$font-button-weight;
|
|
143
|
+
display: inline;
|
|
144
|
+
margin-right: awsui.$space-s;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
> .item-count {
|
|
148
|
+
margin-left: awsui.$space-xxs;
|
|
149
|
+
|
|
150
|
+
> .type-count {
|
|
151
|
+
margin-right: awsui.$space-s;
|
|
152
|
+
|
|
153
|
+
> .count-number {
|
|
154
|
+
margin-left: awsui.$space-xxs;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
&:hover {
|
|
161
|
+
background: awsui.$color-background-layout-toggle-hover;
|
|
162
|
+
border-color: awsui.$color-background-layout-toggle-hover;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
&:active {
|
|
166
|
+
background: awsui.$color-background-layout-toggle-active;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
&.visual-refresh {
|
|
170
|
+
$border-width: 2px;
|
|
171
|
+
// Amount of pixels that the element is pushed up to overlap the Flashbar (when collapsed)
|
|
172
|
+
$top-overlap-collapsed: 27px;
|
|
173
|
+
@include toggle-button-layout($top-overlap-collapsed, $border-width);
|
|
174
|
+
border-width: $border-width;
|
|
175
|
+
padding-left: awsui.$space-l;
|
|
176
|
+
padding-right: awsui.$space-l;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
&:not(.visual-refresh) {
|
|
180
|
+
$border-width: 1px;
|
|
181
|
+
// Amount of pixels that the element is pushed up to overlap the Flashbar (when collapsed)
|
|
182
|
+
$top-overlap-collapsed: 24px;
|
|
183
|
+
@include toggle-button-layout($top-overlap-collapsed, $border-width);
|
|
184
|
+
border-width: $border-width;
|
|
185
|
+
padding-left: awsui.$space-s;
|
|
186
|
+
padding-right: awsui.$space-s;
|
|
187
|
+
|
|
188
|
+
&:focus {
|
|
189
|
+
text-decoration: none;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
&:hover {
|
|
193
|
+
text-decoration: none;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
> .button {
|
|
198
|
+
display: inline-block;
|
|
199
|
+
background: none;
|
|
200
|
+
border: 0 none;
|
|
201
|
+
|
|
202
|
+
> .icon {
|
|
203
|
+
@include styles.with-motion {
|
|
204
|
+
transition: transform awsui.$motion-duration-rotate-90 awsui.$motion-easing-rotate-90;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
&.expanded > .icon {
|
|
208
|
+
transform: rotate(180deg);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
&:focus {
|
|
212
|
+
outline: none;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
@include focus-visible.when-visible {
|
|
216
|
+
@include styles.focus-highlight(0px);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Leave some space below the Flashbar, but only when it reaches the end of the page.
|
|
222
|
+
.stack.spaced-bottom {
|
|
223
|
+
padding-bottom: awsui.$space-xxl;
|
|
224
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
@use '../internal/styles' as styles;
|
|
7
7
|
@use '../internal/styles/tokens' as tokens;
|
|
8
|
-
.flash-
|
|
8
|
+
.flash-with-motion {
|
|
9
9
|
$flashbar-translate-y-content: -8px;
|
|
10
10
|
$flashbar-translate-y: -20px;
|
|
11
11
|
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
$flash-button-wrapper-transition-delay: calc(tokens.$motion-duration-refresh-only-slow * 2 - 100ms);
|
|
16
16
|
|
|
17
17
|
&.enter {
|
|
18
|
-
position: absolute;
|
|
19
18
|
@include styles.with-motion {
|
|
20
19
|
opacity: 0;
|
|
21
20
|
transform: translateY($flashbar-translate-y);
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
@use '../internal/hooks/focus-visible' as focus-visible;
|
|
7
7
|
@use '../internal/styles/tokens' as awsui;
|
|
8
8
|
@use '../internal/styles' as styles;
|
|
9
|
+
@use '../internal/styles/typography' as typography;
|
|
9
10
|
@use './motion';
|
|
11
|
+
@use './collapsible';
|
|
10
12
|
|
|
11
13
|
.flashbar {
|
|
12
14
|
position: relative;
|
|
@@ -53,8 +55,10 @@
|
|
|
53
55
|
padding: 0;
|
|
54
56
|
margin: 0;
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
&:not(.collapsed) {
|
|
59
|
+
> li:not(:last-child) {
|
|
60
|
+
margin-bottom: awsui.$space-xxxs;
|
|
61
|
+
}
|
|
58
62
|
}
|
|
59
63
|
}
|
|
60
64
|
|
|
@@ -62,22 +66,21 @@
|
|
|
62
66
|
display: flex;
|
|
63
67
|
flex-grow: 1;
|
|
64
68
|
min-width: 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.flash-focus-container {
|
|
72
|
+
display: flex;
|
|
73
|
+
flex: 1;
|
|
74
|
+
min-width: 0;
|
|
65
75
|
|
|
66
76
|
&:focus {
|
|
67
77
|
outline: none;
|
|
68
78
|
}
|
|
69
|
-
|
|
70
79
|
@include focus-visible.when-visible {
|
|
71
80
|
@include styles.focus-highlight(awsui.$space-button-focus-outline-gutter);
|
|
72
81
|
}
|
|
73
82
|
}
|
|
74
83
|
|
|
75
|
-
.flash-focus-container {
|
|
76
|
-
display: flex;
|
|
77
|
-
flex: 1;
|
|
78
|
-
min-width: 0;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
84
|
.flash-text {
|
|
82
85
|
margin: awsui.$border-field-width 0;
|
|
83
86
|
padding: awsui.$space-scaled-xxs awsui.$space-xxs;
|
|
@@ -145,141 +148,3 @@
|
|
|
145
148
|
.flash-type-info {
|
|
146
149
|
background-color: awsui.$color-background-notification-blue;
|
|
147
150
|
}
|
|
148
|
-
|
|
149
|
-
// `stackItems` feature beta test
|
|
150
|
-
|
|
151
|
-
.stack {
|
|
152
|
-
display: grid;
|
|
153
|
-
grid-template-columns: 1fr minmax(70px, auto) 1fr;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
.stack > .expanded {
|
|
157
|
-
grid-column: 1 / 4;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/*
|
|
161
|
-
The collapsed stack is a dynamic grid that creates the necessary number of
|
|
162
|
-
rows and columns based on the number of items passed to CSS via the
|
|
163
|
-
`flashbarStackDepth` custom property. Assuming there are three flashbar items,
|
|
164
|
-
the grid layout will be:
|
|
165
|
-
|
|
166
|
-
[item 1 start] [12px] [12px] [fractional unit] [12px] [12px] [item 1 end]
|
|
167
|
-
[12px] [item 2 start] [12px] [fractional unit] [12px] [item 2 end] [12px]
|
|
168
|
-
[12px] [12px] [item 3 start] [fractional unit] [item 3 end] [12px] [12px]
|
|
169
|
-
*/
|
|
170
|
-
.stack > .collapsed {
|
|
171
|
-
display: grid;
|
|
172
|
-
grid-column: 1 / 4;
|
|
173
|
-
grid-template-columns:
|
|
174
|
-
repeat(var(#{custom-props.$flashbarStackDepth}), 12px)
|
|
175
|
-
1fr
|
|
176
|
-
repeat(var(#{custom-props.$flashbarStackDepth}), 12px);
|
|
177
|
-
row-gap: 8px;
|
|
178
|
-
|
|
179
|
-
> .item {
|
|
180
|
-
// Each item will have a unique custom property `flashbarStackIndex`
|
|
181
|
-
// Add +1 is because the array is indexed at zero but grid positions are indexed at 1.
|
|
182
|
-
grid-column-start: calc(var(#{custom-props.$flashbarStackIndex}) + 1);
|
|
183
|
-
|
|
184
|
-
// Add +1 to include the fractional unit in the column count
|
|
185
|
-
// Add +1 because the array indexed at zero but grid positions at indexed at 1.
|
|
186
|
-
grid-column-end: calc(
|
|
187
|
-
var(#{custom-props.$flashbarStackDepth}) * 2 + 1 - var(#{custom-props.$flashbarStackIndex}) + 1
|
|
188
|
-
);
|
|
189
|
-
grid-row-start: 1;
|
|
190
|
-
grid-row-end: calc(var(#{custom-props.$flashbarStackIndex}) + 2);
|
|
191
|
-
|
|
192
|
-
// The first item should have the highest z index than the second item, and so forth...
|
|
193
|
-
z-index: calc(var(#{custom-props.$flashbarStackDepth}) - var(#{custom-props.$flashbarStackIndex}));
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
> .item:not(:first-of-type) {
|
|
197
|
-
align-self: end;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
&.visual-refresh > .item:not(:last-of-type) > .flash {
|
|
201
|
-
box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
&:not(.visual-refresh) > .item:not(:last-of-type) > .flash {
|
|
205
|
-
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.15);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
&.visual-refresh > .item:not(:last-of-type) > .flash-items > li:first-child > .flash {
|
|
209
|
-
box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
&:not(.visual-refresh) > .item:not(:last-of-type) > .flash-items > li:first-child > .flash {
|
|
213
|
-
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.15);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
.stack > .toggle {
|
|
218
|
-
grid-column: 2;
|
|
219
|
-
grid-row: 2;
|
|
220
|
-
|
|
221
|
-
@include focus-visible.when-visible {
|
|
222
|
-
@include styles.focus-highlight(awsui.$space-button-focus-outline-gutter);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
&.visual-refresh {
|
|
226
|
-
background: awsui.$color-background-layout-toggle-default;
|
|
227
|
-
border: none;
|
|
228
|
-
border-radius: 0 0 10px 10px;
|
|
229
|
-
box-shadow: awsui.$shadow-panel-toggle;
|
|
230
|
-
color: awsui.$color-text-layout-toggle;
|
|
231
|
-
cursor: pointer;
|
|
232
|
-
padding: awsui.$space-scaled-xxs;
|
|
233
|
-
z-index: var(#{custom-props.$flashbarStackDepth});
|
|
234
|
-
|
|
235
|
-
&:focus {
|
|
236
|
-
outline: none;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
&:hover {
|
|
240
|
-
background: awsui.$color-background-layout-toggle-hover;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
&:active {
|
|
244
|
-
background: awsui.$color-background-layout-toggle-active;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
&:not(.visual-refresh) {
|
|
249
|
-
background: awsui.$color-background-button-normal-default;
|
|
250
|
-
border: styles.$control-border-width solid awsui.$color-border-button-normal-default;
|
|
251
|
-
border-radius: awsui.$border-radius-button;
|
|
252
|
-
border-top: none;
|
|
253
|
-
cursor: pointer;
|
|
254
|
-
padding: styles.$control-padding-vertical awsui.$space-l;
|
|
255
|
-
text-decoration: none;
|
|
256
|
-
|
|
257
|
-
&:focus {
|
|
258
|
-
outline: none;
|
|
259
|
-
text-decoration: none;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
&:hover {
|
|
263
|
-
background: awsui.$color-background-button-normal-hover;
|
|
264
|
-
border-color: awsui.$color-border-button-normal-hover;
|
|
265
|
-
text-decoration: none;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
&:active {
|
|
269
|
-
background: awsui.$color-background-button-normal-active;
|
|
270
|
-
border-color: awsui.$color-border-button-normal-active;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
> .icon {
|
|
275
|
-
display: inline-block;
|
|
276
|
-
|
|
277
|
-
@include styles.with-motion {
|
|
278
|
-
transition: transform awsui.$motion-duration-rotate-90 awsui.$motion-easing-rotate-90;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
&.expanded {
|
|
282
|
-
transform: rotate(180deg);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { FlashbarProps, CollapsibleFlashbarProps } from './interfaces';
|
|
2
|
+
export { FlashbarProps };
|
|
3
|
+
export default function CollapsibleFlashbar({ items, ...restProps }: FlashbarProps & CollapsibleFlashbarProps): JSX.Element;
|
|
4
|
+
//# sourceMappingURL=collapsible-flashbar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collapsible-flashbar.d.ts","sourceRoot":"","sources":["../../../src/flashbar/collapsible-flashbar.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAgBvE,OAAO,EAAE,aAAa,EAAE,CAAC;AAQzB,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,EAAE,KAAK,EAAE,GAAG,SAAS,EAAE,EAAE,aAAa,GAAG,wBAAwB,eA2S5G"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { __assign, __rest, __spreadArray } from "tslib";
|
|
2
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
import clsx from 'clsx';
|
|
5
|
+
import React, { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
6
|
+
import customCssProps from '../internal/generated/custom-css-properties';
|
|
7
|
+
import { Flash, focusFlashById } from './flash';
|
|
8
|
+
import InternalIcon from '../icon/internal';
|
|
9
|
+
import { TransitionGroup } from 'react-transition-group';
|
|
10
|
+
import { Transition } from '../internal/components/transition';
|
|
11
|
+
import useFocusVisible from '../internal/hooks/focus-visible';
|
|
12
|
+
import { getVisualContextClassname } from '../internal/components/visual-context';
|
|
13
|
+
import styles from './styles.css.js';
|
|
14
|
+
import { counterTypes, getFlashTypeCount, getVisibleCollapsedItems } from './utils';
|
|
15
|
+
import { animate, getDOMRects } from '../internal/animate';
|
|
16
|
+
import { useUniqueId } from '../internal/hooks/use-unique-id';
|
|
17
|
+
import { sendToggleMetric } from './internal/analytics';
|
|
18
|
+
import { useFlashbar } from './common';
|
|
19
|
+
import { throttle } from '../internal/utils/throttle';
|
|
20
|
+
// If the number of items is equal or less than this value,
|
|
21
|
+
// the toggle element will not be displayed and the Flashbar will look like a regular single-item Flashbar.
|
|
22
|
+
var maxNonCollapsibleItems = 1;
|
|
23
|
+
var resizeListenerThrottleDelay = 100;
|
|
24
|
+
export default function CollapsibleFlashbar(_a) {
|
|
25
|
+
var items = _a.items, restProps = __rest(_a, ["items"]);
|
|
26
|
+
var _b = useState([]), enteringItems = _b[0], setEnteringItems = _b[1];
|
|
27
|
+
var _c = useState([]), exitingItems = _c[0], setExitingItems = _c[1];
|
|
28
|
+
var _d = useState(false), isFlashbarStackExpanded = _d[0], setIsFlashbarStackExpanded = _d[1];
|
|
29
|
+
var getElementsToAnimate = useCallback(function () {
|
|
30
|
+
var flashElements = isFlashbarStackExpanded ? expandedItemRefs.current : collapsedItemRefs.current;
|
|
31
|
+
return __assign(__assign({}, flashElements), { toggleButton: toggleElementRef.current });
|
|
32
|
+
}, [isFlashbarStackExpanded]);
|
|
33
|
+
var prepareAnimations = useCallback(function () {
|
|
34
|
+
var rects = getDOMRects(getElementsToAnimate());
|
|
35
|
+
setInitialAnimationState(rects);
|
|
36
|
+
}, [getElementsToAnimate]);
|
|
37
|
+
var _e = useFlashbar(__assign(__assign({ items: items }, restProps), { onItemsAdded: function (newItems) {
|
|
38
|
+
setEnteringItems(__spreadArray(__spreadArray([], enteringItems, true), newItems, true));
|
|
39
|
+
}, onItemsChanged: function (options) {
|
|
40
|
+
// If not all items have ID, we can still animate collapse/expand transitions
|
|
41
|
+
// because we can rely on each item's index in the original array,
|
|
42
|
+
// but we can't do that when elements are added or removed, since the index changes.
|
|
43
|
+
if ((options === null || options === void 0 ? void 0 : options.allItemsHaveId) && !(options === null || options === void 0 ? void 0 : options.isReducedMotion)) {
|
|
44
|
+
prepareAnimations();
|
|
45
|
+
}
|
|
46
|
+
}, onItemsRemoved: function (removedItems) {
|
|
47
|
+
setExitingItems(__spreadArray(__spreadArray([], exitingItems, true), removedItems, true));
|
|
48
|
+
} })), baseProps = _e.baseProps, breakpoint = _e.breakpoint, isReducedMotion = _e.isReducedMotion, isVisualRefresh = _e.isVisualRefresh, mergedRef = _e.mergedRef, ref = _e.ref;
|
|
49
|
+
var isFocusVisible = useFocusVisible();
|
|
50
|
+
var collapsedItemRefs = useRef({});
|
|
51
|
+
var expandedItemRefs = useRef({});
|
|
52
|
+
var _f = useState(null), initialAnimationState = _f[0], setInitialAnimationState = _f[1];
|
|
53
|
+
var listElementRef = useRef(null);
|
|
54
|
+
var toggleElementRef = useRef(null);
|
|
55
|
+
var _g = useState(false), transitioning = _g[0], setTransitioning = _g[1];
|
|
56
|
+
var flashbarElementId = useUniqueId('flashbar');
|
|
57
|
+
var itemCountElementId = useUniqueId('item-count');
|
|
58
|
+
if (items.length <= maxNonCollapsibleItems && isFlashbarStackExpanded) {
|
|
59
|
+
setIsFlashbarStackExpanded(false);
|
|
60
|
+
}
|
|
61
|
+
var animateFlash = !isReducedMotion;
|
|
62
|
+
function toggleCollapseExpand() {
|
|
63
|
+
sendToggleMetric(items.length, !isFlashbarStackExpanded);
|
|
64
|
+
if (!isReducedMotion) {
|
|
65
|
+
prepareAnimations();
|
|
66
|
+
}
|
|
67
|
+
setIsFlashbarStackExpanded(function (prev) { return !prev; });
|
|
68
|
+
}
|
|
69
|
+
useLayoutEffect(function () {
|
|
70
|
+
if (isFlashbarStackExpanded && (items === null || items === void 0 ? void 0 : items.length)) {
|
|
71
|
+
var lastItem = items[items.length - 1];
|
|
72
|
+
if (lastItem.id !== undefined) {
|
|
73
|
+
focusFlashById(ref.current, lastItem.id);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Run this after expanding, but not every time the items change.
|
|
77
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
78
|
+
}, [isFlashbarStackExpanded]);
|
|
79
|
+
var updateBottomSpacing = useMemo(function () {
|
|
80
|
+
return throttle(function () {
|
|
81
|
+
// Allow vertical space between Flashbar and page bottom only when the Flashbar is reaching the end of the page,
|
|
82
|
+
// otherwise avoid spacing with eventual sticky elements below.
|
|
83
|
+
var listElement = listElementRef === null || listElementRef === void 0 ? void 0 : listElementRef.current;
|
|
84
|
+
var flashbar = listElement === null || listElement === void 0 ? void 0 : listElement.parentElement;
|
|
85
|
+
if (listElement && flashbar) {
|
|
86
|
+
var bottom = listElement.getBoundingClientRect().bottom;
|
|
87
|
+
var windowHeight = window.innerHeight;
|
|
88
|
+
// Apply the class first (before rendering)
|
|
89
|
+
// so that we can make calculations based on the applied padding-bottom;
|
|
90
|
+
// then we might decide to remove it or not.
|
|
91
|
+
flashbar.classList.add(styles['spaced-bottom']);
|
|
92
|
+
var applySpacing = isFlashbarStackExpanded && bottom + parseInt(getComputedStyle(flashbar).paddingBottom) >= windowHeight;
|
|
93
|
+
if (!applySpacing) {
|
|
94
|
+
flashbar.classList.remove(styles['spaced-bottom']);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}, resizeListenerThrottleDelay);
|
|
98
|
+
}, [isFlashbarStackExpanded]);
|
|
99
|
+
useLayoutEffect(function () {
|
|
100
|
+
window.addEventListener('resize', updateBottomSpacing);
|
|
101
|
+
return function () {
|
|
102
|
+
window.removeEventListener('resize', updateBottomSpacing);
|
|
103
|
+
updateBottomSpacing.cancel();
|
|
104
|
+
};
|
|
105
|
+
}, [updateBottomSpacing]);
|
|
106
|
+
var i18nStrings = restProps.i18nStrings;
|
|
107
|
+
useLayoutEffect(function () {
|
|
108
|
+
// When `useLayoutEffect` is called, the DOM is updated but has not been painted yet,
|
|
109
|
+
// so it's a good moment to trigger animations that will make calculations based on old and new DOM state.
|
|
110
|
+
// The old state is kept in `initialAnimationState`
|
|
111
|
+
// and the new state can be retrieved from the current DOM elements.
|
|
112
|
+
if (initialAnimationState) {
|
|
113
|
+
updateBottomSpacing();
|
|
114
|
+
animate({
|
|
115
|
+
elements: getElementsToAnimate(),
|
|
116
|
+
oldState: initialAnimationState,
|
|
117
|
+
newElementInitialState: function (_a) {
|
|
118
|
+
var top = _a.top;
|
|
119
|
+
return ({ scale: 0.9, y: -0.2 * top });
|
|
120
|
+
},
|
|
121
|
+
onTransitionsEnd: function () { return setTransitioning(false); }
|
|
122
|
+
});
|
|
123
|
+
setTransitioning(true);
|
|
124
|
+
setInitialAnimationState(null);
|
|
125
|
+
}
|
|
126
|
+
}, [updateBottomSpacing, getElementsToAnimate, initialAnimationState, isFlashbarStackExpanded]);
|
|
127
|
+
var isCollapsible = items.length > maxNonCollapsibleItems;
|
|
128
|
+
// When using the stacking feature, the items are shown in reverse order (last item on top)
|
|
129
|
+
var reversedItems = items.slice().reverse();
|
|
130
|
+
var countByType = getFlashTypeCount(items);
|
|
131
|
+
var stackDepth = Math.min(3, items.length);
|
|
132
|
+
var itemsToShow = isFlashbarStackExpanded
|
|
133
|
+
? reversedItems.map(function (item, index) { return (__assign(__assign({}, item), { expandedIndex: index })); })
|
|
134
|
+
: getVisibleCollapsedItems(reversedItems, stackDepth).map(function (item, index) { return (__assign(__assign({}, item), { collapsedIndex: index })); });
|
|
135
|
+
var ariaLabel = i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.ariaLabel;
|
|
136
|
+
var toggleButtonText = i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.toggleButtonText;
|
|
137
|
+
var getItemId = function (item) { var _a, _b; return (_b = (_a = item.id) !== null && _a !== void 0 ? _a : item.expandedIndex) !== null && _b !== void 0 ? _b : 0; };
|
|
138
|
+
// This check allows us to use the standard "enter" Transition only when the notification was not existing before.
|
|
139
|
+
// If instead it was moved to the top of the stack but was already present in the array
|
|
140
|
+
// (e.g, after dismissing another notification),
|
|
141
|
+
// we need to use different, more custom and more controlled animations.
|
|
142
|
+
var hasEntered = function (item) {
|
|
143
|
+
return enteringItems.some(function (_item) { return _item.id && _item.id === item.id; });
|
|
144
|
+
};
|
|
145
|
+
var hasLeft = function (item) { return !('expandedIndex' in item); };
|
|
146
|
+
var hasEnteredOrLeft = function (item) { return hasEntered(item) || hasLeft(item); };
|
|
147
|
+
var showInnerContent = function (item) {
|
|
148
|
+
return isFlashbarStackExpanded || hasLeft(item) || ('expandedIndex' in item && item.expandedIndex === 0);
|
|
149
|
+
};
|
|
150
|
+
var shouldUseStandardAnimation = function (item, index) { return index === 0 && hasEnteredOrLeft(item); };
|
|
151
|
+
var getAnimationElementId = function (item) { return "flash-".concat(getItemId(item)); };
|
|
152
|
+
var renderList = function () {
|
|
153
|
+
var _a;
|
|
154
|
+
return (React.createElement("ul", { ref: listElementRef, className: clsx(styles['flash-list'], isFlashbarStackExpanded ? styles.expanded : styles.collapsed, transitioning && styles['animation-running'], initialAnimationState && styles['animation-ready'], isVisualRefresh && styles['visual-refresh']), id: flashbarElementId, "aria-label": ariaLabel, "aria-describedby": isCollapsible ? itemCountElementId : undefined, style: !isFlashbarStackExpanded || transitioning
|
|
155
|
+
? (_a = {},
|
|
156
|
+
_a[customCssProps.flashbarStackDepth] = stackDepth,
|
|
157
|
+
_a) : undefined },
|
|
158
|
+
React.createElement(TransitionGroup, { component: null }, itemsToShow.map(function (item, index) { return (React.createElement(Transition, { key: getItemId(item), "in": !hasLeft(item), onStatusChange: function (status) {
|
|
159
|
+
if (status === 'entered') {
|
|
160
|
+
setEnteringItems([]);
|
|
161
|
+
}
|
|
162
|
+
else if (status === 'exited') {
|
|
163
|
+
setExitingItems([]);
|
|
164
|
+
}
|
|
165
|
+
} }, function (state, transitionRootElement) {
|
|
166
|
+
var _a;
|
|
167
|
+
var _b, _c, _d;
|
|
168
|
+
return (React.createElement("li", { "aria-hidden": !showInnerContent(item), className: showInnerContent(item)
|
|
169
|
+
? clsx(styles['flash-list-item'], !isFlashbarStackExpanded && styles.item, !collapsedItemRefs.current[getAnimationElementId(item)] && styles['expanded-only'])
|
|
170
|
+
: clsx(styles.flash, styles["flash-type-".concat((_b = item.type) !== null && _b !== void 0 ? _b : 'info')], styles.item), ref: function (element) {
|
|
171
|
+
if (isFlashbarStackExpanded) {
|
|
172
|
+
expandedItemRefs.current[getAnimationElementId(item)] = element;
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
collapsedItemRefs.current[getAnimationElementId(item)] = element;
|
|
176
|
+
}
|
|
177
|
+
}, style: !isFlashbarStackExpanded || transitioning
|
|
178
|
+
? (_a = {},
|
|
179
|
+
_a[customCssProps.flashbarStackIndex] = (_d = (_c = item.collapsedIndex) !== null && _c !== void 0 ? _c : item.expandedIndex) !== null && _d !== void 0 ? _d : index,
|
|
180
|
+
_a) : undefined, key: getItemId(item) }, showInnerContent(item) && (React.createElement(Flash
|
|
181
|
+
// eslint-disable-next-line react/forbid-component-props
|
|
182
|
+
, __assign({
|
|
183
|
+
// eslint-disable-next-line react/forbid-component-props
|
|
184
|
+
className: clsx(animateFlash && styles['flash-with-motion'], isVisualRefresh && styles['flash-refresh']), key: getItemId(item), ref: shouldUseStandardAnimation(item, index) ? transitionRootElement : undefined, transitionState: shouldUseStandardAnimation(item, index) ? state : undefined }, item)))));
|
|
185
|
+
})); }))));
|
|
186
|
+
};
|
|
187
|
+
return (React.createElement("div", __assign({}, baseProps, { className: clsx(baseProps.className, styles.flashbar, styles["breakpoint-".concat(breakpoint)], styles.stack, isFlashbarStackExpanded && styles.expanded, getVisualContextClassname('flashbar')), ref: mergedRef }),
|
|
188
|
+
React.createElement(React.Fragment, null,
|
|
189
|
+
isFlashbarStackExpanded && renderList(),
|
|
190
|
+
isCollapsible && (React.createElement("div", { className: clsx(styles.toggle, isVisualRefresh && styles['visual-refresh'], isFlashbarStackExpanded ? styles.expanded : styles.collapsed, transitioning && styles['animation-running']), onClick: toggleCollapseExpand, ref: toggleElementRef },
|
|
191
|
+
React.createElement("span", { "aria-live": "polite", className: styles.status, role: "status", id: itemCountElementId },
|
|
192
|
+
toggleButtonText && React.createElement("h2", { className: styles.header }, toggleButtonText),
|
|
193
|
+
React.createElement("span", { className: styles['item-count'] }, counterTypes.map(function (_a) {
|
|
194
|
+
var type = _a.type, labelName = _a.labelName, iconName = _a.iconName;
|
|
195
|
+
return (React.createElement(NotificationTypeCount, { key: type, iconName: iconName, label: i18nStrings ? i18nStrings[labelName] : undefined, count: countByType[type] }));
|
|
196
|
+
}))),
|
|
197
|
+
React.createElement("button", __assign({ "aria-controls": flashbarElementId, "aria-describedby": itemCountElementId, "aria-expanded": isFlashbarStackExpanded, "aria-label": i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.toggleButtonAriaLabel, className: clsx(styles.button, isFlashbarStackExpanded && styles.expanded) }, isFocusVisible),
|
|
198
|
+
React.createElement(InternalIcon, { className: styles.icon, size: "normal", name: "angle-down" })))),
|
|
199
|
+
!isFlashbarStackExpanded && renderList())));
|
|
200
|
+
}
|
|
201
|
+
var NotificationTypeCount = function (_a) {
|
|
202
|
+
var iconName = _a.iconName, label = _a.label, count = _a.count;
|
|
203
|
+
return (React.createElement("span", { className: styles['type-count'] },
|
|
204
|
+
React.createElement("span", { "aria-label": label, role: "img" },
|
|
205
|
+
React.createElement("span", { title: label, "aria-hidden": "true" },
|
|
206
|
+
React.createElement(InternalIcon, { name: iconName }))),
|
|
207
|
+
React.createElement("span", { className: styles['count-number'] }, count)));
|
|
208
|
+
};
|
|
209
|
+
//# sourceMappingURL=collapsible-flashbar.js.map
|